• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3656

14 Mar 2025 08:10AM UTC coverage: 62.841% (+3.3%) from 59.532%
#3656

push

travis-ci

web-flow
feat(keep): support keep on super table level. (#30097)

* Feat: support use keep while create super table.

* Test(keep): add test for create super table with keep option.

* Feat(keep): Add tmsg for create keep.

* Feat(keep): support alter table option keep.

* Fix(keep): Add baisc test for alter table option.

* Fix(keep): memory leek.

* Feat(keep): add keep to metaEntry&metaCache and fix earliestTs with stn keep.

* Test(keep): add some cases for select with stb keep.

* Fix: fix ci core while alter stb.

* Feat(keep): delete expired data in super table level.

* Feat: remove get stb keep while query.

* Fix : build error.

* Revert "Fix : build error."

This reverts commit 0ed66e4e8.

* Revert "Feat(keep): delete expired data in super table level."

This reverts commit 36330f6b4.

* Fix : build errors.

* Feat : support restart taosd.

* Fix : alter table comment problems.

* Test : add tests for super table keep.

* Fix: change sdb stb reserve size.

* Test: add more tests.

* Feat: Disable normal tables and sub tables from setting the keep parameter

* Fix: add more checks to avoid unknown address.

* Docs: Add docs for stable keep.

* Fix: some review changes.

* Fix: review errors.

147682 of 302527 branches covered (48.82%)

Branch coverage included in aggregate %.

88 of 99 new or added lines in 12 files covered. (88.89%)

3177 existing lines in 34 files now uncovered.

232747 of 302857 relevant lines covered (76.85%)

5880306.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

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

31
#define IS_FINAL_INTERVAL_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL)
32
#define IS_MID_INTERVAL_OP(op)   ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL)
33

34
#define IS_FINAL_SESSION_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION)
35

36
#define DEAULT_DELETE_MARK                 INT64_MAX
37
#define STREAM_INTERVAL_OP_STATE_NAME      "StreamIntervalHistoryState"
38
#define STREAM_SESSION_OP_STATE_NAME       "StreamSessionHistoryState"
39
#define STREAM_STATE_OP_STATE_NAME         "StreamStateHistoryState"
40
#define STREAM_INTERVAL_OP_CHECKPOINT_NAME "StreamIntervalOperator_Checkpoint"
41
#define STREAM_SESSION_OP_CHECKPOINT_NAME  "StreamSessionOperator_Checkpoint"
42
#define STREAM_STATE_OP_CHECKPOINT_NAME    "StreamStateOperator_Checkpoint"
43

44
#define MAX_STREAM_HISTORY_RESULT 20000000
45

46
typedef struct SStateWindowInfo {
47
  SResultWindowInfo winInfo;
48
  SStateKeys*       pStateKey;
49
} SStateWindowInfo;
50

51
typedef struct SPullWindowInfo {
52
  STimeWindow window;
53
  uint64_t    groupId;
54
  STimeWindow calWin;
55
} SPullWindowInfo;
56

57
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes);
58

59
typedef int32_t (*__compare_fn_t)(void* pKey, void* data, int32_t index);
60

61
static int32_t binarySearchCom(void* keyList, int num, void* pKey, int order, __compare_fn_t comparefn) {
1,548✔
62
  int firstPos = 0, lastPos = num - 1, midPos = -1;
1,548✔
63
  int numOfRows = 0;
1,548✔
64

65
  if (num <= 0) return -1;
1,548✔
66
  if (order == TSDB_ORDER_DESC) {
1,345!
67
    // find the first position which is smaller or equal than the key
68
    while (1) {
69
      if (comparefn(pKey, keyList, lastPos) >= 0) return lastPos;
1,447✔
70
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
355✔
71
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
222✔
72

73
      numOfRows = lastPos - firstPos + 1;
175✔
74
      midPos = (numOfRows >> 1) + firstPos;
175✔
75

76
      if (comparefn(pKey, keyList, midPos) < 0) {
175✔
77
        lastPos = midPos - 1;
67✔
78
      } else if (comparefn(pKey, keyList, midPos) > 0) {
108✔
79
        firstPos = midPos + 1;
35✔
80
      } else {
81
        break;
73✔
82
      }
83
    }
84

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

91
      if (comparefn(pKey, keyList, lastPos) > 0) {
×
92
        lastPos = lastPos + 1;
×
93
        if (lastPos >= num)
×
94
          return -1;
×
95
        else
96
          return lastPos;
×
97
      }
98

99
      numOfRows = lastPos - firstPos + 1;
×
100
      midPos = (numOfRows >> 1) + firstPos;
×
101

102
      if (comparefn(pKey, keyList, midPos) < 0) {
×
103
        lastPos = midPos - 1;
×
104
      } else if (comparefn(pKey, keyList, midPos) > 0) {
×
105
        firstPos = midPos + 1;
×
106
      } else {
107
        break;
×
108
      }
109
    }
110
  }
111

112
  return midPos;
73✔
113
}
114

115
static int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
212✔
116
  SArray*          res = (SArray*)data;
212✔
117
  SPullWindowInfo* pos = taosArrayGet(res, index);
212✔
118
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
212✔
119
  if (pData->groupId > pos->groupId) {
212✔
120
    return 1;
95✔
121
  } else if (pData->groupId < pos->groupId) {
117✔
122
    return -1;
62✔
123
  }
124

125
  if (pData->window.skey > pos->window.ekey) {
55✔
126
    return 1;
43✔
127
  } else if (pData->window.ekey < pos->window.skey) {
12✔
128
    return -1;
6✔
129
  }
130
  return 0;
6✔
131
}
132

133
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
209✔
134
  int32_t size = taosArrayGetSize(pPullWins);
209✔
135
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
209✔
136
  if (index == -1) {
209✔
137
    index = 0;
154✔
138
  } else {
139
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
55✔
140
    if (code == 0) {
55✔
141
      SPullWindowInfo* pos = taosArrayGet(pPullWins, index);
3✔
142
      pos->window.skey = TMIN(pos->window.skey, pPullInfo->window.skey);
3✔
143
      pos->window.ekey = TMAX(pos->window.ekey, pPullInfo->window.ekey);
3✔
144
      pos->calWin.skey = TMIN(pos->calWin.skey, pPullInfo->calWin.skey);
3✔
145
      pos->calWin.ekey = TMAX(pos->calWin.ekey, pPullInfo->calWin.ekey);
3✔
146
      return TSDB_CODE_SUCCESS;
3✔
147
    } else if (code > 0) {
52!
148
      index++;
52✔
149
    }
150
  }
151
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
206!
152
    return terrno;
×
153
  }
154
  return TSDB_CODE_SUCCESS;
206✔
155
}
156

157
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
7,299✔
158
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
7,299!
159
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
160
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
161
  }
162
  winInfo.sessionWin.win.ekey = winInfo.sessionWin.win.skey;
7,299✔
163
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
7,299✔
164
}
165

166
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
7,080,947✔
167
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
7,080,947!
168
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
169
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
170
  }
171
  return tSimpleHashPut(pUpdatedMap, pKey, sizeof(SWinKey), &pPos, POINTER_BYTES);
7,080,886✔
172
}
173

174
static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
286✔
175
  SWinKey key = {.ts = ts, .groupId = groupId};
286✔
176
  return saveWinResult(&key, pPos, pUpdatedMap);
286✔
177
}
178

179
static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) {
193✔
180
  int32_t size = taosArrayGetSize(pWins);
193✔
181
  for (int32_t i = 0; i < size; i++) {
428✔
182
    SWinKey* pW = taosArrayGet(pWins, i);
235✔
183
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
235✔
184
    if (tmp) {
235!
185
      void* value = *(void**)tmp;
×
186
      taosMemoryFree(value);
×
187
      int32_t tmpRes = tSimpleHashRemove(pUpdatedMap, pW, sizeof(SWinKey));
×
188
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
×
189
    }
190
  }
191
}
193✔
192

193
static int32_t compareWinKey(void* pKey, void* data, int32_t index) {
3,406✔
194
  void* pDataPos = taosArrayGet((SArray*)data, index);
3,406✔
195
  return winKeyCmprImpl(pKey, pDataPos);
3,406✔
196
}
197

198
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
15,168✔
199
  taosArraySort(pDelWins, winKeyCmprImpl);
15,168✔
200
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
15,170✔
201
  int32_t delSize = taosArrayGetSize(pDelWins);
15,170✔
202
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
15,170✔
203
    return;
14,594✔
204
  }
205
  void*   pIte = NULL;
575✔
206
  int32_t iter = 0;
575✔
207
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,633✔
208
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
1,059✔
209
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
1,059✔
210
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
1,059✔
211
      taosArrayRemove(pDelWins, index);
860✔
212
      delSize = taosArrayGetSize(pDelWins);
860✔
213
    }
214
  }
215
}
216

217
bool isOverdue(TSKEY ekey, STimeWindowAggSupp* pTwSup) {
17,089,237✔
218
  return pTwSup->maxTs != INT64_MIN && ekey < pTwSup->maxTs - pTwSup->waterMark;
17,089,237✔
219
}
220

221
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
7,096,197✔
222

223
static void doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) {
3,349✔
224
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,349✔
225

226
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
3,349✔
227
  SWinKey                      key = {.ts = ts, .groupId = groupId};
3,349✔
228
  int32_t                      tmpRes = tSimpleHashRemove(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey));
3,349✔
229
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,349✔
230
  pAPI->stateStore.streamStateDel(pInfo->pState, &key);
3,349✔
231
}
3,348✔
232

233
static int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,379✔
234

235
static void doDeleteWindowByGroupId(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
55✔
236
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
55✔
237
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
55✔
238

239
  SColumnInfoData* pGpIdCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
55✔
240
  uint64_t* pGroupIdData = (uint64_t*)pGpIdCol->pData;
55✔
241
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
110✔
242
    uint64_t groupId = pGroupIdData[i];
55✔
243
    void*   pIte = NULL;
55✔
244
    int32_t iter = 0;
55✔
245
    while ((pIte = tSimpleHashIterate(pInfo->aggSup.pResultRowHashTable, pIte, &iter)) != NULL) {
70✔
246
      size_t keyLen = 0;
15✔
247
      SWinKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
15!
248
      if (pKey->groupId == groupId) {
15!
249
        int32_t tmpRes = tSimpleHashIterateRemove(pInfo->aggSup.pResultRowHashTable, pKey, keyLen, &pIte, &iter);
15✔
250
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
15!
251
      }
252
    }
253

254
    pAPI->stateStore.streamStateDelByGroupId(pInfo->pState, groupId);
55✔
255
  }
256
}
55✔
257

258
static int32_t doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins,
2,209✔
259
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
260
  int32_t                      code = TSDB_CODE_SUCCESS;
2,209✔
261
  int32_t                      lino = 0;
2,209✔
262
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,209✔
263
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2,209✔
264
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,209✔
265
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
2,209✔
266
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,209✔
267
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
2,209✔
268
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
2,209✔
269
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
2,209✔
270
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
2,209✔
271
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
2,209✔
272
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,209✔
273
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
2,209✔
274
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
4,720✔
275
    SResultRowInfo dumyInfo = {0};
2,511✔
276
    dumyInfo.cur.pageId = -1;
2,511✔
277

278
    STimeWindow win = {0};
2,511✔
279
    if (IS_FINAL_INTERVAL_OP(pOperator) || IS_MID_INTERVAL_OP(pOperator)) {
2,511✔
280
      win.skey = startTsCols[i];
247✔
281
      win.ekey = endTsCols[i];
247✔
282
    } else {
283
      win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC);
2,264✔
284
    }
285

286
    do {
287
      if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i], pBlock->info.type)) {
3,398✔
288
        getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
26✔
289
        continue;
72✔
290
      }
291
      uint64_t winGpId = pGpDatas[i];
3,372✔
292
      SWinKey  winRes = {.ts = win.skey, .groupId = winGpId};
3,372✔
293
      void*    chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
3,372✔
294
      if (chIds) {
3,372✔
295
        int32_t childId = getChildIndex(pBlock);
52✔
296
        if (pInvalidWins) {
52✔
297
          qDebug("===stream===save invalid delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d", winRes.ts,
46!
298
                 winRes.groupId, childId);
299
          code = taosHashPut(pInvalidWins, &winRes, sizeof(SWinKey), NULL, 0);
46✔
300
          QUERY_CHECK_CODE(code, lino, _end);
46!
301
        }
302

303
        SArray* chArray = *(void**)chIds;
52✔
304
        int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
52✔
305
        if (index != -1) {
52✔
306
          qDebug("===stream===try push delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d ,continue", win.skey,
46!
307
                 winGpId, childId);
308
          getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
46✔
309
          continue;
46✔
310
        }
311
      }
312
      doDeleteWindow(pOperator, win.skey, winGpId);
3,326✔
313
      if (pUpWins) {
3,325✔
314
        void* tmp = taosArrayPush(pUpWins, &winRes);
2,596✔
315
        if (!tmp) {
2,596!
316
          code = terrno;
×
317
          QUERY_CHECK_CODE(code, lino, _end);
×
318
        }
319
      }
320
      if (pUpdatedMap) {
3,326!
321
        int32_t tmpRes = tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey));
3,326✔
322
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,326✔
323
      }
324
      getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
3,326✔
325
    } while (win.ekey <= endTsCols[i]);
3,398✔
326
  }
327
_end:
2,209✔
328
  if (code != TSDB_CODE_SUCCESS) {
2,209!
329
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
330
  }
331
  return code;
2,208✔
332
}
333

334
static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) {
1,083✔
335
  void*   pIte = NULL;
1,083✔
336
  int32_t iter = 0;
1,083✔
337
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1,378✔
338
    SWinKey*     pKey = tSimpleHashGetKey(pIte, NULL);
295✔
339
    uint64_t     groupId = pKey->groupId;
295✔
340
    TSKEY        ts = pKey->ts;
295✔
341
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
295✔
342
    if (!pPos->beUpdated) {
295✔
343
      continue;
9✔
344
    }
345
    pPos->beUpdated = false;
286✔
346
    int32_t code = saveWinResultInfo(ts, groupId, pPos, resWins);
286✔
347
    if (code != TSDB_CODE_SUCCESS) {
286!
348
      return code;
×
349
    }
350
  }
351
  return TSDB_CODE_SUCCESS;
1,083✔
352
}
353

354
static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval,
13,533✔
355
                                         SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins,
356
                                         SOperatorInfo* pOperator) {
357
  qDebug("===stream===close interval window");
13,533✔
358
  int32_t                      code = TSDB_CODE_SUCCESS;
13,533✔
359
  int32_t                      lino = 0;
13,533✔
360
  void*                        pIte = NULL;
13,533✔
361
  int32_t                      iter = 0;
13,533✔
362
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
13,533✔
363
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
13,533✔
364
  int32_t                      delSize = taosArrayGetSize(pDelWins);
13,533✔
365
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
17,935✔
366
    void*    key = tSimpleHashGetKey(pIte, NULL);
4,401!
367
    SWinKey* pWinKey = (SWinKey*)key;
4,401✔
368
    if (delSize > 0) {
4,401✔
369
      int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey);
280✔
370
      if (index >= 0 && 0 == compareWinKey(pWinKey, pDelWins, index)) {
280✔
371
        taosArrayRemove(pDelWins, index);
118✔
372
        delSize = taosArrayGetSize(pDelWins);
118✔
373
      }
374
    }
375

376
    void*       chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey));
4,401✔
377
    STimeWindow win = {
8,803✔
378
        .skey = pWinKey->ts,
4,402✔
379
        .ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1,
4,402✔
380
    };
381
    if (isCloseWindow(&win, pTwSup)) {
4,401✔
382
      if (chIds && pPullDataMap) {
1,587!
383
        SArray* chAy = *(SArray**)chIds;
×
384
        int32_t size = taosArrayGetSize(chAy);
×
385
        qDebug("===stream===window %" PRId64 " wait child size:%d", pWinKey->ts, size);
×
386
        for (int32_t i = 0; i < size; i++) {
×
387
          qDebug("===stream===window %" PRId64 " wait child id:%d", pWinKey->ts, *(int32_t*)taosArrayGet(chAy, i));
×
388
        }
389
        continue;
×
390
      } else if (pPullDataMap) {
1,587✔
391
        qDebug("===stream===close window %" PRId64, pWinKey->ts);
82✔
392
      }
393

394
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,587!
395
        code = saveWinResult(pWinKey, *(SRowBuffPos**)pIte, closeWins);
1,587✔
396
        QUERY_CHECK_CODE(code, lino, _end);
1,587!
397
      }
398
      int32_t tmpRes = tSimpleHashIterateRemove(pHashMap, pWinKey, sizeof(SWinKey), &pIte, &iter);
1,587✔
399
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,587✔
400
    }
401
  }
402

403
_end:
13,536✔
404
  if (code != TSDB_CODE_SUCCESS) {
13,536!
405
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
406
  }
407
  return code;
13,536✔
408
}
409

410
STimeWindow getFinalTimeWindow(int64_t ts, SInterval* pInterval) {
224,478✔
411
  STimeWindow w = {.skey = ts, .ekey = INT64_MAX};
224,478✔
412
  w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1;
224,478✔
413
  return w;
224,478✔
414
}
415

416
static void doBuildDeleteResult(SStreamIntervalOperatorInfo* pInfo, SArray* pWins, int32_t* index,
31,744✔
417
                                SSDataBlock* pBlock) {
418
  doBuildDeleteResultImpl(&pInfo->stateStore, pInfo->pState, pWins, index, pBlock);
31,744✔
419
}
31,744✔
420

421
void doBuildDeleteResultImpl(SStateStore* pAPI, SStreamState* pState, SArray* pWins, int32_t* index,
33,528✔
422
                             SSDataBlock* pBlock) {
423
  int32_t code = TSDB_CODE_SUCCESS;
33,528✔
424
  int32_t lino = 0;
33,528✔
425
  blockDataCleanup(pBlock);
33,528✔
426
  int32_t size = taosArrayGetSize(pWins);
33,530✔
427
  if (*index == size) {
33,530✔
428
    *index = 0;
32,937✔
429
    taosArrayClear(pWins);
32,937✔
430
    goto _end;
32,937✔
431
  }
432
  code = blockDataEnsureCapacity(pBlock, size - *index);
593✔
433
  QUERY_CHECK_CODE(code, lino, _end);
593!
434

435
  uint64_t uid = 0;
593✔
436
  for (int32_t i = *index; i < size; i++) {
2,029✔
437
    SWinKey* pWin = taosArrayGet(pWins, i);
1,436✔
438
    void*    tbname = NULL;
1,436✔
439
    int32_t  winCode = TSDB_CODE_SUCCESS;
1,436✔
440
    code = pAPI->streamStateGetParName(pState, pWin->groupId, &tbname, false, &winCode);
1,436✔
441
    QUERY_CHECK_CODE(code, lino, _end);
1,436!
442

443
    if (winCode != TSDB_CODE_SUCCESS) {
1,436✔
444
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, NULL);
1,055✔
445
      QUERY_CHECK_CODE(code, lino, _end);
1,055!
446
    } else {
447
      QUERY_CHECK_CONDITION((tbname), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
381!
448
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
449
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
381✔
450
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, parTbName);
381✔
451
      QUERY_CHECK_CODE(code, lino, _end);
381!
452
    }
453
    pAPI->streamStateFreeVal(tbname);
1,436✔
454
    (*index)++;
1,436✔
455
  }
456

457
_end:
593✔
458
  if (code != TSDB_CODE_SUCCESS) {
33,530!
459
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
460
  }
461
}
33,530✔
462

463
void destroyFlusedPos(void* pRes) {
724,992✔
464
  SRowBuffPos* pPos = (SRowBuffPos*)pRes;
724,992✔
465
  if (pPos->needFree && !pPos->pRowBuff) {
724,992!
466
    taosMemoryFreeClear(pPos->pKey);
×
467
    taosMemoryFree(pPos);
×
468
  }
469
}
724,992✔
470

471
void destroyFlusedppPos(void* ppRes) {
×
472
  void* pRes = *(void**)ppRes;
×
473
  destroyFlusedPos(pRes);
×
474
}
×
475

476
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
5,929✔
477
  int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
5,929✔
478
  if (pGroupResInfo->index >= 0 && pGroupResInfo->index < size) {
5,929!
479
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
724,993✔
480
      void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
724,992✔
481
      destroyFlusedPos(pPos);
724,992✔
482
    }
483
  }
484
  pGroupResInfo->freeItem = false;
5,929✔
485
  taosArrayDestroy(pGroupResInfo->pRows);
5,929✔
486
  pGroupResInfo->pRows = NULL;
5,929✔
487
  pGroupResInfo->index = 0;
5,929✔
488
  pGroupResInfo->delIndex = 0;
5,929✔
489
}
5,929✔
490

491
void destroyStreamFinalIntervalOperatorInfo(void* param) {
3,735✔
492
  if (param == NULL) {
3,735!
493
    return;
×
494
  }
495
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)param;
3,735✔
496
  cleanupBasicInfo(&pInfo->binfo);
3,735✔
497
  if (pInfo->pOperator) {
3,735!
498
    cleanupResultInfo(pInfo->pOperator->pTaskInfo, &pInfo->pOperator->exprSupp, &pInfo->groupResInfo, &pInfo->aggSup,
3,735✔
499
                      false);
500
    pInfo->pOperator = NULL;
3,735✔
501
  }
502

503
  destroyStreamBasicInfo(&pInfo->basic);
3,735✔
504
  cleanupAggSup(&pInfo->aggSup);
3,735✔
505
  clearGroupResInfo(&pInfo->groupResInfo);
3,735✔
506
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
3,735✔
507
  pInfo->pUpdated = NULL;
3,735✔
508

509
  // it should be empty.
510
  void* pIte = NULL;
3,735✔
511
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
3,735!
512
    taosArrayDestroy(*(void**)pIte);
×
513
  }
514
  taosHashCleanup(pInfo->pPullDataMap);
3,735✔
515
  taosHashCleanup(pInfo->pFinalPullDataMap);
3,735✔
516
  taosArrayDestroy(pInfo->pPullWins);
3,735✔
517
  blockDataDestroy(pInfo->pPullDataRes);
3,735✔
518
  taosArrayDestroy(pInfo->pDelWins);
3,734✔
519
  blockDataDestroy(pInfo->pDelRes);
3,735✔
520
  blockDataDestroy(pInfo->pMidRetriveRes);
3,735✔
521
  blockDataDestroy(pInfo->pMidPulloverRes);
3,735✔
522
  if (pInfo->pUpdatedMap != NULL) {
3,734!
523
    // free flushed pos
524
    tSimpleHashSetFreeFp(pInfo->pUpdatedMap, destroyFlusedppPos);
×
525
    tSimpleHashCleanup(pInfo->pUpdatedMap);
×
526
    pInfo->pUpdatedMap = NULL;
×
527
  }
528

529
  if (pInfo->stateStore.streamFileStateDestroy != NULL) {
3,734!
530
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
3,734✔
531
  }
532
  taosArrayDestroy(pInfo->pMidPullDatas);
3,735✔
533

534
  if (pInfo->pState != NULL && pInfo->pState->dump == 1) {
3,735!
535
    taosMemoryFreeClear(pInfo->pState->pTdbState->pOwner);
849!
536
    taosMemoryFreeClear(pInfo->pState->pTdbState);
849!
537
  }
538
  taosMemoryFreeClear(pInfo->pState);
3,735!
539

540
  nodesDestroyNode((SNode*)pInfo->pPhyNode);
3,735✔
541
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
3,734✔
542
  cleanupExprSupp(&pInfo->scalarSupp);
3,735✔
543
  tSimpleHashCleanup(pInfo->pDeletedMap);
3,735✔
544

545
  blockDataDestroy(pInfo->pCheckpointRes);
3,735✔
546

547
  taosMemoryFreeClear(param);
3,735!
548
}
549

550
#ifdef BUILD_NO_CALL
551
static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
552
  for (int32_t i = 0; i < numOfCols; i++) {
553
    if (fmIsUserDefinedFunc(pFCtx[i].functionId) || !fmIsInvertible(pFCtx[i].functionId)) {
554
      return false;
555
    }
556
  }
557
  return true;
558
}
559
#endif
560

561
void reloadFromDownStream(SOperatorInfo* downstream, SStreamIntervalOperatorInfo* pInfo) {
1,169✔
562
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
1,169✔
563

564
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
1,169✔
565
    reloadFromDownStream(downstream->pDownstream[0], pInfo);
28✔
566
    return;
28✔
567
  }
568

569
  SStreamScanInfo* pScanInfo = downstream->info;
1,141✔
570
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
1,141✔
571
}
572

573
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
7,861,731✔
574

575
int32_t initIntervalDownStream(SOperatorInfo* downstream, uint16_t type, SStreamIntervalOperatorInfo* pInfo,
3,709✔
576
                               struct SSteamOpBasicInfo* pBasic) {
577
  int32_t        code = TSDB_CODE_SUCCESS;
3,709✔
578
  int32_t        lino = 0;
3,709✔
579
  SStateStore*   pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
3,709✔
580
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
3,709✔
581

582
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
3,709✔
583
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
185✔
584
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
185✔
585
  }
586

587
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
3,709✔
588
    return initIntervalDownStream(downstream->pDownstream[0], type, pInfo, pBasic);
185✔
589
  }
590

591
  SStreamScanInfo* pScanInfo = downstream->info;
3,524✔
592
  pScanInfo->windowSup.parentType = type;
3,524✔
593
  pScanInfo->windowSup.pIntervalAggSup = &pInfo->aggSup;
3,524✔
594
  if (!pScanInfo->pUpdateInfo) {
3,524✔
595
    code = pAPI->updateInfoInitP(&pInfo->interval, pInfo->twAggSup.waterMark, pScanInfo->igCheckUpdate,
3,337✔
596
                                 pScanInfo->pkColType, pScanInfo->pkColLen, &pScanInfo->pUpdateInfo);
3,337✔
597
    QUERY_CHECK_CODE(code, lino, _end);
3,337!
598
  }
599

600
  pScanInfo->interval = pInfo->interval;
3,524✔
601
  pScanInfo->twAggSup = pInfo->twAggSup;
3,524✔
602
  pScanInfo->pState = pInfo->pState;
3,524✔
603
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
3,524✔
604
  if (!hasSrcPrimaryKeyCol(pBasic)) {
3,524✔
605
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
3,521✔
606
  }
607

608
_end:
4✔
609
  if (code != TSDB_CODE_SUCCESS) {
3,525!
610
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
611
  }
612
  return code;
3,525✔
613
}
614

615
int32_t compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t numOfOutput,
40✔
616
                         SExecTaskInfo* pTaskInfo, SColumnInfoData* pTimeWindowData) {
617
  int32_t code = TSDB_CODE_SUCCESS;
40✔
618
  int32_t lino = 0;
40✔
619
  for (int32_t k = 0; k < numOfOutput; ++k) {
203✔
620
    if (fmIsWindowPseudoColumnFunc(pDestCtx[k].functionId)) {
165✔
621
      if (!pTimeWindowData) {
44!
622
        continue;
×
623
      }
624

625
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pDestCtx[k]);
44✔
626
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
44✔
627
      SColumnInfoData      idata = {0};
44✔
628
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
44✔
629
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
44✔
630
      idata.pData = p;
44✔
631

632
      SScalarParam out = {.columnData = &idata};
44✔
633
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
44✔
634
      code = pDestCtx[k].sfp.process(&tw, 1, &out);
44✔
635
      QUERY_CHECK_CODE(code, lino, _end);
44!
636

637
      pEntryInfo->numOfRes = 1;
44✔
638
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
121!
639
      code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
119✔
640
      QUERY_CHECK_CODE(code, lino, _end);
119!
641
    } else if (pDestCtx[k].fpSet.combine == NULL) {
2!
642
      char* funName = fmGetFuncName(pDestCtx[k].functionId);
2✔
643
      qError("%s error, combine funcion for %s is not implemented", GET_TASKID(pTaskInfo), funName);
2!
644
      taosMemoryFreeClear(funName);
2!
645
      code = TSDB_CODE_FAILED;
2✔
646
      QUERY_CHECK_CODE(code, lino, _end);
2!
647
    }
648
  }
649

650
_end:
38✔
651
  if (code != TSDB_CODE_SUCCESS) {
40✔
652
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
653
  }
654
  return code;
40✔
655
}
656

657
bool hasIntervalWindow(void* pState, SWinKey* pKey, SStateStore* pStore) {
23✔
658
  return pStore->streamStateCheck(pState, pKey);
23✔
659
}
660

661
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
7,087,144✔
662
                             SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset,
663
                             SAggSupporter* pAggSup, SStateStore* pStore, int32_t* pWinCode) {
664
  int32_t code = TSDB_CODE_SUCCESS;
7,087,144✔
665
  int32_t lino = 0;
7,087,144✔
666
  SWinKey key = {.ts = win->skey, .groupId = groupId};
7,087,144✔
667
  char*   value = NULL;
7,087,144✔
668
  int32_t size = pAggSup->resultRowSize;
7,087,144✔
669

670
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
7,087,144✔
671
  QUERY_CHECK_CODE(code, lino, _end);
7,086,947!
672

673
  *pResult = (SRowBuffPos*)value;
7,086,947✔
674
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
7,086,947✔
675

676
  // set time window for current result
677
  res->win = (*win);
7,086,947✔
678
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
7,086,947✔
679
  QUERY_CHECK_CODE(code, lino, _end);
7,086,292!
680

681
_end:
7,086,292✔
682
  if (code != TSDB_CODE_SUCCESS) {
7,086,292!
683
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
684
  }
685
  return code;
7,086,167✔
686
}
687

688
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
224,345✔
689
                           SStateStore* pStore) {
690
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
224,345✔
691
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
23✔
692
    if (!hasIntervalWindow(pState, &key, pStore)) {
23✔
693
      return true;
12✔
694
    }
695
    return false;
11✔
696
  }
697
  return false;
224,322✔
698
}
699

700
int32_t getNexWindowPos(SInterval* pInterval, SDataBlockInfo* pBlockInfo, TSKEY* tsCols, int32_t startPos, TSKEY eKey,
45✔
701
                        STimeWindow* pNextWin) {
702
  int32_t forwardRows =
703
      getNumOfRowsInTimeWindow(pBlockInfo, tsCols, startPos, eKey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
45✔
704
  int32_t prevEndPos = forwardRows - 1 + startPos;
45✔
705
  return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
45✔
706
}
707

708
int32_t addPullWindow(SHashObj* pMap, SWinKey* pWinRes, int32_t size) {
215✔
709
  int32_t code = TSDB_CODE_SUCCESS;
215✔
710
  int32_t lino = 0;
215✔
711
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
215✔
712
  QUERY_CHECK_NULL(childIds, code, lino, _end, terrno);
215!
713
  for (int32_t i = 0; i < size; i++) {
933✔
714
    void* tmp = taosArrayPush(childIds, &i);
718✔
715
    if (!tmp) {
718!
716
      code = terrno;
×
717
      QUERY_CHECK_CODE(code, lino, _end);
×
718
    }
719
  }
720
  code = taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
215✔
721
  QUERY_CHECK_CODE(code, lino, _end);
215!
722
_end:
215✔
723
  if (code != TSDB_CODE_SUCCESS) {
215!
724
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
725
  }
726
  return code;
215✔
727
}
728

729
static void clearStreamIntervalOperator(SStreamIntervalOperatorInfo* pInfo) {
1,610✔
730
  tSimpleHashClear(pInfo->aggSup.pResultRowHashTable);
1,610✔
731
  clearDiskbasedBuf(pInfo->aggSup.pResultBuf);
1,610✔
732
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
1,610✔
733
  pInfo->aggSup.currentPageId = -1;
1,610✔
734
  pInfo->stateStore.streamStateClear(pInfo->pState);
1,610✔
735
}
1,610✔
736

737
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
2,895✔
738
  if (pBlock->info.rows <= 0) {
2,895✔
739
    return;
2,751✔
740
  }
741
  blockDataCleanup(pBlock);
144✔
742
}
743

744
static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
2,895✔
745
  int32_t code = TSDB_CODE_SUCCESS;
2,895✔
746
  int32_t lino = 0;
2,895✔
747
  clearSpecialDataBlock(pBlock);
2,895✔
748
  int32_t size = taosArrayGetSize(array);
2,895✔
749
  if (size - (*pIndex) == 0) {
2,895✔
750
    goto _end;
2,751✔
751
  }
752
  code = blockDataEnsureCapacity(pBlock, size - (*pIndex));
144✔
753
  QUERY_CHECK_CODE(code, lino, _end);
144!
754

755
  SColumnInfoData* pStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
144✔
756
  SColumnInfoData* pEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
144✔
757
  SColumnInfoData* pGroupId = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
144✔
758
  SColumnInfoData* pCalStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
144✔
759
  SColumnInfoData* pCalEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
144✔
760
  SColumnInfoData* pTbName = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
144✔
761
  SColumnInfoData* pPrimaryKey = NULL;
144✔
762
  if (taosArrayGetSize(pBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
144!
763
    pPrimaryKey = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
764
  }
765
  for (; (*pIndex) < size; (*pIndex)++) {
350✔
766
    SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
206✔
767
    code = colDataSetVal(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false);
206✔
768
    QUERY_CHECK_CODE(code, lino, _end);
206!
769

770
    code = colDataSetVal(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false);
206✔
771
    QUERY_CHECK_CODE(code, lino, _end);
206!
772

773
    code = colDataSetVal(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false);
206✔
774
    QUERY_CHECK_CODE(code, lino, _end);
206!
775

776
    code = colDataSetVal(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false);
206✔
777
    QUERY_CHECK_CODE(code, lino, _end);
206!
778

779
    code = colDataSetVal(pCalEndTs, pBlock->info.rows, (const char*)&pWin->calWin.ekey, false);
206✔
780
    QUERY_CHECK_CODE(code, lino, _end);
206!
781

782
    colDataSetNULL(pTbName, pBlock->info.rows);
206!
783
    if (pPrimaryKey != NULL) {
206!
784
      colDataSetNULL(pPrimaryKey, pBlock->info.rows);
×
785
    }
786

787
    pBlock->info.rows++;
206✔
788
  }
789
  if ((*pIndex) == size) {
144!
790
    *pIndex = 0;
144✔
791
    taosArrayClear(array);
144✔
792
  }
793
  code = blockDataUpdateTsWindow(pBlock, 0);
144✔
794
  QUERY_CHECK_CODE(code, lino, _end);
144!
795

796
_end:
144✔
797
  if (code != TSDB_CODE_SUCCESS) {
2,895!
798
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
799
  }
800
}
2,895✔
801

802
static int32_t processPullOver(SSDataBlock* pBlock, SHashObj* pMap, SHashObj* pFinalMap, SInterval* pInterval,
492✔
803
                               SArray* pPullWins, int32_t numOfCh, SOperatorInfo* pOperator, bool* pBeOver) {
804
  int32_t                      code = TSDB_CODE_SUCCESS;
492✔
805
  int32_t                      lino = 0;
492✔
806
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
492✔
807
  SColumnInfoData*             pStartCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
492✔
808
  TSKEY*                       tsData = (TSKEY*)pStartCol->pData;
492✔
809
  SColumnInfoData*             pEndCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
492✔
810
  TSKEY*                       tsEndData = (TSKEY*)pEndCol->pData;
492✔
811
  SColumnInfoData*             pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
492✔
812
  uint64_t*                    groupIdData = (uint64_t*)pGroupCol->pData;
492✔
813
  int32_t                      chId = getChildIndex(pBlock);
492✔
814
  bool                         res = false;
492✔
815
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
1,192✔
816
    TSKEY winTs = tsData[i];
700✔
817
    while (winTs <= tsEndData[i]) {
1,418✔
818
      SWinKey winRes = {.ts = winTs, .groupId = groupIdData[i]};
718✔
819
      void*   chIds = taosHashGet(pMap, &winRes, sizeof(SWinKey));
718✔
820
      if (chIds) {
718!
821
        SArray* chArray = *(SArray**)chIds;
718✔
822
        int32_t index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
718✔
823
        if (index != -1) {
718!
824
          qDebug("===stream===retrive window %" PRId64 " delete child id %d", winRes.ts, chId);
718✔
825
          taosArrayRemove(chArray, index);
718✔
826
          if (taosArrayGetSize(chArray) == 0) {
718✔
827
            // pull data is over
828
            taosArrayDestroy(chArray);
215✔
829
            int32_t tmpRes = taosHashRemove(pMap, &winRes, sizeof(SWinKey));
215✔
830
            qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
215!
831
            res = true;
215✔
832
            qDebug("===stream===retrive pull data over.window %" PRId64, winRes.ts);
215✔
833

834
            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
215✔
835
            if (pFinalCh) {
215✔
836
              int32_t tmpRes = taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
23✔
837
              qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
23!
838
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
23✔
839
              STimeWindow     nextWin = getFinalTimeWindow(winRes.ts, pInterval);
23✔
840
              SPullWindowInfo pull = {.window = nextWin,
23✔
841
                                      .groupId = winRes.groupId,
23✔
842
                                      .calWin.skey = nextWin.skey,
23✔
843
                                      .calWin.ekey = nextWin.skey};
23✔
844
              // add pull data request
845
              qDebug("===stream===prepare final retrive for delete window:%" PRId64 ",groupId:%" PRId64 ", size:%d",
23!
846
                     winRes.ts, winRes.groupId, numOfCh);
847
              if (IS_MID_INTERVAL_OP(pOperator)) {
23!
848
                SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
×
849

850
                void* tmp = taosArrayPush(pInfo->pMidPullDatas, &winRes);
×
851
                if (!tmp) {
×
852
                  code = terrno;
×
853
                  QUERY_CHECK_CODE(code, lino, _end);
×
854
                }
855
              } else if (savePullWindow(&pull, pPullWins) == TSDB_CODE_SUCCESS) {
23!
856
                void* tmp = taosArrayPush(pInfo->pDelWins, &winRes);
23✔
857
                if (!tmp) {
23!
858
                  code = terrno;
×
859
                  QUERY_CHECK_CODE(code, lino, _end);
×
860
                }
861

862
                code = addPullWindow(pMap, &winRes, numOfCh);
23✔
863
                QUERY_CHECK_CODE(code, lino, _end);
23!
864

865
                if (pInfo->destHasPrimaryKey) {
23!
866
                  code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
867
                  QUERY_CHECK_CODE(code, lino, _end);
×
868
                }
869
                qDebug("===stream===prepare final retrive for delete %" PRId64 ", size:%d", winRes.ts, numOfCh);
23!
870
              }
871
            }
872
          }
873
        }
874
      }
875
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision, NULL);
718✔
876
    }
877
  }
878
  if (pBeOver) {
492✔
879
    *pBeOver = res;
12✔
880
  }
881

882
_end:
480✔
883
  if (code != TSDB_CODE_SUCCESS) {
492!
884
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
885
  }
886
  return code;
492✔
887
}
888

889
static int32_t addRetriveWindow(SArray* wins, SStreamIntervalOperatorInfo* pInfo, int32_t childId) {
190✔
890
  int32_t code = TSDB_CODE_SUCCESS;
190✔
891
  int32_t lino = 0;
190✔
892
  int32_t size = taosArrayGetSize(wins);
190✔
893
  for (int32_t i = 0; i < size; i++) {
382✔
894
    SWinKey*    winKey = taosArrayGet(wins, i);
192✔
895
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
192✔
896
    void*       chIds = taosHashGet(pInfo->pPullDataMap, winKey, sizeof(SWinKey));
192✔
897
    if (!chIds) {
192✔
898
      SPullWindowInfo pull = {
186✔
899
          .window = nextWin, .groupId = winKey->groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
186✔
900
      // add pull data request
901
      if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
186!
902
        code = addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
186✔
903
        QUERY_CHECK_CODE(code, lino, _end);
186!
904

905
        if (pInfo->destHasPrimaryKey) {
186!
906
          code = tSimpleHashPut(pInfo->pDeletedMap, winKey, sizeof(SWinKey), NULL, 0);
×
907
          QUERY_CHECK_CODE(code, lino, _end);
×
908
        }
909
        qDebug("===stream===prepare retrive for delete %" PRId64 ", size:%d", winKey->ts, pInfo->numOfChild);
186✔
910
      }
911
    } else {
912
      SArray* chArray = *(void**)chIds;
6✔
913
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
6✔
914
      qDebug("===stream===check final retrive %" PRId64 ",chid:%d", winKey->ts, index);
6!
915
      if (index == -1) {
6!
916
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
6!
917
        code = taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
6✔
918
        QUERY_CHECK_CODE(code, lino, _end);
6!
919
      }
920
    }
921
  }
922

923
_end:
190✔
924
  if (code != TSDB_CODE_SUCCESS) {
190!
925
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
926
  }
927
  return code;
190✔
928
}
929

930
static void clearFunctionContext(SExprSupp* pSup) {
2,118✔
931
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
23,006✔
932
    pSup->pCtx[i].saveHandle.currentPage = -1;
20,888✔
933
  }
934
}
2,118✔
935

936
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
6,255,387✔
937
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
6,255,387✔
938
}
939

940
void buildDataBlockFromGroupRes(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
9,452✔
941
                                SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
942
  int32_t         code = TSDB_CODE_SUCCESS;
9,452✔
943
  int32_t         lino = 0;
9,452✔
944
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
9,452✔
945
  SStorageAPI*    pAPI = &pOperator->pTaskInfo->storageAPI;
9,452✔
946
  SExprInfo*      pExprInfo = pSup->pExprInfo;
9,452✔
947
  int32_t         numOfExprs = pSup->numOfExprs;
9,452✔
948
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
9,452✔
949
  SqlFunctionCtx* pCtx = pSup->pCtx;
9,452✔
950

951
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
9,452✔
952

953
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
6,261,639✔
954
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
6,255,387✔
955
    SResultRow*  pRow = NULL;
6,255,386✔
956
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
6,255,386✔
957
    QUERY_CHECK_CODE(code, lino, _end);
6,255,386!
958
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
6,255,386✔
959
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
6,255,386✔
960
    // no results, continue to check the next one
961
    if (pRow->numOfRows == 0) {
6,255,387!
962
      pGroupResInfo->index += 1;
×
963
      continue;
×
964
    }
965
    if (pBlock->info.id.groupId == 0) {
6,255,387✔
966
      pBlock->info.id.groupId = groupId;
444,304✔
967
      void*   tbname = NULL;
444,304✔
968
      int32_t winCode = TSDB_CODE_SUCCESS;
444,304✔
969
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
444,304✔
970
                                                    false, &winCode);
971
      QUERY_CHECK_CODE(code, lino, _end);
444,302!
972
      if (winCode != TSDB_CODE_SUCCESS) {
444,302✔
973
        pBlock->info.parTbName[0] = 0;
439,458✔
974
      } else {
975
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,844✔
976
      }
977
      pAPI->stateStore.streamStateFreeVal(tbname);
444,302✔
978
    } else {
979
      // current value belongs to different group, it can't be packed into one datablock
980
      if (pBlock->info.id.groupId != groupId) {
5,811,083✔
981
        break;
3,206✔
982
      }
983
    }
984

985
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,253,375✔
986
      break;
1,194✔
987
    }
988
    pGroupResInfo->index += 1;
6,252,181✔
989

990
    for (int32_t j = 0; j < numOfExprs; ++j) {
59,517,847✔
991
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
53,265,660✔
992

993
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
53,265,660✔
994

995
      if (pCtx[j].fpSet.finalize) {
53,265,668✔
996
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
35,376,514✔
997
        if (TAOS_FAILED(tmpRes)) {
35,376,509!
998
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
999
          QUERY_CHECK_CODE(code, lino, _end);
2!
1000
        }
1001
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
17,889,154✔
1002
        // do nothing, todo refactor
1003
      } else {
1004
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
1005
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
1006
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
17,858,730✔
1007
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
17,858,730✔
1008
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
35,717,461✔
1009
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
17,858,730✔
1010
          QUERY_CHECK_CODE(code, lino, _end);
17,858,731!
1011
        }
1012
      }
1013
    }
1014

1015
    if (pSessionKeys) {
6,252,187!
1016
      SSessionKey key = {.groupId = groupId, .win = pRow->win};
×
1017
      for (int32_t j = 0; j < pRow->numOfRows; ++j) {
×
1018
        const void* px = taosArrayPush(pSessionKeys, &key);
×
1019
        QUERY_CHECK_NULL(px, code, lino, _end, terrno);
×
1020
      }
1021
    }
1022

1023
    pBlock->info.rows += pRow->numOfRows;
6,252,187✔
1024
  }
1025

1026
  pBlock->info.dataLoad = 1;
9,458✔
1027
  code = blockDataUpdateTsWindow(pBlock, 0);
9,458✔
1028
  QUERY_CHECK_CODE(code, lino, _end);
9,452!
1029

1030
_end:
9,452✔
1031
  if (code != TSDB_CODE_SUCCESS) {
9,452!
1032
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1033
  }
1034
}
9,452✔
1035

1036
void doBuildStreamIntervalResult(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock,
32,832✔
1037
                                 SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
1038
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
32,832✔
1039
  // set output datablock version
1040
  pBlock->info.version = pTaskInfo->version;
32,832✔
1041

1042
  blockDataCleanup(pBlock);
32,832✔
1043
  taosArrayClear(pSessionKeys);
32,836✔
1044
  if (!hasRemainResults(pGroupResInfo)) {
32,837✔
1045
    return;
23,386✔
1046
  }
1047

1048
  // clear the existed group id
1049
  pBlock->info.id.groupId = 0;
9,452✔
1050
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
9,452✔
1051
}
1052

1053
static int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
224,263✔
1054
                                           TSKEY* primaryKeys, int32_t prevPosition) {
1055
  int32_t startPos = prevPosition + 1;
224,263✔
1056
  if (startPos == pDataBlockInfo->rows) {
224,263✔
1057
    startPos = -1;
1,898✔
1058
  } else {
1059
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
222,365✔
1060
  }
1061
  return startPos;
224,263✔
1062
}
1063

1064
static int32_t doStreamIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, uint64_t groupId,
762,082✔
1065
                                       SSHashObj* pUpdatedMap, SSHashObj* pDeletedMap) {
1066
  int32_t                      code = TSDB_CODE_SUCCESS;
762,082✔
1067
  int32_t                      lino = 0;
762,082✔
1068
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
762,082✔
1069
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
762,082✔
1070

1071
  SResultRowInfo* pResultRowInfo = &(pInfo->binfo.resultRowInfo);
762,082✔
1072
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
762,082✔
1073
  SExprSupp*      pSup = &pOperator->exprSupp;
762,082✔
1074
  int32_t         numOfOutput = pSup->numOfExprs;
762,082✔
1075
  int32_t         step = 1;
762,082✔
1076
  TSKEY*          tsCols = NULL;
762,082✔
1077
  SRowBuffPos*    pResPos = NULL;
762,082✔
1078
  SResultRow*     pResult = NULL;
762,082✔
1079
  int32_t         forwardRows = 0;
762,082✔
1080
  int32_t         endRowId = pSDataBlock->info.rows - 1;
762,082✔
1081

1082
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
762,082✔
1083
  tsCols = (int64_t*)pColDataInfo->pData;
762,082✔
1084

1085
  void*            pPkVal = NULL;
762,082✔
1086
  int32_t          pkLen = 0;
762,082✔
1087
  SColumnInfoData* pPkColDataInfo = NULL;
762,082✔
1088
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
762,082✔
1089
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
14✔
1090
  }
1091

1092
  if (pSDataBlock->info.window.skey != tsCols[0] || pSDataBlock->info.window.ekey != tsCols[endRowId]) {
762,082!
1093
    qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64 ",maxKey %" PRId64,
×
1094
           pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
1095
    code = blockDataUpdateTsWindow(pSDataBlock, pInfo->primaryTsIndex);
×
1096
    QUERY_CHECK_CODE(code, lino, _end);
×
1097

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

1105
  int32_t     startPos = 0;
762,083✔
1106
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
762,083✔
1107
  STimeWindow nextWin = {0};
762,084✔
1108
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
762,084✔
1109
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
1,860✔
1110
  } else {
1111
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
760,224✔
1112
  }
1113
  while (1) {
6,323,703✔
1114
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
7,085,785✔
1115
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
7,085,748!
1116
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1117
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1118
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1119
    }
1120

1121
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
7,086,405✔
1122
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
688✔
1123
                          nextWin.ekey, pPkVal, pkLen)) ||
7,085,502✔
1124
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
7,085,691✔
1125
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
38✔
1126
      if (startPos < 0) {
45✔
1127
        break;
762,084✔
1128
      }
1129
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
19!
1130
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1131
      continue;
57✔
1132
    }
1133

1134
    if (IS_FINAL_INTERVAL_OP(pOperator) && pInfo->numOfChild > 0) {
7,085,490!
1135
      bool    ignore = true;
222,959✔
1136
      SWinKey winRes = {
222,959✔
1137
          .ts = nextWin.skey,
222,959✔
1138
          .groupId = groupId,
1139
      };
1140
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
222,959✔
1141
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore) && isClosed &&
222,959!
1142
          !chIds) {
×
1143
        SPullWindowInfo pull = {
×
1144
            .window = nextWin, .groupId = groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
×
1145
        // add pull data request
1146
        if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
×
1147
          code = addPullWindow(pInfo->pPullDataMap, &winRes, pInfo->numOfChild);
×
1148
          QUERY_CHECK_CODE(code, lino, _end);
×
1149

1150
          if (pInfo->destHasPrimaryKey) {
×
1151
            code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
1152
            QUERY_CHECK_CODE(code, lino, _end);
×
1153
          }
1154
        }
1155
      } else {
1156
        int32_t index = -1;
222,959✔
1157
        SArray* chArray = NULL;
222,959✔
1158
        int32_t chId = 0;
222,959✔
1159
        if (chIds) {
222,959✔
1160
          chArray = *(void**)chIds;
353✔
1161
          chId = getChildIndex(pSDataBlock);
353✔
1162
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
353✔
1163
        }
1164
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
222,959✔
1165
          ignore = false;
222,828✔
1166
        }
1167
      }
1168

1169
      if (ignore) {
222,959✔
1170
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
131✔
1171
        if (startPos < 0) {
131✔
1172
          break;
93✔
1173
        }
1174
        continue;
38✔
1175
      }
1176
    }
1177

1178
    int32_t winCode = TSDB_CODE_SUCCESS;
7,085,359✔
1179
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
7,085,359✔
1180
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1181
    QUERY_CHECK_CODE(code, lino, _end);
7,084,843!
1182

1183
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator) &&
7,084,843✔
1184
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
6,636,692!
1185
      SSessionKey key = {.win = nextWin, .groupId = groupId};
×
1186
      code = addIntervalAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &key, &pInfo->basic.notifyEventSup,
×
1187
                                       pTaskInfo->streamInfo.pNotifyEventStat);
1188
      QUERY_CHECK_CODE(code, lino, _end);
×
1189
    }
1190

1191
    pResult = (SResultRow*)pResPos->pRowBuff;
7,084,843✔
1192

1193
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
7,084,843✔
1194
      forwardRows = 1;
222,828✔
1195
    } else {
1196
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
6,862,015✔
1197
                                             NULL, TSDB_ORDER_ASC);
1198
    }
1199

1200
    SWinKey key = {
7,086,561✔
1201
        .ts = pResult->win.skey,
7,086,561✔
1202
        .groupId = groupId,
1203
    };
1204

1205
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
7,086,561!
1206
      code = tSimpleHashPut(pDeletedMap, &key, sizeof(SWinKey), NULL, 0);
6✔
1207
      QUERY_CHECK_CODE(code, lino, _end);
6!
1208
    }
1209

1210
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
7,086,561!
1211
      code = saveWinResult(&key, pResPos, pUpdatedMap);
7,077,628✔
1212
      QUERY_CHECK_CODE(code, lino, _end);
7,077,452!
1213
    }
1214

1215
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
7,086,385✔
1216
      pResPos->beUpdated = true;
8,173✔
1217
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
8,173✔
1218
      QUERY_CHECK_CODE(code, lino, _end);
8,179!
1219
    }
1220

1221
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
7,086,391✔
1222
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
7,085,561✔
1223
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
7,085,561✔
1224
    QUERY_CHECK_CODE(code, lino, _end);
7,086,564!
1225
    key.ts = nextWin.skey;
7,086,564✔
1226

1227
    if (pInfo->delKey.ts > key.ts) {
7,086,564✔
1228
      pInfo->delKey = key;
1,932✔
1229
    }
1230
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
7,086,564✔
1231
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
7,086,564✔
1232
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
222,828✔
1233
    } else {
1234
      startPos =
1235
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
6,863,736✔
1236
    }
1237
    if (startPos < 0) {
7,085,611✔
1238
      break;
761,965✔
1239
    }
1240
  }
1241
_end:
762,084✔
1242
  if (code != TSDB_CODE_SUCCESS) {
762,084!
1243
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1244
  }
1245
  return code;
762,083✔
1246
}
1247

1248
int winPosCmprImpl(const void* pKey1, const void* pKey2) {
96,947,716✔
1249
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
96,947,716✔
1250
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
96,947,716✔
1251
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
96,947,716✔
1252
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
96,947,716✔
1253

1254
  if (pWin1->groupId > pWin2->groupId) {
96,947,716✔
1255
    return 1;
11,085,511✔
1256
  } else if (pWin1->groupId < pWin2->groupId) {
85,862,205✔
1257
    return -1;
10,229,566✔
1258
  }
1259

1260
  if (pWin1->ts > pWin2->ts) {
75,632,639✔
1261
    return 1;
38,124,348✔
1262
  } else if (pWin1->ts < pWin2->ts) {
37,508,291!
1263
    return -1;
37,508,291✔
1264
  }
1265

1266
  return 0;
×
1267
}
1268

1269
static void resetUnCloseWinInfo(SSHashObj* winMap) {
248✔
1270
  void*   pIte = NULL;
248✔
1271
  int32_t iter = 0;
248✔
1272
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
546✔
1273
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
298✔
1274
    pPos->beUsed = true;
298✔
1275
  }
1276
}
248✔
1277

1278
int32_t encodeSWinKey(void** buf, SWinKey* key) {
38✔
1279
  int32_t tlen = 0;
38✔
1280
  tlen += taosEncodeFixedI64(buf, key->ts);
38✔
1281
  tlen += taosEncodeFixedU64(buf, key->groupId);
38✔
1282
  return tlen;
38✔
1283
}
1284

1285
void* decodeSWinKey(void* buf, SWinKey* key) {
2✔
1286
  buf = taosDecodeFixedI64(buf, &key->ts);
2!
1287
  buf = taosDecodeFixedU64(buf, &key->groupId);
2!
1288
  return buf;
2✔
1289
}
1290

1291
int32_t encodeSTimeWindowAggSupp(void** buf, STimeWindowAggSupp* pTwAggSup) {
139✔
1292
  int32_t tlen = 0;
139✔
1293
  tlen += taosEncodeFixedI64(buf, pTwAggSup->minTs);
139✔
1294
  tlen += taosEncodeFixedI64(buf, pTwAggSup->maxTs);
139✔
1295
  return tlen;
139✔
1296
}
1297

1298
void* decodeSTimeWindowAggSupp(void* buf, STimeWindowAggSupp* pTwAggSup) {
12✔
1299
  buf = taosDecodeFixedI64(buf, &pTwAggSup->minTs);
12!
1300
  buf = taosDecodeFixedI64(buf, &pTwAggSup->maxTs);
12!
1301
  return buf;
12✔
1302
}
1303

1304
int32_t encodeSTimeWindow(void** buf, STimeWindow* pWin) {
4✔
1305
  int32_t tlen = 0;
4✔
1306
  tlen += taosEncodeFixedI64(buf, pWin->skey);
4✔
1307
  tlen += taosEncodeFixedI64(buf, pWin->ekey);
4✔
1308
  return tlen;
4✔
1309
}
1310

1311
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
×
1312
  buf = taosDecodeFixedI64(buf, &pWin->skey);
×
1313
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
×
1314
  return buf;
×
1315
}
1316

1317
int32_t encodeSPullWindowInfo(void** buf, SPullWindowInfo* pPullInfo) {
×
1318
  int32_t tlen = 0;
×
1319
  tlen += encodeSTimeWindow(buf, &pPullInfo->calWin);
×
1320
  tlen += taosEncodeFixedU64(buf, pPullInfo->groupId);
×
1321
  tlen += encodeSTimeWindow(buf, &pPullInfo->window);
×
1322
  return tlen;
×
1323
}
1324

1325
void* decodeSPullWindowInfo(void* buf, SPullWindowInfo* pPullInfo) {
×
1326
  buf = decodeSTimeWindow(buf, &pPullInfo->calWin);
×
1327
  buf = taosDecodeFixedU64(buf, &pPullInfo->groupId);
×
1328
  buf = decodeSTimeWindow(buf, &pPullInfo->window);
×
1329
  return buf;
×
1330
}
1331

1332
int32_t encodeSPullWindowInfoArray(void** buf, SArray* pPullInfos) {
58✔
1333
  int32_t tlen = 0;
58✔
1334
  int32_t size = taosArrayGetSize(pPullInfos);
58✔
1335
  tlen += taosEncodeFixedI32(buf, size);
58✔
1336
  for (int32_t i = 0; i < size; i++) {
58!
1337
    void* pItem = taosArrayGet(pPullInfos, i);
×
1338
    tlen += encodeSPullWindowInfo(buf, pItem);
×
1339
  }
1340
  return tlen;
58✔
1341
}
1342

1343
int32_t decodeSPullWindowInfoArray(void* buf, SArray* pPullInfos, void** ppBuf) {
4✔
1344
  int32_t code = TSDB_CODE_SUCCESS;
4✔
1345
  int32_t lino = 0;
4✔
1346
  int32_t size = 0;
4!
1347
  buf = taosDecodeFixedI32(buf, &size);
4✔
1348
  for (int32_t i = 0; i < size; i++) {
4!
1349
    SPullWindowInfo item = {0};
×
1350
    buf = decodeSPullWindowInfo(buf, &item);
×
1351
    void* tmp = taosArrayPush(pPullInfos, &item);
×
1352
    if (!tmp) {
×
1353
      code = terrno;
×
1354
      QUERY_CHECK_CODE(code, lino, _end);
×
1355
    }
1356
  }
1357
  (*ppBuf) = buf;
4✔
1358

1359
_end:
4✔
1360
  if (code != TSDB_CODE_SUCCESS) {
4!
1361
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1362
  }
1363
  return code;
4✔
1364
}
1365

1366
int32_t doStreamIntervalEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator) {
58✔
1367
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
58✔
1368
  if (!pInfo) {
58!
1369
    return 0;
×
1370
  }
1371

1372
  void* pData = (buf == NULL) ? NULL : *buf;
58✔
1373

1374
  // 1.pResultRowHashTable
1375
  int32_t tlen = 0;
58✔
1376
  int32_t mapSize = tSimpleHashGetSize(pInfo->aggSup.pResultRowHashTable);
58✔
1377
  tlen += taosEncodeFixedI32(buf, mapSize);
58✔
1378
  void*   pIte = NULL;
58✔
1379
  size_t  keyLen = 0;
58✔
1380
  int32_t iter = 0;
58✔
1381
  while ((pIte = tSimpleHashIterate(pInfo->aggSup.pResultRowHashTable, pIte, &iter)) != NULL) {
96✔
1382
    void* key = tSimpleHashGetKey(pIte, &keyLen);
38✔
1383
    tlen += encodeSWinKey(buf, key);
38✔
1384
  }
1385

1386
  // 2.twAggSup
1387
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
58✔
1388

1389
  // 3.pPullDataMap
1390
  int32_t size = taosHashGetSize(pInfo->pPullDataMap);
58✔
1391
  tlen += taosEncodeFixedI32(buf, size);
58✔
1392
  pIte = NULL;
58✔
1393
  keyLen = 0;
58✔
1394
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
58!
1395
    void* key = taosHashGetKey(pIte, &keyLen);
×
1396
    tlen += encodeSWinKey(buf, key);
×
1397
    SArray* pArray = *(SArray**)pIte;
×
1398
    int32_t chSize = taosArrayGetSize(pArray);
×
1399
    tlen += taosEncodeFixedI32(buf, chSize);
×
1400
    for (int32_t i = 0; i < chSize; i++) {
×
1401
      void* pChItem = taosArrayGet(pArray, i);
×
1402
      tlen += taosEncodeFixedI32(buf, *(int32_t*)pChItem);
×
1403
    }
1404
  }
1405

1406
  // 4.pPullWins
1407
  tlen += encodeSPullWindowInfoArray(buf, pInfo->pPullWins);
58✔
1408

1409
  // 5.dataVersion
1410
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
58✔
1411

1412
  // 6.basicInfo
1413
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
58✔
1414

1415
  // 7.checksum
1416
  if (buf) {
58✔
1417
    uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
58!
1418
    tlen += taosEncodeFixedU32(buf, cksum);
29✔
1419
  } else {
1420
    tlen += sizeof(uint32_t);
29✔
1421
  }
1422

1423
  return tlen;
58✔
1424
}
1425

1426
void doStreamIntervalDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator) {
4✔
1427
  int32_t                      code = TSDB_CODE_SUCCESS;
4✔
1428
  int32_t                      lino = 0;
4✔
1429
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
4✔
1430
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4✔
1431
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
4✔
1432
  if (!pInfo) {
4!
1433
    code = TSDB_CODE_FAILED;
×
1434
    QUERY_CHECK_CODE(code, lino, _end);
×
1435
  }
1436

1437
  // 7.checksum
1438
  int32_t dataLen = len - sizeof(uint32_t);
4✔
1439
  void*   pCksum = POINTER_SHIFT(buf, dataLen);
4✔
1440
  if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
8!
1441
    code = TSDB_CODE_FAILED;
×
1442
    QUERY_CHECK_CODE(code, lino, _end);
×
1443
  }
1444
  pDataEnd = pCksum;
4✔
1445

1446
  // 1.pResultRowHashTable
1447
  int32_t mapSize = 0;
4✔
1448
  buf = taosDecodeFixedI32(buf, &mapSize);
4!
1449
  for (int32_t i = 0; i < mapSize; i++) {
6✔
1450
    SWinKey key = {0};
2✔
1451
    buf = decodeSWinKey(buf, &key);
2✔
1452
    SRowBuffPos* pPos = NULL;
2✔
1453
    int32_t      resSize = pInfo->aggSup.resultRowSize;
2✔
1454
    int32_t      winCode = TSDB_CODE_SUCCESS;
2✔
1455
    code = pInfo->stateStore.streamStateAddIfNotExist(pInfo->pState, &key, (void**)&pPos, &resSize, &winCode);
2✔
1456
    QUERY_CHECK_CODE(code, lino, _end);
2!
1457
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
2!
1458

1459
    code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pPos, POINTER_BYTES);
2✔
1460
    QUERY_CHECK_CODE(code, lino, _end);
2!
1461
  }
1462

1463
  // 2.twAggSup
1464
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
4✔
1465

1466
  // 3.pPullDataMap
1467
  int32_t size = 0;
4✔
1468
  buf = taosDecodeFixedI32(buf, &size);
4!
1469
  for (int32_t i = 0; i < size; i++) {
4!
1470
    SWinKey key = {0};
×
1471
    SArray* pArray = taosArrayInit(0, sizeof(int32_t));
×
1472
    if (!pArray) {
×
1473
      code = terrno;
×
1474
      QUERY_CHECK_CODE(code, lino, _end);
×
1475
    }
1476

1477
    buf = decodeSWinKey(buf, &key);
×
1478
    int32_t chSize = 0;
×
1479
    buf = taosDecodeFixedI32(buf, &chSize);
×
1480
    for (int32_t i = 0; i < chSize; i++) {
×
1481
      int32_t chId = 0;
×
1482
      buf = taosDecodeFixedI32(buf, &chId);
×
1483
      void* tmp = taosArrayPush(pArray, &chId);
×
1484
      if (!tmp) {
×
1485
        code = terrno;
×
1486
        QUERY_CHECK_CODE(code, lino, _end);
×
1487
      }
1488
    }
1489
    code = taosHashPut(pInfo->pPullDataMap, &key, sizeof(SWinKey), &pArray, POINTER_BYTES);
×
1490
    QUERY_CHECK_CODE(code, lino, _end);
×
1491
  }
1492

1493
  // 4.pPullWins
1494
  code = decodeSPullWindowInfoArray(buf, pInfo->pPullWins, &buf);
4✔
1495
  QUERY_CHECK_CODE(code, lino, _end);
4!
1496

1497
  // 5.dataVersion
1498
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
4!
1499

1500
  // 6.basicInfo
1501
  if (buf < pDataEnd) {
4!
1502
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
4✔
1503
    QUERY_CHECK_CODE(code, lino, _end);
4!
1504
  }
1505

1506
_end:
4✔
1507
  if (code != TSDB_CODE_SUCCESS) {
4!
1508
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1509
  }
1510
}
4✔
1511

1512
void doStreamIntervalSaveCheckpoint(SOperatorInfo* pOperator) {
1,192✔
1513
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,192✔
1514
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
1,192✔
1515
    int32_t len = doStreamIntervalEncodeOpState(NULL, 0, pOperator);
29✔
1516
    void*   buf = taosMemoryCalloc(1, len);
29!
1517
    if (!buf) {
29!
1518
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1519
      return;
×
1520
    }
1521
    void* pBuf = buf;
29✔
1522
    len = doStreamIntervalEncodeOpState(&pBuf, len, pOperator);
29✔
1523
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
29✔
1524
                                          strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), buf, len);
1525
    taosMemoryFree(buf);
29!
1526
    saveStreamOperatorStateComplete(&pInfo->basic);
29✔
1527
  }
1528
}
1529

1530
int32_t copyIntervalDeleteKey(SSHashObj* pMap, SArray* pWins) {
62✔
1531
  int32_t code = TSDB_CODE_SUCCESS;
62✔
1532
  int32_t lino = 0;
62✔
1533
  void*   pIte = NULL;
62✔
1534
  int32_t iter = 0;
62✔
1535
  while ((pIte = tSimpleHashIterate(pMap, pIte, &iter)) != NULL) {
83✔
1536
    void* pKey = tSimpleHashGetKey(pIte, NULL);
21✔
1537
    void* tmp = taosArrayPush(pWins, pKey);
21✔
1538
    if (!tmp) {
21!
1539
      code = terrno;
×
1540
      QUERY_CHECK_CODE(code, lino, _end);
×
1541
    }
1542
  }
1543
  tSimpleHashClear(pMap);
62✔
1544

1545
_end:
62✔
1546
  if (code != TSDB_CODE_SUCCESS) {
62!
1547
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1548
  }
1549
  return code;
62✔
1550
}
1551

1552
static int32_t buildIntervalResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
31,598✔
1553
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
31,598✔
1554
  int32_t                      code = TSDB_CODE_SUCCESS;
31,598✔
1555
  int32_t                      lino = 0;
31,598✔
1556
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
31,598✔
1557
  uint16_t                     opType = pOperator->operatorType;
31,598✔
1558
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
31,598✔
1559
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
31,598✔
1560
  bool                         addNotifyEvent = false;
31,598✔
1561

1562
  // check if query task is closed or not
1563
  if (isTaskKilled(pTaskInfo)) {
31,598✔
1564
    (*ppRes) = NULL;
2✔
1565
    return code;
2✔
1566
  }
1567

1568
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
53,086✔
1569
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
21,490!
1570
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
31,596✔
1571
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
2,895✔
1572
    if (pInfo->pPullDataRes->info.rows != 0) {
2,895✔
1573
      // process the rest of the data
1574
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
144✔
1575
      (*ppRes) = pInfo->pPullDataRes;
144✔
1576
      return code;
144✔
1577
    }
1578
  }
1579

1580
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
31,452✔
1581
  if (pInfo->pDelRes->info.rows != 0) {
31,452✔
1582
    // process the rest of the data
1583
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
402✔
1584
    if (addNotifyEvent) {
400!
1585
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
1586
      QUERY_CHECK_CODE(code, lino, _end);
×
1587
    }
1588
    (*ppRes) = pInfo->pDelRes;
400✔
1589
    return code;
400✔
1590
  }
1591

1592
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo,
31,050!
1593
                              addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
1594
  if (pInfo->binfo.pRes->info.rows != 0) {
31,053✔
1595
    printDataBlock(pInfo->binfo.pRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
9,260✔
1596
    if (addNotifyEvent) {
9,260!
1597
      code = addAggResultNotifyEvent(pInfo->binfo.pRes, pNotifySup->pSessionKeys,
×
1598
                                     pTaskInfo->streamInfo.notifyResultSchema, pNotifySup, pNotifyEventStat);
×
1599
      QUERY_CHECK_CODE(code, lino, _end);
×
1600
    }
1601
    (*ppRes) = pInfo->binfo.pRes;
9,260✔
1602
    return code;
9,260✔
1603
  }
1604

1605
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
21,793✔
1606
  QUERY_CHECK_CODE(code, lino, _end);
21,792!
1607
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
21,792!
1608
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1609
    (*ppRes) = pNotifySup->pEventBlock;
×
1610
    return code;
×
1611
  }
1612

1613
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
21,792✔
1614
  QUERY_CHECK_CODE(code, lino, _end);
21,791!
1615

1616
_end:
21,791✔
1617
  if (code != TSDB_CODE_SUCCESS) {
21,791!
1618
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1619
  }
1620
  (*ppRes) = NULL;
21,793✔
1621
  return code;
21,793✔
1622
}
1623

1624
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
14,123✔
1625
  int32_t code = TSDB_CODE_SUCCESS;
14,123✔
1626
  int32_t lino = 0;
14,123✔
1627
  void*   pIte = NULL;
14,123✔
1628
  int32_t iter = 0;
14,123✔
1629
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
463,995✔
1630
    void* tmp = taosArrayPush(pUpdated, pIte);
449,872✔
1631
    if (!tmp) {
449,872!
1632
      code = terrno;
×
1633
      QUERY_CHECK_CODE(code, lino, _end);
×
1634
    }
1635
  }
1636
  taosArraySort(pUpdated, compar);
14,125✔
1637
  tSimpleHashCleanup(*ppWinUpdated);
14,121✔
1638
  *ppWinUpdated = NULL;
14,123✔
1639

1640
_end:
14,123✔
1641
  if (code != TSDB_CODE_SUCCESS) {
14,123!
1642
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1643
  }
1644
  return code;
14,120✔
1645
}
1646

1647
static int32_t doStreamFinalIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
9,819✔
1648
  int32_t                      code = TSDB_CODE_SUCCESS;
9,819✔
1649
  int32_t                      lino = 0;
9,819✔
1650
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
9,819✔
1651
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
9,819✔
1652
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
9,819✔
1653

1654
  SOperatorInfo* downstream = pOperator->pDownstream[0];
9,819✔
1655
  SExprSupp*     pSup = &pOperator->exprSupp;
9,819✔
1656

1657
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
9,819✔
1658

1659
  if (pOperator->status == OP_EXEC_DONE) {
9,818!
1660
    (*ppRes) = NULL;
×
1661
    return code;
×
1662
  } else if (pOperator->status == OP_RES_TO_RETURN) {
9,818✔
1663
    SSDataBlock* resBlock = NULL;
3,515✔
1664
    code = buildIntervalResult(pOperator, &resBlock);
3,515✔
1665
    QUERY_CHECK_CODE(code, lino, _end);
3,515!
1666
    if (resBlock != NULL) {
3,515✔
1667
      (*ppRes) = resBlock;
803✔
1668
      return code;
3,515✔
1669
    }
1670

1671
    if (pInfo->recvGetAll) {
2,712✔
1672
      pInfo->recvGetAll = false;
72✔
1673
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
72✔
1674
    }
1675

1676
    if (pInfo->reCkBlock) {
2,712!
1677
      pInfo->reCkBlock = false;
×
1678
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1679
      (*ppRes) = pInfo->pCheckpointRes;
×
1680
      return code;
×
1681
    }
1682

1683
    setStreamOperatorCompleted(pOperator);
2,712✔
1684
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
2,712✔
1685
      clearFunctionContext(&pOperator->exprSupp);
1,567✔
1686
      // semi interval operator clear disk buffer
1687
      clearStreamIntervalOperator(pInfo);
1,567✔
1688
      qDebug("===stream===clear semi operator");
1,567✔
1689
    }
1690
    (*ppRes) = NULL;
2,712✔
1691
    return code;
2,712✔
1692
  } else {
1693
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
6,303✔
1694
      SSDataBlock* resBlock = NULL;
4,400✔
1695
      code = buildIntervalResult(pOperator, &resBlock);
4,400✔
1696
      QUERY_CHECK_CODE(code, lino, _end);
4,401!
1697
      if (resBlock != NULL) {
4,401!
1698
        (*ppRes) = resBlock;
×
1699
        return code;
×
1700
      }
1701

1702
      if (pInfo->recvRetrive) {
4,401!
1703
        pInfo->recvRetrive = false;
×
1704
        printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1705
        (*ppRes) = pInfo->pMidRetriveRes;
×
1706
        return code;
×
1707
      }
1708
    }
1709
  }
1710

1711
  if (!pInfo->pUpdated) {
6,304✔
1712
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
4,916✔
1713
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
4,915!
1714
  }
1715
  if (!pInfo->pUpdatedMap) {
6,303✔
1716
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
4,915✔
1717
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
4,915✔
1718
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
4,917!
1719
  }
1720

1721
  while (1) {
21,539✔
1722
    if (isTaskKilled(pTaskInfo)) {
27,844!
1723
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
1724
      (*ppRes) = NULL;
×
1725
      return code;
1,388✔
1726
    }
1727

1728
    SSDataBlock* pBlock = NULL;
27,844✔
1729
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
27,844✔
1730
    QUERY_CHECK_CODE(code, lino, _end);
27,845!
1731

1732
    if (pBlock == NULL) {
27,845✔
1733
      pOperator->status = OP_RES_TO_RETURN;
4,431✔
1734
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
4,431✔
1735
             pInfo->numOfDatapack);
1736
      pInfo->numOfDatapack = 0;
4,431✔
1737
      break;
4,431✔
1738
    }
1739

1740
    pInfo->numOfDatapack++;
23,414✔
1741
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
23,414✔
1742
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
23,414✔
1743

1744
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
23,414✔
1745
      pInfo->binfo.pRes->info.type = pBlock->info.type;
19,537✔
1746
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
3,877✔
1747
               pBlock->info.type == STREAM_CLEAR) {
3,673✔
1748
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
380✔
1749
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
380!
1750
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
380✔
1751
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
380✔
1752
      QUERY_CHECK_CODE(code, lino, _end);
380!
1753

1754
      if (IS_FINAL_INTERVAL_OP(pOperator)) {
380✔
1755
        int32_t chId = getChildIndex(pBlock);
190✔
1756
        code = addRetriveWindow(delWins, pInfo, chId);
190✔
1757
        QUERY_CHECK_CODE(code, lino, _end);
190!
1758

1759
        if (pBlock->info.type != STREAM_CLEAR) {
190✔
1760
          void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
102✔
1761
          if (!tmp && taosArrayGetSize(delWins) > 0) {
102!
1762
            code = TSDB_CODE_OUT_OF_MEMORY;
×
1763
            QUERY_CHECK_CODE(code, lino, _end);
×
1764
          }
1765
        }
1766
        taosArrayDestroy(delWins);
190✔
1767
        continue;
1,350✔
1768
      }
1769
      removeResults(delWins, pInfo->pUpdatedMap);
190✔
1770
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
190✔
1771
      if (!tmp && taosArrayGetSize(delWins) > 0) {
190!
1772
        code = TSDB_CODE_OUT_OF_MEMORY;
×
1773
        QUERY_CHECK_CODE(code, lino, _end);
×
1774
      }
1775
      taosArrayDestroy(delWins);
190✔
1776

1777
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
190✔
1778
      if (pInfo->pDelRes->info.rows != 0) {
190!
1779
        // process the rest of the data
1780
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
190✔
1781
        if (pBlock->info.type == STREAM_CLEAR) {
190✔
1782
          pInfo->pDelRes->info.type = STREAM_CLEAR;
88✔
1783
        } else {
1784
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
102✔
1785
        }
1786
        (*ppRes) = pInfo->pDelRes;
190✔
1787
        return code;
190✔
1788
      }
1789

1790
      break;
×
1791
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
3,497!
1792
      pInfo->recvGetAll = true;
72✔
1793
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
72✔
1794
      QUERY_CHECK_CODE(code, lino, _end);
72!
1795
      continue;
72✔
1796
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
3,425✔
1797
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
486!
1798
        pInfo->recvRetrive = true;
486✔
1799
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
486✔
1800
        QUERY_CHECK_CODE(code, lino, _end);
486!
1801

1802
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
486✔
1803
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
486✔
1804
        QUERY_CHECK_CODE(code, lino, _end);
485!
1805
        break;
485✔
1806
      }
1807
      continue;
×
1808
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
2,939!
1809
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
480✔
1810
                             pInfo->numOfChild, pOperator, NULL);
1811
      QUERY_CHECK_CODE(code, lino, _end);
480!
1812
      continue;
480✔
1813
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
2,459✔
1814
      (*ppRes) = pBlock;
1,198✔
1815
      return code;
1,198✔
1816
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,261✔
1817
      pAPI->stateStore.streamStateCommit(pInfo->pState);
122✔
1818
      doStreamIntervalSaveCheckpoint(pOperator);
122✔
1819
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
122✔
1820
      QUERY_CHECK_CODE(code, lino, _end);
122!
1821

1822
      continue;
122✔
1823
    } else if (IS_FINAL_INTERVAL_OP(pOperator) && pBlock->info.type == STREAM_MID_RETRIEVE) {
1,139✔
1824
      continue;
486✔
1825
    } else {
1826
      if (pBlock->info.type != STREAM_INVALID) {
653!
1827
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1828
        QUERY_CHECK_CODE(code, lino, _end);
×
1829
      }
1830
    }
1831

1832
    if (pInfo->scalarSupp.pExprInfo != NULL) {
20,190!
1833
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
1834
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
1835
      QUERY_CHECK_CODE(code, lino, _end);
×
1836
    }
1837
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
20,190✔
1838
    QUERY_CHECK_CODE(code, lino, _end);
20,190!
1839

1840
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
20,190✔
1841
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
20,189!
1842
      code = TSDB_CODE_SUCCESS;
×
1843
      pOperator->status = OP_RES_TO_RETURN;
×
1844
      break;
×
1845
    }
1846
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
20,189✔
1847
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
20,189✔
1848
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
20,189✔
1849
  }
1850

1851
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
4,916✔
1852
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,302✔
1853
  }
1854
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
4,916✔
1855
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,304✔
1856
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1857
    QUERY_CHECK_CODE(code, lino, _end);
1,304!
1858

1859
    if (pInfo->destHasPrimaryKey) {
1,304✔
1860
      code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
2✔
1861
      QUERY_CHECK_CODE(code, lino, _end);
2!
1862
    }
1863
  }
1864
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
4,916✔
1865

1866
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
4,916✔
1867
  QUERY_CHECK_CODE(code, lino, _end);
4,917!
1868

1869
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
4,917✔
1870
  pInfo->pUpdated = NULL;
4,917✔
1871
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
4,917✔
1872
  QUERY_CHECK_CODE(code, lino, _end);
4,917!
1873

1874
  SSDataBlock* resBlock = NULL;
4,917✔
1875
  code = buildIntervalResult(pOperator, &resBlock);
4,917✔
1876
  QUERY_CHECK_CODE(code, lino, _end);
4,916!
1877
  if (resBlock != NULL) {
4,916✔
1878
    (*ppRes) = resBlock;
2,712✔
1879
    return code;
2,712✔
1880
  }
1881

1882
  if (pInfo->recvRetrive) {
2,204✔
1883
    pInfo->recvRetrive = false;
486✔
1884
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
486✔
1885
    (*ppRes) = pInfo->pMidRetriveRes;
486✔
1886
    return code;
486✔
1887
  }
1888

1889
_end:
1,718✔
1890
  if (code != TSDB_CODE_SUCCESS) {
1,718!
1891
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1892
    pTaskInfo->code = code;
×
1893
    T_LONG_JMP(pTaskInfo->env, code);
×
1894
  }
1895
  setStreamOperatorCompleted(pOperator);
1,718✔
1896
  (*ppRes) = NULL;
1,719✔
1897
  return code;
1,719✔
1898
}
1899

1900
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
5,257✔
1901
  if (pWinPhyNode->deleteMark <= 0) {
5,257✔
1902
    return DEAULT_DELETE_MARK;
3,200✔
1903
  }
1904
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
2,057✔
1905
  deleteMark = TMAX(deleteMark, interval);
2,057✔
1906
  return deleteMark;
2,057✔
1907
}
1908

1909
int64_t getDeleteMarkFromOption(SStreamNodeOption* pOption) {
216✔
1910
  if (pOption->deleteMark <= 0) {
216!
1911
    return DEAULT_DELETE_MARK;
216✔
1912
  }
1913
  int64_t deleteMark = TMAX(pOption->deleteMark, pOption->watermark);
×
1914
  return deleteMark;
×
1915
}
1916

1917
TSKEY compareTs(void* pKey) {
23,747,326✔
1918
  SWinKey* pWinKey = (SWinKey*)pKey;
23,747,326✔
1919
  return pWinKey->ts;
23,747,326✔
1920
}
1921

1922
static int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
219,224✔
1923
  if (pCtx->subsidiaries.rowLen == 0) {
219,224!
1924
    int32_t rowLen = 0;
219,224✔
1925
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
219,615✔
1926
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
391✔
1927
      rowLen += pc->pExpr->base.resSchema.bytes;
391✔
1928
    }
1929

1930
    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
219,224✔
1931
  } else {
1932
    return pCtx->subsidiaries.rowLen;
×
1933
  }
1934
}
1935

1936
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
5,478✔
1937
  int32_t size = 0;
5,478✔
1938
  for (int32_t i = 0; i < numOfCols; ++i) {
224,702✔
1939
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
219,224✔
1940
    size = TMAX(size, resSize);
219,224✔
1941
  }
1942
  return size;
5,478✔
1943
}
1944

1945
static void streamIntervalReleaseState(SOperatorInfo* pOperator) {
1,141✔
1946
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,141✔
1947
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,059✔
1948
    SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,049✔
1949
    int32_t                      resSize = sizeof(TSKEY);
1,049✔
1950
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,049✔
1951
                                          strlen(STREAM_INTERVAL_OP_STATE_NAME), &pInfo->twAggSup.maxTs, resSize);
1,049✔
1952
  }
1953
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,141✔
1954
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
1,141✔
1955
  pAPI->stateStore.streamStateCommit(pInfo->pState);
1,141✔
1956
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,141✔
1957
  if (downstream->fpSet.releaseStreamStateFn) {
1,141!
1958
    downstream->fpSet.releaseStreamStateFn(downstream);
1,141✔
1959
  }
1960
}
1,141✔
1961

1962
void streamIntervalReloadState(SOperatorInfo* pOperator) {
1,141✔
1963
  int32_t                      code = TSDB_CODE_SUCCESS;
1,141✔
1964
  int32_t                      lino = 0;
1,141✔
1965
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,141✔
1966
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1,141✔
1967
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,141✔
1968
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,059✔
1969
    int32_t size = 0;
1,049✔
1970
    void*   pBuf = NULL;
1,049✔
1971
    code = pInfo->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,049✔
1972
                                                strlen(STREAM_INTERVAL_OP_STATE_NAME), &pBuf, &size);
1973
    QUERY_CHECK_CODE(code, lino, _end);
1,049!
1974

1975
    TSKEY ts = *(TSKEY*)pBuf;
1,049✔
1976
    taosMemoryFree(pBuf);
1,049!
1977
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
1,049✔
1978
    pInfo->stateStore.streamStateReloadInfo(pInfo->pState, ts);
1,049✔
1979
  }
1980
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,141✔
1981
  if (downstream->fpSet.reloadStreamStateFn) {
1,141!
1982
    downstream->fpSet.reloadStreamStateFn(downstream);
1,141✔
1983
  }
1984
  reloadFromDownStream(downstream, pInfo);
1,141✔
1985

1986
_end:
1,141✔
1987
  if (code != TSDB_CODE_SUCCESS) {
1,141!
1988
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1989
  }
1990
}
1,141✔
1991

1992
int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
847✔
1993
                                              int32_t numOfChild, SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
1994
  QRY_PARAM_CHECK(pOptrInfo);
847!
1995

1996
  int32_t                      code = TSDB_CODE_SUCCESS;
847✔
1997
  int32_t                      lino = 0;
847✔
1998
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
847✔
1999
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
847!
2000
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
849!
2001
  if (pInfo == NULL || pOperator == NULL) {
849!
2002
    code = terrno;
×
2003
    QUERY_CHECK_CODE(code, lino, _error);
×
2004
  }
2005

2006
  pOperator->exprSupp.hasWindowOrGroup = true;
849✔
2007
  pOperator->pTaskInfo = pTaskInfo;
849✔
2008
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
849✔
2009

2010
  pInfo->interval = (SInterval){.interval = pIntervalPhyNode->interval,
849✔
2011
                                .sliding = pIntervalPhyNode->sliding,
849✔
2012
                                .intervalUnit = pIntervalPhyNode->intervalUnit,
849✔
2013
                                .slidingUnit = pIntervalPhyNode->slidingUnit,
849✔
2014
                                .offset = pIntervalPhyNode->offset,
849✔
2015
                                .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
849✔
2016
                                .timeRange = pIntervalPhyNode->timeRange};
849✔
2017
  calcIntervalAutoOffset(&pInfo->interval);
849✔
2018
  pInfo->twAggSup = (STimeWindowAggSupp){
849✔
2019
      .waterMark = pIntervalPhyNode->window.watermark,
849✔
2020
      .calTrigger = pIntervalPhyNode->window.triggerType,
849✔
2021
      .maxTs = INT64_MIN,
2022
      .minTs = INT64_MAX,
2023
      .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval),
849✔
2024
      .deleteMarkSaved = 0,
2025
      .calTriggerSaved = 0,
2026
  };
2027
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
849✔
2028
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
849✔
2029
  initResultSizeInfo(&pOperator->resultInfo, 4096);
849✔
2030
  if (pIntervalPhyNode->window.pExprs != NULL) {
849!
2031
    int32_t    numOfScalar = 0;
×
2032
    SExprInfo* pScalarExprInfo = NULL;
×
2033

2034
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
×
2035
    QUERY_CHECK_CODE(code, lino, _error);
×
2036

2037
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
×
2038
    QUERY_CHECK_CODE(code, lino, _error);
×
2039
  }
2040

2041
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
849✔
2042
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
849!
2043
  initBasicInfo(&pInfo->binfo, pResBlock);
849✔
2044

2045
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
849!
2046
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
849!
2047
  qInfo("open state %p", pInfo->pState);
849!
2048
  pAPI->stateStore.streamStateCopyBackend(pTaskInfo->streamInfo.pState, pInfo->pState);
849✔
2049
  //*(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2050

2051
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
849!
2052

2053
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
849✔
2054

2055
  int32_t    numOfCols = 0;
849✔
2056
  SExprInfo* pExprInfo = NULL;
849✔
2057
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
849✔
2058
  QUERY_CHECK_CODE(code, lino, _error);
849!
2059

2060
  code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
849✔
2061
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
849✔
2062
  QUERY_CHECK_CODE(code, lino, _error);
849!
2063

2064
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
849✔
2065
  QUERY_CHECK_CODE(code, lino, _error);
849!
2066
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
849✔
2067

2068
  pInfo->numOfChild = numOfChild;
849✔
2069
  pInfo->pPhyNode = NULL;
849✔
2070
  code = nodesCloneNode((SNode*)pPhyNode, (SNode**)&pInfo->pPhyNode);
849✔
2071
  if (TSDB_CODE_SUCCESS != code) {
849!
2072
    goto _error;
×
2073
  }
2074

2075
  pInfo->pPullWins = taosArrayInit(8, sizeof(SPullWindowInfo));
849✔
2076
  QUERY_CHECK_NULL(pInfo->pPullWins, code, lino, _error, terrno);
849!
2077
  pInfo->pullIndex = 0;
849✔
2078
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
849✔
2079
  pInfo->pPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
849✔
2080
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
849✔
2081

2082
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
849✔
2083
  QUERY_CHECK_CODE(code, lino, _error);
849!
2084

2085
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
849✔
2086
  pInfo->ignoreExpiredDataSaved = false;
849✔
2087
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
849✔
2088
  QUERY_CHECK_CODE(code, lino, _error);
849!
2089

2090
  pInfo->delIndex = 0;
849✔
2091
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
849✔
2092
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
849!
2093
  pInfo->delKey.ts = INT64_MAX;
849✔
2094
  pInfo->delKey.groupId = 0;
849✔
2095
  pInfo->numOfDatapack = 0;
849✔
2096
  pInfo->pUpdated = NULL;
849✔
2097
  pInfo->pUpdatedMap = NULL;
849✔
2098
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
849✔
2099
  int32_t funResSize = getMaxFunResSize(&pOperator->exprSupp, numOfCols);
849✔
2100
  pInfo->pState->pFileState = NULL;
849✔
2101

2102
  // used for backward compatibility of function's result info
2103
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
849✔
2104
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
849✔
2105
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
849✔
2106

2107
  code =
2108
      pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
849✔
2109
                                           compareTs, pInfo->pState, pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo),
849✔
2110
                                           pHandle->checkpointId, STREAM_STATE_BUFF_HASH, &pInfo->pState->pFileState);
849✔
2111
  QUERY_CHECK_CODE(code, lino, _error);
849!
2112

2113
  pInfo->dataVersion = 0;
849✔
2114
  pInfo->recvGetAll = false;
849✔
2115
  pInfo->recvPullover = false;
849✔
2116
  pInfo->recvRetrive = false;
849✔
2117

2118
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
849✔
2119
  QUERY_CHECK_CODE(code, lino, _error);
849!
2120
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidRetriveRes);
849✔
2121
  QUERY_CHECK_CODE(code, lino, _error);
849!
2122
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidPulloverRes);
849✔
2123
  QUERY_CHECK_CODE(code, lino, _error);
849!
2124

2125
  pInfo->clearState = false;
849✔
2126
  pInfo->pMidPullDatas = taosArrayInit(4, sizeof(SWinKey));
849✔
2127
  QUERY_CHECK_NULL(pInfo->pMidPullDatas, code, lino, _error, terrno);
849!
2128
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
849✔
2129
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
849!
2130
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
849✔
2131
  pInfo->pOperator = pOperator;
849✔
2132

2133
  pOperator->operatorType = pPhyNode->type;
849✔
2134
  if (!IS_FINAL_INTERVAL_OP(pOperator) || numOfChild == 0) {
849!
2135
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
639✔
2136
  }
2137
  pOperator->name = getStreamOpName(pOperator->operatorType);
849✔
2138
  pOperator->blocking = true;
849✔
2139
  pOperator->status = OP_NOT_OPENED;
849✔
2140
  pOperator->info = pInfo;
849✔
2141

2142
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
849✔
2143
    pOperator->fpSet =
2144
        createOperatorFpSet(NULL, doStreamMidIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
22✔
2145
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2146
  } else {
2147
    pOperator->fpSet =
2148
        createOperatorFpSet(NULL, doStreamFinalIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
827✔
2149
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2150
  }
2151
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
849✔
2152

2153
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
849✔
2154
  QUERY_CHECK_CODE(code, lino, _error);
849!
2155

2156
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL ||
849✔
2157
      pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
232✔
2158
    pInfo->basic.primaryPkIndex = -1;
639✔
2159
    code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
639✔
2160
    QUERY_CHECK_CODE(code, lino, _error);
639!
2161
  }
2162
  code = appendDownstream(pOperator, &downstream, 1);
849✔
2163
  QUERY_CHECK_CODE(code, lino, _error);
849!
2164

2165
  // for stream
2166
  void*   buff = NULL;
849✔
2167
  int32_t len = 0;
849✔
2168
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
849✔
2169
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
2170
  if (res == TSDB_CODE_SUCCESS) {
849✔
2171
    doStreamIntervalDecodeOpState(buff, len, pOperator);
1✔
2172
    taosMemoryFree(buff);
1!
2173
  }
2174

2175
  *pOptrInfo = pOperator;
849✔
2176
  return TSDB_CODE_SUCCESS;
849✔
2177

2178
_error:
×
2179
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
2180
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
2181
  pTaskInfo->code = code;
×
2182
  return code;
×
2183
}
2184

2185
void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
1,743✔
2186
  tSimpleHashCleanup(pSup->pResultRows);
1,743✔
2187
  destroyDiskbasedBuf(pSup->pResultBuf);
1,743✔
2188
  blockDataDestroy(pSup->pScanBlock);
1,743✔
2189
  if (pSup->stateStore.streamFileStateDestroy != NULL) {
1,743!
2190
    pSup->stateStore.streamFileStateDestroy(pSup->pState->pFileState);
1,743✔
2191
  }
2192
  taosMemoryFreeClear(pSup->pState);
1,743!
2193
  taosMemoryFreeClear(pSup->pDummyCtx);
1,743!
2194
}
1,743✔
2195

2196
void destroyStreamSessionAggOperatorInfo(void* param) {
870✔
2197
  if (param == NULL) {
870!
2198
    return;
×
2199
  }
2200
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
870✔
2201
  cleanupBasicInfo(&pInfo->binfo);
870✔
2202
  if (pInfo->pOperator) {
870!
2203
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
870✔
2204
                              &pInfo->groupResInfo);
2205
    pInfo->pOperator = NULL;
870✔
2206
  }
2207

2208
  destroyStreamBasicInfo(&pInfo->basic);
870✔
2209
  cleanupExprSupp(&pInfo->scalarSupp);
870✔
2210
  clearGroupResInfo(&pInfo->groupResInfo);
870✔
2211
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
870✔
2212
  pInfo->pUpdated = NULL;
870✔
2213
  destroyStreamAggSupporter(&pInfo->streamAggSup);
870✔
2214

2215
  if (pInfo->pChildren != NULL) {
870✔
2216
    int32_t size = taosArrayGetSize(pInfo->pChildren);
36✔
2217
    for (int32_t i = 0; i < size; i++) {
155✔
2218
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
119✔
2219
      destroyOperator(pChild);
119✔
2220
    }
2221
    taosArrayDestroy(pInfo->pChildren);
36✔
2222
  }
2223

2224
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
870✔
2225
  blockDataDestroy(pInfo->pDelRes);
870✔
2226
  blockDataDestroy(pInfo->pWinBlock);
870✔
2227
  tSimpleHashCleanup(pInfo->pStUpdated);
870✔
2228
  tSimpleHashCleanup(pInfo->pStDeleted);
870✔
2229
  cleanupGroupResInfo(&pInfo->groupResInfo);
870✔
2230

2231
  taosArrayDestroy(pInfo->historyWins);
870✔
2232
  blockDataDestroy(pInfo->pCheckpointRes);
870✔
2233
  tSimpleHashCleanup(pInfo->pPkDeleted);
870✔
2234

2235
  taosMemoryFreeClear(param);
870!
2236
}
2237

2238
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
1,457✔
2239
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
2240
  initBasicInfo(pBasicInfo, pResultBlock);
1,457✔
2241
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
1,457✔
2242
  if (code != TSDB_CODE_SUCCESS) {
1,456!
2243
    return code;
×
2244
  }
2245

2246
  for (int32_t i = 0; i < numOfCols; ++i) {
24,094✔
2247
    pSup->pCtx[i].saveHandle.pBuf = NULL;
22,638✔
2248
  }
2249

2250
  return TSDB_CODE_SUCCESS;
1,456✔
2251
}
2252

2253
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
1,743✔
2254
  for (int i = 0; i < nums; i++) {
25,659✔
2255
    pDummy[i].functionId = pCtx[i].functionId;
23,916✔
2256
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
23,916✔
2257
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
23,916✔
2258
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
23,916✔
2259
  }
2260
}
1,743✔
2261

2262
int32_t initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
1,752✔
2263
                       STimeWindowAggSupp* pTwSup, struct SSteamOpBasicInfo* pBasic) {
2264
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
1,752✔
2265
  int32_t        code = TSDB_CODE_SUCCESS;
1,752✔
2266
  int32_t        lino = 0;
1,752✔
2267
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
1,752✔
2268
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
414✔
2269
    pScanInfo->tsColIndex = tsColIndex;
414✔
2270
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
414✔
2271
  }
2272

2273
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
1,752✔
2274
    code = initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup, pBasic);
414✔
2275
    return code;
414✔
2276
  }
2277
  SStreamScanInfo* pScanInfo = downstream->info;
1,338✔
2278
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
1,338✔
2279
  pScanInfo->pState = pAggSup->pState;
1,338✔
2280
  if (!pScanInfo->pUpdateInfo) {
1,338✔
2281
    code = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark,
924✔
2282
                                              pScanInfo->igCheckUpdate, pScanInfo->pkColType, pScanInfo->pkColLen,
924✔
2283
                                              &pScanInfo->pUpdateInfo);
924✔
2284
    QUERY_CHECK_CODE(code, lino, _end);
924!
2285
  }
2286
  pScanInfo->twAggSup = *pTwSup;
1,338✔
2287
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
1,338✔
2288
  if (!hasSrcPrimaryKeyCol(pBasic)) {
1,338✔
2289
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
1,333✔
2290
  }
2291

2292
_end:
4✔
2293
  if (code != TSDB_CODE_SUCCESS) {
1,337!
2294
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2295
  }
2296
  return code;
1,337✔
2297
}
2298

2299
static TSKEY sesionTs(void* pKey) {
4,567✔
2300
  SSessionKey* pWinKey = (SSessionKey*)pKey;
4,567✔
2301
  return pWinKey->win.skey;
4,567✔
2302
}
2303

2304
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SExprSupp* pExpSup, int32_t numOfOutput, int64_t gap,
1,743✔
2305
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore,
2306
                               SReadHandle* pHandle, STimeWindowAggSupp* pTwAggSup, const char* taskIdStr,
2307
                               SStorageAPI* pApi, int32_t tsIndex, int8_t stateType, int32_t ratio) {
2308
  pSup->resultRowSize = (keySize + getResultRowSize(pExpSup->pCtx, numOfOutput)) * ratio;
1,743✔
2309
  int32_t lino = 0;
1,743✔
2310
  int32_t code = createSpecialDataBlock(STREAM_CLEAR, &pSup->pScanBlock);
1,743✔
2311
  QUERY_CHECK_CODE(code, lino, _end);
1,742!
2312

2313
  pSup->gap = gap;
1,742✔
2314
  pSup->stateKeySize = keySize;
1,742✔
2315
  pSup->stateKeyType = keyType;
1,742✔
2316
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
1,742!
2317
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
1,743!
2318

2319
  pSup->stateStore = *pStore;
1,743✔
2320
  pSup->pSessionAPI = pApi;
1,743✔
2321

2322
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
1,743✔
2323
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
1,743!
2324
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
1,743!
2325

2326
  *(pSup->pState) = *pState;
1,743✔
2327
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1, tsIndex);
1,743✔
2328
  int32_t funResSize = getMaxFunResSize(pExpSup, numOfOutput);
1,743✔
2329
  if (stateType != STREAM_STATE_BUFF_HASH_SORT) {
1,743✔
2330
    // used for backward compatibility of function's result info
2331
    pSup->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
1,527✔
2332
    pSup->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
1,527✔
2333
    pSup->pState->pExprSupp = pExpSup;
1,527✔
2334
  }
2335

2336
  if (stateType == STREAM_STATE_BUFF_SORT) {
1,743✔
2337
    pSup->pState->pFileState = NULL;
1,457✔
2338
    code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SSessionKey), pSup->resultRowSize,
1,457✔
2339
                                                funResSize, sesionTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
1,457✔
2340
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
1,457✔
2341
  } else if (stateType == STREAM_STATE_BUFF_HASH_SORT || stateType == STREAM_STATE_BUFF_HASH_SEARCH) {
286!
2342
    pSup->pState->pFileState = NULL;
286✔
2343
    code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pSup->resultRowSize, funResSize,
286✔
2344
                                                compareTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
286✔
2345
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
286✔
2346
  }
2347
  QUERY_CHECK_CODE(code, lino, _end);
1,743!
2348

2349
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
1,743✔
2350
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
1,743✔
2351
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
1,743!
2352

2353
  for (int32_t i = 0; i < numOfOutput; ++i) {
25,659✔
2354
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
23,916✔
2355
  }
2356

2357
_end:
1,743✔
2358
  if (code != TSDB_CODE_SUCCESS) {
1,743!
2359
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2360
  }
2361
  return code;
1,743✔
2362
}
2363

2364
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5,264✔
2365
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5,264✔
2366
    return true;
4,030✔
2367
  }
2368
  return false;
1,234✔
2369
}
2370

2371
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
4,545✔
2372
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
4,545✔
2373
}
2374

2375
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
4,328✔
2376
                         SSessionKey* pKey) {
2377
  pKey->win.skey = startTs;
4,328✔
2378
  pKey->win.ekey = endTs;
4,328✔
2379
  pKey->groupId = groupId;
4,328✔
2380
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
4,328✔
2381
  if (code != TSDB_CODE_SUCCESS) {
4,329✔
2382
    SET_SESSION_WIN_KEY_INVALID(pKey);
1,244✔
2383
  }
2384
}
4,329✔
2385

2386
bool isInvalidSessionWin(SResultWindowInfo* pWinInfo) { return pWinInfo->sessionWin.win.skey == 0; }
×
2387

2388
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
51,681✔
2389
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
51,681!
2390
    return true;
51,694✔
2391
  }
2392
  return false;
×
2393
}
2394

2395
void clearOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) { pAPI->streamStateClearBuff(pState, pPos); }
×
2396

2397
int32_t setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
3,154✔
2398
                            SResultWindowInfo* pCurWin, int32_t* pWinCode) {
2399
  int32_t code = TSDB_CODE_SUCCESS;
3,154✔
2400
  int32_t lino = 0;
3,154✔
2401
  pCurWin->sessionWin.groupId = groupId;
3,154✔
2402
  pCurWin->sessionWin.win.skey = startTs;
3,154✔
2403
  pCurWin->sessionWin.win.ekey = endTs;
3,154✔
2404
  int32_t size = pAggSup->resultRowSize;
3,154✔
2405
  code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin, pAggSup->gap,
3,154✔
2406
                                                             (void**)&pCurWin->pStatePos, &size, pWinCode);
3,154✔
2407
  QUERY_CHECK_CODE(code, lino, _end);
3,152!
2408

2409
  if (*pWinCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->sessionWin.win)) {
3,152!
2410
    *pWinCode = TSDB_CODE_FAILED;
×
2411
    clearOutputBuf(pAggSup->pState, pCurWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2412
  }
2413

2414
  if (*pWinCode == TSDB_CODE_SUCCESS) {
3,152✔
2415
    pCurWin->isOutput = true;
898✔
2416
    if (pCurWin->pStatePos->needFree) {
898✔
2417
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
136✔
2418
    }
2419
  } else {
2420
    pCurWin->sessionWin.win.skey = startTs;
2,254✔
2421
    pCurWin->sessionWin.win.ekey = endTs;
2,254✔
2422
  }
2423
  qDebug("===stream===set session window buff .start:%" PRId64 ",end:%" PRId64 ",groupid:%" PRIu64,
3,152✔
2424
         pCurWin->sessionWin.win.skey, pCurWin->sessionWin.win.ekey, pCurWin->sessionWin.groupId);
2425

2426
_end:
1,675✔
2427
  if (code != TSDB_CODE_SUCCESS) {
3,152!
2428
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2429
  }
2430
  return code;
3,152✔
2431
}
2432

2433
void getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo,
215✔
2434
                      int32_t* pWinCode) {
2435
  int32_t size = 0;
215✔
2436
  (*pWinCode) = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin,
430✔
2437
                                                                 (void**)&pWinInfo->pStatePos, &size);
215✔
2438
  if ((*pWinCode) != TSDB_CODE_SUCCESS) {
215✔
2439
    return;
184✔
2440
  }
2441

2442
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
31✔
2443
}
2444

2445
int32_t saveDeleteInfo(SArray* pWins, SSessionKey key) {
1,126✔
2446
  int32_t code = TSDB_CODE_SUCCESS;
1,126✔
2447
  int32_t lino = 0;
1,126✔
2448
  void*   res = taosArrayPush(pWins, &key);
1,126✔
2449
  if (!res) {
1,126!
2450
    code = terrno;
×
2451
    QUERY_CHECK_CODE(code, lino, _end);
×
2452
  }
2453

2454
_end:
1,126✔
2455
  if (code != TSDB_CODE_SUCCESS) {
1,126!
2456
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2457
  }
2458
  return code;
1,126✔
2459
}
2460

2461
int32_t saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
83✔
2462
  key.win.ekey = key.win.skey;
83✔
2463
  return tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
83✔
2464
}
2465

2466
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
12,251✔
2467
  pAPI->streamStateReleaseBuf(pState, pPos, false);
12,251✔
2468
}
12,249✔
2469

2470
void removeSessionResult(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SSHashObj* pResMap, SSessionKey* pKey) {
88✔
2471
  int32_t     code = TSDB_CODE_SUCCESS;
88✔
2472
  int32_t     lino = 0;
88✔
2473
  SSessionKey key = {0};
88✔
2474
  getSessionHashKey(pKey, &key);
88✔
2475
  void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
88✔
2476
  if (pVal) {
88✔
2477
    releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
4✔
2478
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
4✔
2479
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
4!
2480
  }
2481
  int32_t tmpRes = tSimpleHashRemove(pResMap, &key, sizeof(SSessionKey));
88✔
2482
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
88!
2483
}
88✔
2484

2485
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
11,174✔
2486
  *pHashKey = *pKey;
11,174✔
2487
  pHashKey->win.ekey = pKey->win.skey;
11,174✔
2488
}
11,174✔
2489

2490
void removeSessionDeleteResults(SSHashObj* pHashMap, SArray* pWins) {
7,581✔
2491
  if (tSimpleHashGetSize(pHashMap) == 0) {
7,581✔
2492
    return;
6,635✔
2493
  }
2494
  int32_t size = taosArrayGetSize(pWins);
949✔
2495
  for (int32_t i = 0; i < size; i++) {
2,110✔
2496
    SResultWindowInfo* pWin = taosArrayGet(pWins, i);
1,160✔
2497
    if (!pWin) continue;
1,160!
2498
    SSessionKey key = {0};
1,160✔
2499
    getSessionHashKey(&pWin->sessionWin, &key);
1,160✔
2500
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
1,160✔
2501
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,160!
2502
  }
2503
}
2504

2505
void removeSessionResults(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SArray* pWins) {
1,064✔
2506
  if (tSimpleHashGetSize(pHashMap) == 0) {
1,064✔
2507
    return;
807✔
2508
  }
2509
  int32_t size = taosArrayGetSize(pWins);
257✔
2510
  for (int32_t i = 0; i < size; i++) {
547✔
2511
    SSessionKey* pWin = taosArrayGet(pWins, i);
289✔
2512
    if (!pWin) continue;
289!
2513
    SSessionKey key = {0};
289✔
2514
    getSessionHashKey(pWin, &key);
289✔
2515
    void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
289✔
2516
    if (pVal) {
289✔
2517
      releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
199✔
2518
      int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
199✔
2519
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
199!
2520
    }
2521
  }
2522
}
2523

2524
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
3,130✔
2525
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2526
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2527
                                int32_t* pWinRos) {
2528
  int32_t code = TSDB_CODE_SUCCESS;
3,130✔
2529
  int32_t lino = 0;
3,130✔
2530
  for (int32_t i = start; i < rows; ++i) {
7,087✔
2531
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
4,035!
2532
      (*pWinRos) = i - start;
76✔
2533
      goto _end;
76✔
2534
    }
2535
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
3,957✔
2536
      if (pStDeleted && pWinInfo->isOutput) {
25!
2537
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
20✔
2538
        QUERY_CHECK_CODE(code, lino, _end);
20!
2539
      }
2540
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
25✔
2541
      pWinInfo->sessionWin.win.skey = pStartTs[i];
25✔
2542
    }
2543
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
3,957✔
2544
    if (pEndTs) {
3,957!
2545
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
3,958✔
2546
    }
2547
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
3,957✔
2548
  }
2549
  (*pWinRos) = rows - start;
3,052✔
2550

2551
_end:
3,128✔
2552
  if (code != TSDB_CODE_SUCCESS) {
3,128!
2553
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2554
  }
2555
  return code;
3,129✔
2556
}
2557

2558
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
9,143✔
2559
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
2560
  *pResult = (SResultRow*)pWinInfo->pStatePos->pRowBuff;
9,143✔
2561
  // set time window for current result
2562
  (*pResult)->win = pWinInfo->sessionWin.win;
9,143✔
2563
  return setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
9,143✔
2564
}
2565

2566
int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
9,062✔
2567
                           int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
2568
                           SOperatorInfo* pOperator, int64_t winDelta) {
2569
  int32_t        code = TSDB_CODE_SUCCESS;
9,062✔
2570
  int32_t        lino = 0;
9,062✔
2571
  SExprSupp*     pSup = &pOperator->exprSupp;
9,062✔
2572
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
9,062✔
2573
  code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
9,062✔
2574
  QUERY_CHECK_CODE(code, lino, _end);
9,064!
2575

2576
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
9,064✔
2577
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
9,066✔
2578

2579
_end:
9,064✔
2580
  if (code != TSDB_CODE_SUCCESS) {
9,064!
2581
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2582
  }
2583
  return code;
9,064✔
2584
}
2585

2586
void doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
1,207✔
2587
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
1,207✔
2588
  SSessionKey hashKey = {0};
1,206✔
2589
  getSessionHashKey(pKey, &hashKey);
1,206✔
2590
  int32_t tmpRes = tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
1,206✔
2591
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,207!
2592
}
1,207✔
2593

2594
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
12,556✔
2595
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
12,556✔
2596
  if (pVal) {
12,558✔
2597
    SResultWindowInfo* pWin = pVal;
607✔
2598
    pWinInfo->isOutput = pWin->isOutput;
607✔
2599
  }
2600
}
12,558✔
2601

2602
void getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
3,420✔
2603
                           SResultWindowInfo* pNextWin) {
2604
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
3,420✔
2605
  pNextWin->isOutput = true;
3,422✔
2606
  setSessionWinOutputInfo(pStUpdated, pNextWin);
3,422✔
2607
  int32_t size = 0;
3,422✔
2608
  pNextWin->sessionWin = pCurWin->sessionWin;
3,422✔
2609
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin,
3,422✔
2610
                                                                  (void**)&pNextWin->pStatePos, &size);
3,422✔
2611
  if (code != TSDB_CODE_SUCCESS) {
3,422✔
2612
    SET_SESSION_WIN_INVALID(*pNextWin);
2,986✔
2613
  }
2614
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,422✔
2615
}
3,422✔
2616

2617
int32_t compactTimeWindow(SExprSupp* pSup, SStreamAggSupporter* pAggSup, STimeWindowAggSupp* pTwAggSup,
19✔
2618
                          SExecTaskInfo* pTaskInfo, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
2619
                          SSHashObj* pStUpdated, SSHashObj* pStDeleted, bool addGap) {
2620
  int32_t     code = TSDB_CODE_SUCCESS;
19✔
2621
  int32_t     lino = 0;
19✔
2622
  SResultRow* pCurResult = NULL;
19✔
2623
  int32_t     numOfOutput = pSup->numOfExprs;
19✔
2624
  code = initSessionOutputBuf(pCurWin, &pCurResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
19✔
2625
  QUERY_CHECK_CODE(code, lino, _end);
19!
2626

2627
  SResultRow* pWinResult = NULL;
19✔
2628
  code = initSessionOutputBuf(pNextWin, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
19✔
2629
  QUERY_CHECK_CODE(code, lino, _end);
19!
2630

2631
  pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, pNextWin->sessionWin.win.ekey);
19✔
2632
  memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
19✔
2633

2634
  int64_t winDelta = 0;
19✔
2635
  if (addGap) {
19✔
2636
    winDelta = pAggSup->gap;
15✔
2637
  }
2638
  updateTimeWindowInfo(&pTwAggSup->timeWindowData, &pCurWin->sessionWin.win, winDelta);
19✔
2639
  code = compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pTwAggSup->timeWindowData);
19✔
2640
  QUERY_CHECK_CODE(code, lino, _end);
19✔
2641

2642
  int32_t tmpRes = tSimpleHashRemove(pStUpdated, &pNextWin->sessionWin, sizeof(SSessionKey));
17✔
2643
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
17!
2644

2645
  if (pNextWin->isOutput && pStDeleted) {
17!
2646
    qDebug("===stream=== save delete window info %" PRId64 ", %" PRIu64, pNextWin->sessionWin.win.skey,
16!
2647
           pNextWin->sessionWin.groupId);
2648
    code = saveDeleteRes(pStDeleted, pNextWin->sessionWin);
16✔
2649
    QUERY_CHECK_CODE(code, lino, _end);
16!
2650
  }
2651
  removeSessionResult(pAggSup, pStUpdated, pAggSup->pResultRows, &pNextWin->sessionWin);
17✔
2652
  doDeleteSessionWindow(pAggSup, &pNextWin->sessionWin);
17✔
2653
  releaseOutputBuf(pAggSup->pState, pNextWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
17✔
2654

2655
_end:
19✔
2656
  if (code != TSDB_CODE_SUCCESS) {
19✔
2657
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2658
  }
2659
  return code;
19✔
2660
}
2661

2662
static int32_t compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
3,304✔
2663
                                    SSHashObj* pStDeleted, bool addGap, int32_t* pWinNum) {
2664
  int32_t                        code = TSDB_CODE_SUCCESS;
3,304✔
2665
  int32_t                        lino = 0;
3,304✔
2666
  SExprSupp*                     pSup = &pOperator->exprSupp;
3,304✔
2667
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,304✔
2668
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
3,304✔
2669
  int32_t                        winNum = 0;
3,304✔
2670
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,304✔
2671
  SResultRow*                    pCurResult = NULL;
3,304✔
2672
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,304✔
2673
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,304✔
2674

2675
  // Just look for the window behind StartIndex
2676
  while (1) {
13✔
2677
    SResultWindowInfo winInfo = {0};
3,317✔
2678
    getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
3,317✔
2679
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
3,319✔
2680
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
15!
2681
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
3,304✔
2682
      break;
3,302✔
2683
    }
2684
    code =
2685
        compactTimeWindow(pSup, pAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, &winInfo, pStUpdated, pStDeleted, true);
15✔
2686
    QUERY_CHECK_CODE(code, lino, _end);
15✔
2687
    winNum++;
13✔
2688
  }
2689
  if (pWinNum) {
3,302✔
2690
    (*pWinNum) = winNum;
152✔
2691
  }
2692

2693
_end:
3,150✔
2694
  if (code != TSDB_CODE_SUCCESS) {
3,304✔
2695
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2696
  }
2697
  return code;
3,304✔
2698
}
2699

2700
static void compactSessionSemiWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin) {
25✔
2701
  SExprSupp*                     pSup = &pOperator->exprSupp;
25✔
2702
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
25✔
2703
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
25✔
2704
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
25✔
2705
  SResultRow*                    pCurResult = NULL;
25✔
2706
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
25✔
2707
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
25✔
2708
  // Just look for the window behind StartIndex
2709
  while (1) {
×
2710
    SResultWindowInfo winInfo = {0};
25✔
2711
    getNextSessionWinInfo(pAggSup, NULL, pCurWin, &winInfo);
25✔
2712
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
25!
2713
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
×
2714
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
25✔
2715
      break;
25✔
2716
    }
2717
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
×
2718
    memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
×
2719
    doDeleteSessionWindow(pAggSup, &winInfo.sessionWin);
×
2720
    releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2721
  }
2722
}
25✔
2723

2724
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
9,377✔
2725
  qDebug("===stream===try save session result skey:%" PRId64 ", ekey:%" PRId64 ".pos%d", pWinInfo->sessionWin.win.skey,
9,377✔
2726
         pWinInfo->sessionWin.win.ekey, pWinInfo->pStatePos->needFree);
2727
  return pAggSup->stateStore.streamStateSessionPut(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pStatePos,
9,377✔
2728
                                                   pAggSup->resultRowSize);
2729
}
2730

2731
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3,069✔
2732
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
2733
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,069✔
2734
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,069✔
2735
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,069✔
2736
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
3,069✔
2737
  int32_t                        code = TSDB_CODE_SUCCESS;
3,069✔
2738
  int32_t                        lino = 0;
3,069✔
2739
  SResultRow*                    pResult = NULL;
3,069✔
2740
  int32_t                        rows = pSDataBlock->info.rows;
3,069✔
2741
  int32_t                        winRows = 0;
3,069✔
2742
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,069✔
2743

2744
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,069✔
2745
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,069✔
2746
  if (pAggSup->winRange.ekey <= 0) {
3,069!
2747
    pAggSup->winRange.ekey = INT64_MAX;
×
2748
  }
2749

2750
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,069✔
2751
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,069✔
2752
  SColumnInfoData* pEndTsCol = NULL;
3,069✔
2753
  if (hasEndTs) {
3,069✔
2754
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
464✔
2755
  } else {
2756
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,605✔
2757
  }
2758

2759
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
3,069✔
2760

2761
  void*            pPkVal = NULL;
3,069✔
2762
  int32_t          pkLen = 0;
3,069✔
2763
  SColumnInfoData* pPkColDataInfo = NULL;
3,069✔
2764
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
3,069✔
2765
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
10✔
2766
  }
2767

2768
  for (int32_t i = 0; i < rows;) {
6,213✔
2769
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
3,146!
2770
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2771
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2772
    }
2773
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
3,318✔
2774
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
173✔
2775
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
173✔
2776
      i++;
13✔
2777
      continue;
13✔
2778
    }
2779
    SResultWindowInfo winInfo = {0};
3,132✔
2780
    int32_t           winCode = TSDB_CODE_SUCCESS;
3,132✔
2781
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo, &winCode);
3,132✔
2782
    QUERY_CHECK_CODE(code, lino, _end);
3,133!
2783

2784
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_SESSION_OP(pOperator) &&
3,131✔
2785
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
1,975!
2786
      code = addSessionAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &winInfo.sessionWin, &pInfo->basic.notifyEventSup,
×
2787
                                      pTaskInfo->streamInfo.pNotifyEventStat);
2788
      QUERY_CHECK_CODE(code, lino, _end);
×
2789
    }
2790

2791
    // coverity scan error
2792
    if (!winInfo.pStatePos) {
3,131!
2793
      continue;
×
2794
    }
2795
    setSessionWinOutputInfo(pStUpdated, &winInfo);
3,131✔
2796
    code = updateSessionWindowInfo(pAggSup, &winInfo, startTsCols, endTsCols, groupId, rows, i, pAggSup->gap,
3,131✔
2797
                                   pAggSup->pResultRows, pStUpdated, pStDeleted, &winRows);
2798
    QUERY_CHECK_CODE(code, lino, _end);
3,129!
2799

2800
    int64_t winDelta = 0;
3,129✔
2801
    if (addGap) {
3,129✔
2802
      winDelta = pAggSup->gap;
2,534✔
2803
    }
2804
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
3,129✔
2805
                              pOperator, winDelta);
2806
    QUERY_CHECK_CODE(code, lino, _end);
3,130!
2807

2808
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL);
3,130✔
2809
    QUERY_CHECK_CODE(code, lino, _end);
3,131✔
2810

2811
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,129✔
2812
    QUERY_CHECK_CODE(code, lino, _end);
3,129!
2813

2814
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
3,129!
2815
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
7✔
2816
      QUERY_CHECK_CODE(code, lino, _end);
6!
2817
    }
2818
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
3,128✔
2819
      code = saveResult(winInfo, pStUpdated);
2,268✔
2820
      QUERY_CHECK_CODE(code, lino, _end);
2,270!
2821
    }
2822
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,130✔
2823
      winInfo.pStatePos->beUpdated = true;
600✔
2824
      SSessionKey key = {0};
600✔
2825
      getSessionHashKey(&winInfo.sessionWin, &key);
600✔
2826
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
600✔
2827
      QUERY_CHECK_CODE(code, lino, _end);
600!
2828
    }
2829

2830
    i += winRows;
3,130✔
2831
  }
2832

2833
_end:
3,067✔
2834
  if (code != TSDB_CODE_SUCCESS) {
3,069✔
2835
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2836
  }
2837
}
3,069✔
2838

2839
int32_t doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
1,116✔
2840
  int32_t          code = TSDB_CODE_SUCCESS;
1,116✔
2841
  int32_t          lino = 0;
1,116✔
2842
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,116✔
2843
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
1,116✔
2844
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,116✔
2845
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
1,116✔
2846
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,116✔
2847
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
1,116✔
2848
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
2,288✔
2849
    while (1) {
1,152✔
2850
      SSessionKey curWin = {0};
2,324✔
2851
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
2,324✔
2852
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
2,325✔
2853
        break;
1,172✔
2854
      }
2855
      doDeleteSessionWindow(pAggSup, &curWin);
1,153✔
2856
      if (result) {
1,153✔
2857
        code = saveDeleteInfo(result, curWin);
1,110✔
2858
        QUERY_CHECK_CODE(code, lino, _end);
1,109!
2859
      }
2860
    }
2861
  }
2862

2863
_end:
1,116✔
2864
  if (code != TSDB_CODE_SUCCESS) {
1,116!
2865
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2866
  }
2867
  return code;
1,116✔
2868
}
2869

2870
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
2,936✔
2871
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
2,936✔
2872
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
2,936✔
2873
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
2,936✔
2874
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
2,936✔
2875

2876
  if (pWin1->groupId > pWin2->groupId) {
2,936✔
2877
    return 1;
418✔
2878
  } else if (pWin1->groupId < pWin2->groupId) {
2,518✔
2879
    return -1;
380✔
2880
  }
2881

2882
  if (pWin1->win.skey > pWin2->win.skey) {
2,138✔
2883
    return 1;
1,201✔
2884
  } else if (pWin1->win.skey < pWin2->win.skey) {
937!
2885
    return -1;
938✔
2886
  }
2887

2888
  return 0;
×
2889
}
2890

2891
static int32_t appendToDeleteDataBlock(SOperatorInfo* pOp, SSDataBlock *pBlock, SSessionKey *pKey) {
625✔
2892
  int32_t        code = TSDB_CODE_SUCCESS;
625✔
2893
  int32_t        lino = 0;
625✔
2894
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
625✔
2895

2896
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
625!
2897
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
625!
2898

2899
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
625✔
2900
  code = colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
625✔
2901
  QUERY_CHECK_CODE(code, lino, _end);
625!
2902

2903
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
625✔
2904
  code = colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
625✔
2905
  QUERY_CHECK_CODE(code, lino, _end);
625!
2906

2907
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
625✔
2908
  colDataSetNULL(pUidCol, pBlock->info.rows);
625!
2909

2910
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
625✔
2911
  code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&pKey->groupId, false);
625✔
2912
  QUERY_CHECK_CODE(code, lino, _end);
625!
2913

2914
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
625✔
2915
  colDataSetNULL(pCalStCol, pBlock->info.rows);
625!
2916

2917
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
625✔
2918
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
625!
2919

2920
  SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
625✔
2921
  if (!pTableCol) {
625!
2922
    QUERY_CHECK_CODE(code, lino, _end);
×
2923
  }
2924

2925
  void*        tbname = NULL;
625✔
2926
  int32_t      winCode = TSDB_CODE_SUCCESS;
625✔
2927
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;
625✔
2928
  code =
2929
      pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, pKey->groupId, &tbname, false, &winCode);
625✔
2930
  QUERY_CHECK_CODE(code, lino, _end);
625!
2931

2932
  if (winCode != TSDB_CODE_SUCCESS) {
625✔
2933
    colDataSetNULL(pTableCol, pBlock->info.rows);
237!
2934
  } else {
2935
    char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
2936
    STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
388✔
2937
    code = colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
388✔
2938
    QUERY_CHECK_CODE(code, lino, _end);
388!
2939
    pAPI->stateStore.streamStateFreeVal(tbname);
388✔
2940
  }
2941
  pBlock->info.rows += 1;
625✔
2942

2943
_end:
625✔
2944
  if (code != TSDB_CODE_SUCCESS) {
625!
2945
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2946
  }
2947
  return code;
625✔
2948
}
2949

2950
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite,
12,192✔
2951
                            SGroupResInfo* pGroupResInfo) {
2952
  int32_t        code = TSDB_CODE_SUCCESS;
12,192✔
2953
  int32_t        lino = 0;
12,192✔
2954
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
12,192✔
2955
  int64_t        minWindowSize = getMinWindowSize(pOp);
12,192✔
2956
  int32_t        numOfRows = getNumOfTotalRes(pGroupResInfo);
12,189✔
2957

2958
  blockDataCleanup(pBlock);
12,189✔
2959
  int32_t size = tSimpleHashGetSize(pStDeleted);
12,189✔
2960
  if (minWindowSize > 0) {
12,186✔
2961
    // Add the number of windows that are below the minimum width limit.
2962
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
239✔
2963
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
2964
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
2965
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
2966
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
2967
        size++;
60✔
2968
      }
2969
    }
2970
  }
2971
  if (size == 0) {
12,186✔
2972
    return;
11,688✔
2973
  }
2974
  code = blockDataEnsureCapacity(pBlock, size);
498✔
2975
  QUERY_CHECK_CODE(code, lino, _end);
498!
2976

2977
  int32_t iter = 0;
498✔
2978
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
1,063✔
2979
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
565!
2980
      break;
×
2981
    }
2982
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
565!
2983
    code = appendToDeleteDataBlock(pOp, pBlock, res);
565✔
2984
    QUERY_CHECK_CODE(code, lino, _end);
565!
2985
  }
2986

2987
  if (minWindowSize > 0) {
497✔
2988
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
138✔
2989
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
2990
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
2991
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
2992
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
2993
        code = appendToDeleteDataBlock(pOp, pBlock, pKey);
60✔
2994
        QUERY_CHECK_CODE(code, lino, _end);
60!
2995
      }
2996
    }
2997
    pGroupResInfo->delIndex = numOfRows;
18✔
2998
  }
2999

3000
_end:
479✔
3001
  if ((*Ite) == NULL) {
497!
3002
    tSimpleHashClear(pStDeleted);
498✔
3003
  }
3004

3005
  if (code != TSDB_CODE_SUCCESS) {
497!
3006
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3007
  }
3008
}
3009

3010
static int32_t rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
56✔
3011
  int32_t        winCode = TSDB_CODE_SUCCESS;
56✔
3012
  int32_t        code = TSDB_CODE_SUCCESS;
56✔
3013
  int32_t        lino = 0;
56✔
3014
  SExprSupp*     pSup = &pOperator->exprSupp;
56✔
3015
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
56✔
3016
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
56✔
3017

3018
  int32_t                        size = taosArrayGetSize(pWinArray);
56✔
3019
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
56✔
3020
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
56✔
3021
  int32_t                        numOfOutput = pSup->numOfExprs;
56✔
3022
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
56✔
3023

3024
  for (int32_t i = 0; i < size; i++) {
111✔
3025
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
55✔
3026
    int32_t           num = 0;
55✔
3027
    SResultWindowInfo parentWin = {0};
55✔
3028
    for (int32_t j = 0; j < numOfChild; j++) {
249✔
3029
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
194✔
3030
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
194✔
3031
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
194✔
3032
      SSessionKey                    chWinKey = {0};
194✔
3033
      getSessionHashKey(pWinKey, &chWinKey);
194✔
3034
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
194✔
3035
      SResultRow*      pResult = NULL;
194✔
3036
      SResultRow*      pChResult = NULL;
194✔
3037
      while (1) {
21✔
3038
        SResultWindowInfo childWin = {0};
215✔
3039
        childWin.sessionWin = *pWinKey;
215✔
3040
        getSessionWinBuf(pChAggSup, pCur, &childWin, &winCode);
215✔
3041

3042
        if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
215!
3043
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
×
3044
          continue;
×
3045
        }
3046

3047
        if (winCode == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
215✔
3048
          if (num == 0) {
21!
3049
            code = setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin,
21✔
3050
                                       &winCode);
3051
            QUERY_CHECK_CODE(code, lino, _end);
21!
3052

3053
            parentWin.sessionWin = childWin.sessionWin;
21✔
3054
            memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3055
            code = initSessionOutputBuf(&parentWin, &pResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
21✔
3056
            QUERY_CHECK_CODE(code, lino, _end);
21!
3057
          }
3058
          num++;
21✔
3059
          parentWin.sessionWin.win.skey = TMIN(parentWin.sessionWin.win.skey, childWin.sessionWin.win.skey);
21✔
3060
          parentWin.sessionWin.win.ekey = TMAX(parentWin.sessionWin.win.ekey, childWin.sessionWin.win.ekey);
21✔
3061
          memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3062

3063
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap);
21✔
3064
          code = initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
21✔
3065
                                      pChild->exprSupp.rowEntryInfoOffset);
3066
          QUERY_CHECK_CODE(code, lino, _end);
21!
3067

3068
          code = compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo,
21✔
3069
                                  &pInfo->twAggSup.timeWindowData);
3070
          QUERY_CHECK_CODE(code, lino, _end);
21!
3071

3072
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL);
21✔
3073
          QUERY_CHECK_CODE(code, lino, _end);
21!
3074

3075
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
21✔
3076
        } else {
3077
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
194✔
3078
          break;
194✔
3079
        }
3080
      }
3081
      pAPI->stateStore.streamStateFreeCur(pCur);
194✔
3082
    }
3083
    if (num > 0) {
55✔
3084
      code = saveResult(parentWin, pStUpdated);
21✔
3085
      QUERY_CHECK_CODE(code, lino, _end);
21!
3086

3087
      code = saveSessionOutputBuf(pAggSup, &parentWin);
21✔
3088
      QUERY_CHECK_CODE(code, lino, _end);
21!
3089
    }
3090
  }
3091

3092
_end:
56✔
3093
  if (code != TSDB_CODE_SUCCESS) {
56!
3094
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3095
  }
3096
  return code;
56✔
3097
}
3098

3099
int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) {
7,634✔
3100
  int32_t code = TSDB_CODE_SUCCESS;
7,634✔
3101
  int32_t lino = 0;
7,634✔
3102
  void*   pIte = NULL;
7,634✔
3103
  int32_t iter = 0;
7,634✔
3104
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
9,340✔
3105
    SResultWindowInfo* pWinInfo = pIte;
1,706✔
3106
    if (isCloseWindow(&pWinInfo->sessionWin.win, pTwSup)) {
1,706✔
3107
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
602!
3108
        code = saveResult(*pWinInfo, pClosed);
602✔
3109
        QUERY_CHECK_CODE(code, lino, _end);
602!
3110
      }
3111
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
602!
3112
      code = tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
602✔
3113
      QUERY_CHECK_CODE(code, lino, _end);
602!
3114
    }
3115
  }
3116
_end:
7,637✔
3117
  if (code != TSDB_CODE_SUCCESS) {
7,637!
3118
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3119
  }
3120
  return code;
7,639✔
3121
}
3122

3123
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
3,692✔
3124
  int32_t code = TSDB_CODE_SUCCESS;
3,692✔
3125
  int32_t lino = 0;
3,692✔
3126

3127
  int32_t size = taosArrayGetSize(pChildren);
3,692✔
3128
  for (int32_t i = 0; i < size; i++) {
4,232✔
3129
    SOperatorInfo*                 pChildOp = taosArrayGetP(pChildren, i);
539✔
3130
    SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
539✔
3131
    pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
539✔
3132
    code = closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
539✔
3133
    QUERY_CHECK_CODE(code, lino, _end);
539!
3134
  }
3135
_end:
3,693✔
3136
  if (code != TSDB_CODE_SUCCESS) {
3,693!
3137
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3138
  }
3139
  return code;
3,692✔
3140
}
3141

3142
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
244✔
3143
  int32_t code = TSDB_CODE_SUCCESS;
244✔
3144
  int32_t lino = 0;
244✔
3145
  void*   pIte = NULL;
244✔
3146
  int32_t iter = 0;
244✔
3147
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
349✔
3148
    SResultWindowInfo* pWinInfo = pIte;
105✔
3149
    if (!pWinInfo->pStatePos->beUpdated) {
105✔
3150
      continue;
4✔
3151
    }
3152
    pWinInfo->pStatePos->beUpdated = false;
101✔
3153
    code = saveResult(*pWinInfo, pStUpdated);
101✔
3154
    QUERY_CHECK_CODE(code, lino, _end);
101!
3155
  }
3156

3157
_end:
244✔
3158
  if (code != TSDB_CODE_SUCCESS) {
244!
3159
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3160
  }
3161
  return code;
245✔
3162
}
3163

3164
int32_t copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
1,067✔
3165
  int32_t code = TSDB_CODE_SUCCESS;
1,067✔
3166
  int32_t lino = 0;
1,067✔
3167
  int32_t size = taosArrayGetSize(pResWins);
1,067✔
3168
  for (int32_t i = 0; i < size; i++) {
2,197✔
3169
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
1,130✔
3170
    if (!pWinKey) continue;
1,130!
3171
    SSessionKey winInfo = {0};
1,130✔
3172
    getSessionHashKey(pWinKey, &winInfo);
1,130✔
3173
    code = tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
1,130✔
3174
    QUERY_CHECK_CODE(code, lino, _end);
1,130!
3175
  }
3176

3177
_end:
1,067✔
3178
  if (code != TSDB_CODE_SUCCESS) {
1,067!
3179
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3180
  }
3181
  return code;
1,067✔
3182
}
3183

3184
// the allocated memory comes from outer function.
3185
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
7,601✔
3186
  pGroupResInfo->pRows = pArrayList;
7,601✔
3187
  pGroupResInfo->index = 0;
7,601✔
3188
  pGroupResInfo->pBuf = NULL;
7,601✔
3189
  pGroupResInfo->freeItem = false;
7,601✔
3190
  pGroupResInfo->delIndex = 0;
7,601✔
3191
}
7,601✔
3192

3193
int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
3,458✔
3194
                                    SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
3195
  int32_t         code = TSDB_CODE_SUCCESS;
3,458✔
3196
  int32_t         lino = 0;
3,458✔
3197
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
3,458✔
3198
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
3,458✔
3199
  SExprInfo*      pExprInfo = pSup->pExprInfo;
3,458✔
3200
  int32_t         numOfExprs = pSup->numOfExprs;
3,458✔
3201
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
3,458✔
3202
  SqlFunctionCtx* pCtx = pSup->pCtx;
3,458✔
3203
  int64_t         minWindowSize = getMinWindowSize(pOperator);
3,458✔
3204

3205
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
3,458✔
3206

3207
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
8,070✔
3208
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
5,186✔
3209
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
5,186✔
3210
    SResultRow*        pRow = NULL;
5,186✔
3211
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
5,186✔
3212

3213
    if (pBlock->info.id.groupId == 0) {
5,186✔
3214
      pBlock->info.id.groupId = pKey->groupId;
3,977✔
3215

3216
      void*   tbname = NULL;
3,977✔
3217
      int32_t winCode = TSDB_CODE_SUCCESS;
3,977✔
3218
      code = pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
3,977✔
3219
                                                    &tbname, false, &winCode);
3220
      QUERY_CHECK_CODE(code, lino, _end);
3,978!
3221

3222
      if (winCode != TSDB_CODE_SUCCESS) {
3,978✔
3223
        pBlock->info.parTbName[0] = 0;
1,301✔
3224
      } else {
3225
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
2,677✔
3226
      }
3227
      pAPI->stateStore.streamStateFreeVal(tbname);
3,978✔
3228
    } else {
3229
      // current value belongs to different group, it can't be packed into one datablock
3230
      if (pBlock->info.id.groupId != pKey->groupId) {
1,209✔
3231
        break;
560✔
3232
      }
3233
    }
3234

3235
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
4,627✔
3236
    QUERY_CHECK_CODE(code, lino, _end);
4,625!
3237

3238
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
4,625✔
3239
    // no results, continue to check the next one
3240
    if (pRow->numOfRows == 0) {
4,626!
3241
      pGroupResInfo->index += 1;
×
3242
      continue;
60✔
3243
    }
3244
    // skip the window which is less than the windowMinSize
3245
    if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
4,626✔
3246
      qDebug("skip small window, groupId: %" PRId64 ", windowSize: %" PRId64 ", minWindowSize: %" PRId64, pKey->groupId,
60!
3247
             pKey->win.ekey - pKey->win.skey, minWindowSize);
3248
      pGroupResInfo->index += 1;
60✔
3249
      continue;
60✔
3250
    }
3251

3252
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
4,566!
3253
      break;
×
3254
    }
3255

3256
    pGroupResInfo->index += 1;
4,566✔
3257

3258
    for (int32_t j = 0; j < numOfExprs; ++j) {
78,705✔
3259
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
74,153✔
3260

3261
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
74,153✔
3262
      if (pCtx[j].fpSet.finalize) {
74,153✔
3263
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
67,186✔
3264
        if (TAOS_FAILED(tmpRes)) {
67,186!
3265
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
UNCOV
3266
          QUERY_CHECK_CODE(code, lino, _end);
×
3267
        }
3268
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
6,967✔
3269
        // do nothing, todo refactor
3270
      } else {
3271
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
3272
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
3273
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
6,901✔
3274
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
6,901✔
3275
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
13,802✔
3276
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
6,901✔
3277
          QUERY_CHECK_CODE(code, lino, _end);
6,901!
3278
        }
3279
      }
3280
    }
3281

3282
    if (pSessionKeys) {
4,552!
3283
      for (int32_t j = 0; j < pRow->numOfRows; ++j) {
×
3284
        const void* px = taosArrayPush(pSessionKeys, pKey);
×
3285
        QUERY_CHECK_NULL(px, code, lino, _end, terrno);
×
3286
      }
3287
    }
3288

3289
    pBlock->info.dataLoad = 1;
4,552✔
3290
    pBlock->info.rows += pRow->numOfRows;
4,552✔
3291
  }
3292
  code = blockDataUpdateTsWindow(pBlock, 0);
3,444✔
3293
  QUERY_CHECK_CODE(code, lino, _end);
3,459!
3294

3295
_end:
3,459✔
3296
  if (code != TSDB_CODE_SUCCESS) {
3,459!
3297
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3298
  }
3299
  return code;
3,459✔
3300
}
3301

3302
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo, SSDataBlock* pBlock,
11,685✔
3303
                          SArray* pSessionKeys) {
3304
  int32_t        code = TSDB_CODE_SUCCESS;
11,685✔
3305
  int32_t        lino = 0;
11,685✔
3306
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
11,685✔
3307
  // set output datablock version
3308
  pBlock->info.version = pTaskInfo->version;
11,685✔
3309

3310
  blockDataCleanup(pBlock);
11,685✔
3311
  taosArrayClear(pSessionKeys);
11,692✔
3312
  if (!hasRemainResults(pGroupResInfo)) {
11,693✔
3313
    cleanupGroupResInfo(pGroupResInfo);
8,234✔
3314
    goto _end;
8,241✔
3315
  }
3316

3317
  // clear the existed group id
3318
  pBlock->info.id.groupId = 0;
3,458✔
3319
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
3,458✔
3320
  QUERY_CHECK_CODE(code, lino, _end);
3,459!
3321

3322
  if (pBlock->info.rows == 0) {
3,459!
3323
    cleanupGroupResInfo(pGroupResInfo);
×
3324
  }
3325

3326
_end:
3,459✔
3327
  if (code != TSDB_CODE_SUCCESS) {
11,700!
3328
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3329
  }
3330
}
11,700✔
3331

3332
static int32_t buildSessionResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
6,930✔
3333
  int32_t                        code = TSDB_CODE_SUCCESS;
6,930✔
3334
  int32_t                        lino = 0;
6,930✔
3335
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
6,930✔
3336
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
6,930✔
3337
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
6,930✔
3338
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
6,930✔
3339
  SStreamNotifyEventSupp*        pNotifySup = &pInfo->basic.notifyEventSup;
6,930✔
3340
  STaskNotifyEventStat*          pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
6,930✔
3341
  bool                           addNotifyEvent = false;
6,930✔
3342
  addNotifyEvent = IS_NORMAL_SESSION_OP(pOperator) &&
12,435✔
3343
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
5,505!
3344
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
6,930✔
3345
  if (pInfo->pDelRes->info.rows > 0) {
6,928✔
3346
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
255✔
3347
    if (addNotifyEvent) {
253!
3348
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
3349
      QUERY_CHECK_CODE(code, lino, _end);
×
3350
    }
3351
    (*ppRes) = pInfo->pDelRes;
253✔
3352
    return code;
253✔
3353
  }
3354

3355
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes,
6,673!
3356
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
3357
  if (pBInfo->pRes->info.rows > 0) {
6,680✔
3358
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,850✔
3359
    if (addNotifyEvent) {
1,850!
3360
      // Adjust the window end time based on the Session Window gap
3361
      for (int32_t i = 0; i < taosArrayGetSize(pNotifySup->pSessionKeys); ++i) {
×
3362
        SSessionKey* pKey = taosArrayGet(pNotifySup->pSessionKeys, i);
×
3363
        pKey->win.ekey += pAggSup->gap;
×
3364
      }
3365
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
3366
                                     pNotifySup, pNotifyEventStat);
3367
      QUERY_CHECK_CODE(code, lino, _end);
×
3368
    }
3369
    (*ppRes) = pBInfo->pRes;
1,850✔
3370
    return code;
1,850✔
3371
  }
3372

3373
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
4,830✔
3374
  QUERY_CHECK_CODE(code, lino, _end);
4,830!
3375
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
4,830!
3376
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3377
    (*ppRes) = pNotifySup->pEventBlock;
×
3378
    return code;
×
3379
  }
3380

3381
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
4,830✔
3382
  QUERY_CHECK_CODE(code, lino, _end);
4,828!
3383

3384
_end:
4,828✔
3385
  if (code != TSDB_CODE_SUCCESS) {
4,828!
3386
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3387
  }
3388
  (*ppRes) = NULL;
4,829✔
3389
  return code;
4,829✔
3390
}
3391

3392
int32_t getMaxTsWins(const SArray* pAllWins, SArray* pMaxWins) {
307✔
3393
  int32_t code = TSDB_CODE_SUCCESS;
307✔
3394
  int32_t lino = 0;
307✔
3395
  int32_t size = taosArrayGetSize(pAllWins);
307✔
3396
  if (size == 0) {
307✔
3397
    goto _end;
200✔
3398
  }
3399
  SResultWindowInfo* pWinInfo = taosArrayGet(pAllWins, size - 1);
107✔
3400
  SSessionKey*       pSeKey = &pWinInfo->sessionWin;
107✔
3401
  void*              tmp = taosArrayPush(pMaxWins, pSeKey);
107✔
3402
  if (!tmp) {
107!
3403
    code = terrno;
×
3404
    QUERY_CHECK_CODE(code, lino, _end);
×
3405
  }
3406

3407
  if (pSeKey->groupId == 0) {
107✔
3408
    goto _end;
17✔
3409
  }
3410
  uint64_t preGpId = pSeKey->groupId;
90✔
3411
  for (int32_t i = size - 2; i >= 0; i--) {
326✔
3412
    pWinInfo = taosArrayGet(pAllWins, i);
236✔
3413
    pSeKey = &pWinInfo->sessionWin;
236✔
3414
    if (preGpId != pSeKey->groupId) {
236✔
3415
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
185✔
3416
      if (!tmp) {
185!
3417
        code = terrno;
×
3418
        QUERY_CHECK_CODE(code, lino, _end);
×
3419
      }
3420
      preGpId = pSeKey->groupId;
185✔
3421
    }
3422
  }
3423

3424
_end:
90✔
3425
  if (code != TSDB_CODE_SUCCESS) {
307!
3426
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3427
  }
3428
  return code;
307✔
3429
}
3430

3431
int32_t encodeSSessionKey(void** buf, SSessionKey* key) {
4✔
3432
  int32_t tlen = 0;
4✔
3433
  tlen += encodeSTimeWindow(buf, &key->win);
4✔
3434
  tlen += taosEncodeFixedU64(buf, key->groupId);
4✔
3435
  return tlen;
4✔
3436
}
3437

3438
void* decodeSSessionKey(void* buf, SSessionKey* key) {
×
3439
  buf = decodeSTimeWindow(buf, &key->win);
×
3440
  buf = taosDecodeFixedU64(buf, &key->groupId);
×
3441
  return buf;
×
3442
}
3443

3444
int32_t encodeSResultWindowInfo(void** buf, SResultWindowInfo* key, int32_t outLen) {
2✔
3445
  int32_t tlen = 0;
2✔
3446
  tlen += taosEncodeFixedBool(buf, key->isOutput);
2✔
3447
  tlen += encodeSSessionKey(buf, &key->sessionWin);
2✔
3448
  return tlen;
2✔
3449
}
3450

3451
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
×
3452
  buf = taosDecodeFixedBool(buf, &key->isOutput);
×
3453
  buf = decodeSSessionKey(buf, &key->sessionWin);
×
3454
  return buf;
×
3455
}
3456

3457
int32_t doStreamSessionEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
×
3458
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3459
  if (!pInfo) {
×
3460
    return 0;
×
3461
  }
3462

3463
  void* pData = (buf == NULL) ? NULL : *buf;
×
3464

3465
  // 1.streamAggSup.pResultRows
3466
  int32_t tlen = 0;
×
3467
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
×
3468
  tlen += taosEncodeFixedI32(buf, mapSize);
×
3469
  void*   pIte = NULL;
×
3470
  size_t  keyLen = 0;
×
3471
  int32_t iter = 0;
×
3472
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
×
3473
    void* key = tSimpleHashGetKey(pIte, &keyLen);
×
3474
    tlen += encodeSSessionKey(buf, key);
×
3475
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
×
3476
  }
3477

3478
  // 2.twAggSup
3479
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3480

3481
  // 3.pChildren
3482
  int32_t size = taosArrayGetSize(pInfo->pChildren);
×
3483
  tlen += taosEncodeFixedI32(buf, size);
×
3484
  for (int32_t i = 0; i < size; i++) {
×
3485
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3486
    tlen += doStreamSessionEncodeOpState(buf, 0, pChOp, false);
×
3487
  }
3488

3489
  // 4.dataVersion
3490
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
3491

3492
  // 5.basicInfo
3493
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
×
3494

3495
  // 6.checksum
3496
  if (isParent) {
×
3497
    if (buf) {
×
3498
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
×
3499
      tlen += taosEncodeFixedU32(buf, cksum);
×
3500
    } else {
3501
      tlen += sizeof(uint32_t);
×
3502
    }
3503
  }
3504

3505
  return tlen;
×
3506
}
3507

3508
int32_t doStreamSessionDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
3509
  int32_t                        code = TSDB_CODE_SUCCESS;
×
3510
  int32_t                        lino = 0;
×
3511
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3512
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
×
3513
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
×
3514
  if (!pInfo) {
×
3515
    code = TSDB_CODE_FAILED;
×
3516
    QUERY_CHECK_CODE(code, lino, _end);
×
3517
  }
3518
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
×
3519

3520
  // 6.checksum
3521
  if (isParent) {
×
3522
    int32_t dataLen = len - sizeof(uint32_t);
×
3523
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
3524
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
3525
      qError("stream session state is invalid");
×
3526
      code = TSDB_CODE_FAILED;
×
3527
      QUERY_CHECK_CODE(code, lino, _end);
×
3528
    }
3529
    pDataEnd = pCksum;
×
3530
  }
3531

3532
  // 1.streamAggSup.pResultRows
3533
  int32_t mapSize = 0;
×
3534
  buf = taosDecodeFixedI32(buf, &mapSize);
×
3535
  for (int32_t i = 0; i < mapSize; i++) {
×
3536
    SResultWindowInfo winfo = {0};
×
3537
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
3538
    int32_t winCode = TSDB_CODE_SUCCESS;
×
3539
    code = pAggSup->stateStore.streamStateSessionAddIfNotExist(
×
3540
        pAggSup->pState, &winfo.sessionWin, pAggSup->gap, (void**)&winfo.pStatePos, &pAggSup->resultRowSize, &winCode);
3541
    QUERY_CHECK_CODE(code, lino, _end);
×
3542
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
3543

3544
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
3545
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
3546
                          sizeof(SResultWindowInfo));
3547
    QUERY_CHECK_CODE(code, lino, _end);
×
3548
  }
3549

3550
  // 2.twAggSup
3551
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3552

3553
  // 3.pChildren
3554
  int32_t size = 0;
×
3555
  buf = taosDecodeFixedI32(buf, &size);
×
3556
  for (int32_t i = 0; i < size; i++) {
×
3557
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3558
    code = doStreamSessionDecodeOpState(buf, 0, pChOp, false, &buf);
×
3559
    QUERY_CHECK_CODE(code, lino, _end);
×
3560
  }
3561

3562
  // 4.dataVersion
3563
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
3564
  if (ppBuf) {
×
3565
    (*ppBuf) = buf;
×
3566
  }
3567

3568
  // 5.basicInfo
3569
  if (buf < pDataEnd) {
×
3570
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
×
3571
    QUERY_CHECK_CODE(code, lino, _end);
×
3572
  }
3573

3574
_end:
×
3575
  if (code != TSDB_CODE_SUCCESS) {
×
3576
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3577
  }
3578
  return code;
×
3579
}
3580

3581
void doStreamSessionSaveCheckpoint(SOperatorInfo* pOperator) {
185✔
3582
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
185✔
3583
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
185!
3584
    int32_t len = doStreamSessionEncodeOpState(NULL, 0, pOperator, true);
×
3585
    void*   buf = taosMemoryCalloc(1, len);
×
3586
    if (!buf) {
×
3587
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
3588
      return;
×
3589
    }
3590
    void* pBuf = buf;
×
3591
    len = doStreamSessionEncodeOpState(&pBuf, len, pOperator, true);
×
3592
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
×
3593
                                                       strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), buf, len);
3594
    taosMemoryFree(buf);
×
3595
    saveStreamOperatorStateComplete(&pInfo->basic);
×
3596
  }
3597
}
3598

3599
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
101✔
3600
  void*   pIte = NULL;
101✔
3601
  int32_t iter = 0;
101✔
3602
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
202✔
3603
    SResultWindowInfo* pResInfo = pIte;
101✔
3604
    pResInfo->pStatePos->beUsed = true;
101✔
3605
  }
3606
}
101✔
3607

3608
int32_t copyDeleteSessionKey(SSHashObj* source, SSHashObj* dest) {
34✔
3609
  int32_t code = TSDB_CODE_SUCCESS;
34✔
3610
  int32_t lino = 0;
34✔
3611
  if (tSimpleHashGetSize(source) == 0) {
34✔
3612
    goto _end;
25✔
3613
  }
3614
  void*   pIte = NULL;
9✔
3615
  int32_t iter = 0;
9✔
3616
  size_t  keyLen = 0;
9✔
3617
  while ((pIte = tSimpleHashIterate(source, pIte, &iter)) != NULL) {
21✔
3618
    SSessionKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
12✔
3619
    code = saveDeleteRes(dest, *pKey);
12✔
3620
    QUERY_CHECK_CODE(code, lino, _end);
12!
3621
  }
3622
  tSimpleHashClear(source);
9✔
3623

3624
_end:
34✔
3625
  if (code != TSDB_CODE_SUCCESS) {
34!
3626
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3627
  }
3628
  return code;
34✔
3629
}
3630

3631
static int32_t doStreamSessionAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
6,304✔
3632
  int32_t                        code = TSDB_CODE_SUCCESS;
6,304✔
3633
  int32_t                        lino = 0;
6,304✔
3634
  SExprSupp*                     pSup = &pOperator->exprSupp;
6,304✔
3635
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
6,304✔
3636
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
6,304✔
3637
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
6,304✔
3638
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
6,304✔
3639
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
6,304✔
3640
  if (pOperator->status == OP_EXEC_DONE) {
6,304!
3641
    (*ppRes) = NULL;
×
3642
    return code;
×
3643
  } else if (pOperator->status == OP_RES_TO_RETURN) {
6,304✔
3644
    SSDataBlock* opRes = NULL;
1,815✔
3645
    code = buildSessionResult(pOperator, &opRes);
1,815✔
3646
    QUERY_CHECK_CODE(code, lino, _end);
1,814!
3647
    if (opRes) {
1,814✔
3648
      (*ppRes) = opRes;
423✔
3649
      return code;
1,813✔
3650
    }
3651

3652
    if (pInfo->recvGetAll) {
1,391✔
3653
      pInfo->recvGetAll = false;
83✔
3654
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
83✔
3655
    }
3656

3657
    if (pInfo->reCkBlock) {
1,391!
3658
      pInfo->reCkBlock = false;
×
3659
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3660
      (*ppRes) = pInfo->pCheckpointRes;
×
3661
      return code;
×
3662
    }
3663

3664
    setStreamOperatorCompleted(pOperator);
1,391✔
3665
    (*ppRes) = NULL;
1,390✔
3666
    return code;
1,390✔
3667
  }
3668

3669
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,489✔
3670
  if (!pInfo->pUpdated) {
4,489✔
3671
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
3,691✔
3672
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
3,690!
3673
  }
3674
  if (!pInfo->pStUpdated) {
4,488✔
3675
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,623✔
3676
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
3,622✔
3677
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
3,623!
3678
  }
3679
  while (1) {
3,269✔
3680
    SSDataBlock* pBlock = NULL;
7,757✔
3681
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,757✔
3682
    QUERY_CHECK_CODE(code, lino, _end);
7,755!
3683

3684
    if (pBlock == NULL) {
7,755✔
3685
      break;
3,694✔
3686
    }
3687
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,061✔
3688
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,060✔
3689

3690
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,061✔
3691
        pBlock->info.type == STREAM_CLEAR) {
3,824✔
3692
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
402✔
3693
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
403!
3694
      // gap must be 0
3695
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
403✔
3696
      QUERY_CHECK_CODE(code, lino, _end);
402!
3697

3698
      removeSessionResults(pAggSup, pInfo->pStUpdated, pWins);
402✔
3699
      if (IS_FINAL_SESSION_OP(pOperator)) {
403✔
3700
        int32_t                        childIndex = getChildIndex(pBlock);
56✔
3701
        SOperatorInfo*                 pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
56✔
3702
        SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
56✔
3703
        // gap must be 0
3704
        code = doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
56✔
3705
        QUERY_CHECK_CODE(code, lino, _end);
56!
3706

3707
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
56✔
3708
        QUERY_CHECK_CODE(code, lino, _end);
56!
3709
      }
3710
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
403✔
3711
      QUERY_CHECK_CODE(code, lino, _end);
403!
3712

3713
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
403!
3714
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
2✔
3715
        QUERY_CHECK_CODE(code, lino, _end);
2!
3716
      }
3717
      taosArrayDestroy(pWins);
403✔
3718
      continue;
762✔
3719
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,659✔
3720
      pInfo->recvGetAll = true;
188✔
3721
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
188✔
3722
      QUERY_CHECK_CODE(code, lino, _end);
189!
3723
      continue;
189✔
3724
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,471✔
3725
      (*ppRes) = pBlock;
796✔
3726
      return code;
796✔
3727
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,675✔
3728
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
170✔
3729
      doStreamSessionSaveCheckpoint(pOperator);
170✔
3730
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
170✔
3731
      QUERY_CHECK_CODE(code, lino, _end);
170!
3732

3733
      continue;
170✔
3734
    } else {
3735
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
2,505!
3736
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3737
        QUERY_CHECK_CODE(code, lino, _end);
×
3738
      }
3739
    }
3740

3741
    if (pInfo->scalarSupp.pExprInfo != NULL) {
2,505✔
3742
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
3743
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
3744
      QUERY_CHECK_CODE(code, lino, _end);
13!
3745
    }
3746
    // the pDataBlock are always the same one, no need to call this again
3747
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
2,505✔
3748
    QUERY_CHECK_CODE(code, lino, _end);
2,506!
3749

3750
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_SESSION_OP(pOperator),
2,506✔
3751
                           true);
3752
    if (IS_FINAL_SESSION_OP(pOperator)) {
2,507✔
3753
      int32_t chIndex = getChildIndex(pBlock);
232✔
3754
      int32_t size = taosArrayGetSize(pInfo->pChildren);
232✔
3755
      // if chIndex + 1 - size > 0, add new child
3756
      for (int32_t i = 0; i < chIndex + 1 - size; i++) {
232!
3757
        SOperatorInfo* pChildOp = NULL;
×
3758
        code = createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0, NULL, &pChildOp);
×
3759
        if (pChildOp == NULL || code != 0) {
×
3760
          qError("%s create stream child of final session error", GET_TASKID(pTaskInfo));
×
3761
          code = TSDB_CODE_FAILED;
×
3762
          QUERY_CHECK_CODE(code, lino, _end);
×
3763
        }
3764

3765
        void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
×
3766
        if (!tmp) {
×
3767
          code = terrno;
×
3768
          QUERY_CHECK_CODE(code, lino, _end);
×
3769
        }
3770
      }
3771

3772
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
232✔
3773
      code = setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
232✔
3774
      QUERY_CHECK_CODE(code, lino, _end);
232!
3775
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
232✔
3776
    }
3777
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
2,507✔
3778
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
2,507✔
3779
  }
3780
  // restore the value
3781
  pOperator->status = OP_RES_TO_RETURN;
3,694✔
3782

3783
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
3,694✔
3784
  QUERY_CHECK_CODE(code, lino, _end);
3,693!
3785

3786
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
3,693✔
3787
  QUERY_CHECK_CODE(code, lino, _end);
3,690!
3788

3789
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
3,690✔
3790
  QUERY_CHECK_CODE(code, lino, _end);
3,690!
3791

3792
  if (!pInfo->destHasPrimaryKey) {
3,690✔
3793
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
3,670✔
3794
  }
3795
  if (pInfo->isHistoryOp) {
3,691✔
3796
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
193✔
3797
    QUERY_CHECK_CODE(code, lino, _end);
193!
3798
  }
3799
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
3,691!
3800
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
22✔
3801
    QUERY_CHECK_CODE(code, lino, _end);
22!
3802
  }
3803
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
3,691✔
3804
  pInfo->pUpdated = NULL;
3,680✔
3805
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3,680✔
3806
  QUERY_CHECK_CODE(code, lino, _end);
3,692!
3807

3808
  SSDataBlock* opRes = NULL;
3,692✔
3809
  code = buildSessionResult(pOperator, &opRes);
3,692✔
3810
  QUERY_CHECK_CODE(code, lino, _end);
3,695!
3811
  if (opRes) {
3,695✔
3812
    (*ppRes) = opRes;
1,392✔
3813
    return code;
1,392✔
3814
  }
3815

3816
_end:
2,303✔
3817
  if (code != TSDB_CODE_SUCCESS) {
2,303!
3818
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3819
    pTaskInfo->code = code;
×
3820
    T_LONG_JMP(pTaskInfo->env, code);
×
3821
  }
3822
  setStreamOperatorCompleted(pOperator);
2,303✔
3823
  (*ppRes) = NULL;
2,302✔
3824
  return code;
2,302✔
3825
}
3826

3827
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
×
3828
  SSDataBlock* pRes = NULL;
×
3829
  int32_t      code = doStreamSessionAggNext(pOperator, &pRes);
×
3830
  return pRes;
×
3831
}
3832

3833
void streamSessionReleaseState(SOperatorInfo* pOperator) {
185✔
3834
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
185✔
3835
  int32_t                        winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
185✔
3836
  int32_t                        resSize = winSize + sizeof(TSKEY);
185✔
3837
  char*                          pBuff = taosMemoryCalloc(1, resSize);
185!
3838
  if (!pBuff) {
185!
3839
    return;
×
3840
  }
3841
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
185✔
3842
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
185✔
3843
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_STATE_NAME,
185✔
3844
                                                     strlen(STREAM_SESSION_OP_STATE_NAME), pBuff, resSize);
3845
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
185✔
3846
  taosMemoryFreeClear(pBuff);
185!
3847
  SOperatorInfo* downstream = pOperator->pDownstream[0];
185✔
3848
  if (downstream->fpSet.releaseStreamStateFn) {
185!
3849
    downstream->fpSet.releaseStreamStateFn(downstream);
185✔
3850
  }
3851
}
3852

3853
void resetWinRange(STimeWindow* winRange) {
279✔
3854
  winRange->skey = INT64_MIN;
279✔
3855
  winRange->ekey = INT64_MAX;
279✔
3856
}
279✔
3857

3858
int32_t getSessionWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SResultWindowInfo* pWinInfo) {
292✔
3859
  int32_t code = TSDB_CODE_SUCCESS;
292✔
3860
  int32_t lino = 0;
292✔
3861
  int32_t rowSize = pAggSup->resultRowSize;
292✔
3862
  int32_t winCode = TSDB_CODE_SUCCESS;
292✔
3863
  code = pAggSup->stateStore.streamStateSessionGet(pAggSup->pState, pKey, (void**)&pWinInfo->pStatePos, &rowSize,
292✔
3864
                                                   &winCode);
3865
  QUERY_CHECK_CODE(code, lino, _end);
292!
3866

3867
  if (winCode == TSDB_CODE_SUCCESS) {
292!
3868
    pWinInfo->sessionWin = *pKey;
292✔
3869
    pWinInfo->isOutput = true;
292✔
3870
    if (pWinInfo->pStatePos->needFree) {
292!
3871
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pWinInfo->sessionWin);
292✔
3872
    }
3873
  } else {
3874
    SET_SESSION_WIN_INVALID((*pWinInfo));
×
3875
  }
3876

3877
_end:
292✔
3878
  if (code != TSDB_CODE_SUCCESS) {
292!
3879
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3880
  }
3881
  return code;
292✔
3882
}
3883

3884
void reloadAggSupFromDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup) {
411✔
3885
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
411✔
3886

3887
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
411✔
3888
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
107✔
3889
    return;
107✔
3890
  }
3891

3892
  SStreamScanInfo* pScanInfo = downstream->info;
304✔
3893
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
304✔
3894
}
3895

3896
void streamSessionSemiReloadState(SOperatorInfo* pOperator) {
15✔
3897
  int32_t                        code = TSDB_CODE_SUCCESS;
15✔
3898
  int32_t                        lino = 0;
15✔
3899
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
15✔
3900
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
15✔
3901
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
15✔
3902
  resetWinRange(&pAggSup->winRange);
15✔
3903

3904
  SResultWindowInfo winInfo = {0};
15✔
3905
  int32_t           size = 0;
15✔
3906
  void*             pBuf = NULL;
15✔
3907
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
15✔
3908
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3909
  QUERY_CHECK_CODE(code, lino, _end);
15!
3910

3911
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
15✔
3912
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
15✔
3913
  for (int32_t i = 0; i < num; i++) {
40✔
3914
    SResultWindowInfo winInfo = {0};
25✔
3915
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
25✔
3916
    QUERY_CHECK_CODE(code, lino, _end);
25!
3917
    if (!IS_VALID_SESSION_WIN(winInfo)) {
25!
3918
      continue;
×
3919
    }
3920
    compactSessionSemiWindow(pOperator, &winInfo);
25✔
3921
    code = saveSessionOutputBuf(pAggSup, &winInfo);
25✔
3922
    QUERY_CHECK_CODE(code, lino, _end);
25!
3923
  }
3924
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
15✔
3925
  taosMemoryFree(pBuf);
15!
3926
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
15✔
3927
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
15✔
3928

3929
  SOperatorInfo* downstream = pOperator->pDownstream[0];
15✔
3930
  if (downstream->fpSet.reloadStreamStateFn) {
15!
3931
    downstream->fpSet.reloadStreamStateFn(downstream);
15✔
3932
  }
3933
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
15✔
3934

3935
_end:
15✔
3936
  if (code != TSDB_CODE_SUCCESS) {
15!
3937
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3938
  }
3939
}
15✔
3940

3941
void streamSessionReloadState(SOperatorInfo* pOperator) {
170✔
3942
  int32_t                        code = TSDB_CODE_SUCCESS;
170✔
3943
  int32_t                        lino = 0;
170✔
3944
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
170✔
3945
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
170✔
3946
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
170✔
3947
  resetWinRange(&pAggSup->winRange);
170✔
3948

3949
  int32_t size = 0;
170✔
3950
  void*   pBuf = NULL;
170✔
3951
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
170✔
3952
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3953

3954
  QUERY_CHECK_CODE(code, lino, _end);
170!
3955

3956
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
170✔
3957
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
170✔
3958

3959
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
170✔
3960
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
170✔
3961
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
170✔
3962

3963
  if (!pInfo->pStUpdated && num > 0) {
170!
3964
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
68✔
3965
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
68✔
3966
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
68!
3967
  }
3968
  for (int32_t i = 0; i < num; i++) {
322✔
3969
    SResultWindowInfo winInfo = {0};
152✔
3970
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
152✔
3971
    QUERY_CHECK_CODE(code, lino, _end);
152!
3972
    if (!IS_VALID_SESSION_WIN(winInfo)) {
152!
3973
      continue;
×
3974
    }
3975

3976
    int32_t winNum = 0;
152✔
3977
    code = compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted, true, &winNum);
152✔
3978
    QUERY_CHECK_CODE(code, lino, _end);
152!
3979

3980
    if (winNum > 0) {
152!
3981
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, winInfo.sessionWin.win.skey,
×
3982
             winInfo.sessionWin.groupId);
3983
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
3984
        code = saveResult(winInfo, pInfo->pStUpdated);
×
3985
        QUERY_CHECK_CODE(code, lino, _end);
×
3986
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
3987
        if (!isCloseWindow(&winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
3988
          code = saveDeleteRes(pInfo->pStDeleted, winInfo.sessionWin);
×
3989
          QUERY_CHECK_CODE(code, lino, _end);
×
3990
        }
3991
        SSessionKey key = {0};
×
3992
        getSessionHashKey(&winInfo.sessionWin, &key);
×
3993
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
×
3994
        QUERY_CHECK_CODE(code, lino, _end);
×
3995
      }
3996
    }
3997
    code = saveSessionOutputBuf(pAggSup, &winInfo);
152✔
3998
    QUERY_CHECK_CODE(code, lino, _end);
152!
3999
  }
4000
  taosMemoryFree(pBuf);
170!
4001

4002
  SOperatorInfo* downstream = pOperator->pDownstream[0];
170✔
4003
  if (downstream->fpSet.reloadStreamStateFn) {
170!
4004
    downstream->fpSet.reloadStreamStateFn(downstream);
170✔
4005
  }
4006
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
170✔
4007

4008
_end:
170✔
4009
  if (code != TSDB_CODE_SUCCESS) {
170!
4010
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4011
  }
4012
}
170✔
4013

4014
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
870✔
4015
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4016
  QRY_PARAM_CHECK(pOptrInfo);
870!
4017

4018
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
870✔
4019
  int32_t                        numOfCols = 0;
870✔
4020
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
870✔
4021
  int32_t                        lino = 0;
870✔
4022
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
870!
4023
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
870!
4024
  if (pInfo == NULL || pOperator == NULL) {
870!
4025
    code = terrno;
×
4026
    goto _error;
×
4027
  }
4028

4029
  pOperator->pTaskInfo = pTaskInfo;
870✔
4030

4031
  initResultSizeInfo(&pOperator->resultInfo, 4096);
870✔
4032
  if (pSessionNode->window.pExprs != NULL) {
870✔
4033
    int32_t    numOfScalar = 0;
1✔
4034
    SExprInfo* pScalarExprInfo = NULL;
1✔
4035
    code = createExprInfo(pSessionNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
4036
    QUERY_CHECK_CODE(code, lino, _error);
1!
4037

4038
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
4039
    if (code != TSDB_CODE_SUCCESS) {
1!
4040
      goto _error;
×
4041
    }
4042
  }
4043
  SExprSupp* pExpSup = &pOperator->exprSupp;
870✔
4044

4045
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
870✔
4046
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
870!
4047
  pInfo->binfo.pRes = pResBlock;
870✔
4048

4049
  SExprInfo* pExprInfo = NULL;
870✔
4050
  code = createExprInfo(pSessionNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
870✔
4051
  QUERY_CHECK_CODE(code, lino, _error);
870!
4052

4053
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
870✔
4054
  QUERY_CHECK_CODE(code, lino, _error);
870!
4055

4056
  pInfo->twAggSup = (STimeWindowAggSupp){
870✔
4057
      .waterMark = pSessionNode->window.watermark,
870✔
4058
      .calTrigger = pSessionNode->window.triggerType,
870✔
4059
      .maxTs = INT64_MIN,
4060
      .minTs = INT64_MAX,
4061
      .deleteMark = getDeleteMark(&pSessionNode->window, 0),
870✔
4062
  };
4063

4064
  pInfo->primaryTsIndex = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
870✔
4065
  code =
4066
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, pSessionNode->gap, pTaskInfo->streamInfo.pState,
870✔
4067
                             0, 0, &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
870✔
4068
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
4069
  if (code != TSDB_CODE_SUCCESS) {
870!
4070
    goto _error;
×
4071
  }
4072

4073
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
870✔
4074
  QUERY_CHECK_CODE(code, lino, _error);
870!
4075

4076
  if (pSessionNode->window.pTsEnd) {
870!
4077
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
870✔
4078
  }
4079

4080
  pInfo->order = TSDB_ORDER_ASC;
870✔
4081
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
870✔
4082
  pInfo->pStDeleted = tSimpleHashInit(64, hashFn);
870✔
4083
  QUERY_CHECK_NULL(pInfo->pStDeleted, code, lino, _error, terrno);
870!
4084
  pInfo->pDelIterator = NULL;
870✔
4085
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
870✔
4086
  QUERY_CHECK_CODE(code, lino, _error);
870!
4087

4088
  pInfo->pChildren = NULL;
870✔
4089
  pInfo->pPhyNode = pPhyNode;
870✔
4090
  pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
870✔
4091
  pInfo->ignoreExpiredDataSaved = false;
870✔
4092
  pInfo->pUpdated = NULL;
870✔
4093
  pInfo->pStUpdated = NULL;
870✔
4094
  pInfo->dataVersion = 0;
870✔
4095
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
870✔
4096
  if (!pInfo->historyWins) {
870!
4097
    goto _error;
×
4098
  }
4099
  if (pHandle) {
870!
4100
    pInfo->isHistoryOp = pHandle->fillHistory;
870✔
4101
  }
4102

4103
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
870✔
4104
  QUERY_CHECK_CODE(code, lino, _error);
870!
4105

4106
  pInfo->clearState = false;
870✔
4107
  pInfo->recvGetAll = false;
870✔
4108
  pInfo->destHasPrimaryKey = pSessionNode->window.destHasPrimaryKey;
870✔
4109
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
870✔
4110
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
870!
4111
  pInfo->pOperator = pOperator;
870✔
4112

4113
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION;
870✔
4114
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
870✔
4115
                  OP_NOT_OPENED, pInfo, pTaskInfo);
4116
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
870✔
4117
    // for stream
4118
    void*   buff = NULL;
715✔
4119
    int32_t len = 0;
715✔
4120
    int32_t res =
4121
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
715✔
4122
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4123
    if (res == TSDB_CODE_SUCCESS) {
715!
4124
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4125
      taosMemoryFree(buff);
×
4126
      QUERY_CHECK_CODE(code, lino, _error);
×
4127
    }
4128
  }
4129
  pOperator->fpSet =
4130
      createOperatorFpSet(optrDummyOpenFn, doStreamSessionAggNext, NULL, destroyStreamSessionAggOperatorInfo,
870✔
4131
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4132
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
870✔
4133

4134
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
870✔
4135
  QUERY_CHECK_CODE(code, lino, _error);
870!
4136

4137
  if (downstream) {
870✔
4138
    pInfo->basic.primaryPkIndex = -1;
751✔
4139
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
751✔
4140
                          &pInfo->twAggSup, &pInfo->basic);
751✔
4141
    QUERY_CHECK_CODE(code, lino, _error);
750!
4142

4143
    code = appendDownstream(pOperator, &downstream, 1);
750✔
4144
    QUERY_CHECK_CODE(code, lino, _error);
751!
4145
  }
4146

4147
  *pOptrInfo = pOperator;
870✔
4148
  return TSDB_CODE_SUCCESS;
870✔
4149

4150
_error:
×
4151
  if (pInfo != NULL) {
×
4152
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4153
  }
4154
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
4155
  pTaskInfo->code = code;
×
4156
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4157
  return code;
×
4158
}
4159

4160
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
508✔
4161
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
508✔
4162
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
508✔
4163
  pInfo->clearState = false;
508✔
4164
}
508✔
4165

4166
int32_t deleteSessionWinState(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SSHashObj* pMapUpdate,
617✔
4167
                              SSHashObj* pMapDelete, SSHashObj* pPkDelete, bool needAdd) {
4168
  int32_t code = TSDB_CODE_SUCCESS;
617✔
4169
  int32_t lino = 0;
617✔
4170
  SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
617✔
4171
  if (!pWins) {
617!
4172
    code = terrno;
×
4173
    QUERY_CHECK_CODE(code, lino, _end);
×
4174
  }
4175
  code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
617✔
4176
  QUERY_CHECK_CODE(code, lino, _end);
617!
4177

4178
  removeSessionResults(pAggSup, pMapUpdate, pWins);
617✔
4179
  code = copyDeleteWindowInfo(pWins, pMapDelete);
617✔
4180
  QUERY_CHECK_CODE(code, lino, _end);
617!
4181

4182
  if (needAdd) {
617!
4183
    code = copyDeleteWindowInfo(pWins, pPkDelete);
×
4184
    QUERY_CHECK_CODE(code, lino, _end);
×
4185
  }
4186
  taosArrayDestroy(pWins);
617✔
4187

4188
_end:
617✔
4189
  if (code != TSDB_CODE_SUCCESS) {
617!
4190
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4191
  }
4192
  return code;
617✔
4193
}
4194

4195
static int32_t doStreamSessionSemiAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
917✔
4196
  int32_t                        code = TSDB_CODE_SUCCESS;
917✔
4197
  int32_t                        lino = 0;
917✔
4198
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
917✔
4199
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
917✔
4200
  TSKEY                          maxTs = INT64_MIN;
917✔
4201
  SExprSupp*                     pSup = &pOperator->exprSupp;
917✔
4202
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
917✔
4203
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
917✔
4204

4205
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
917✔
4206
  if (pOperator->status == OP_EXEC_DONE) {
917!
4207
    (*ppRes) = NULL;
×
4208
    return code;
×
4209
  }
4210

4211
  {
4212
    SSDataBlock* opRes = NULL;
917✔
4213
    code = buildSessionResult(pOperator, &opRes);
917✔
4214
    QUERY_CHECK_CODE(code, lino, _end);
917!
4215
    if (opRes) {
917✔
4216
      (*ppRes) = opRes;
95✔
4217
      return code;
232✔
4218
    }
4219

4220
    if (pInfo->clearState) {
822✔
4221
      clearFunctionContext(&pOperator->exprSupp);
56✔
4222
      // semi session operator clear disk buffer
4223
      clearStreamSessionOperator(pInfo);
56✔
4224
    }
4225

4226
    if (pOperator->status == OP_RES_TO_RETURN) {
822✔
4227
      if (pInfo->reCkBlock) {
137!
4228
        pInfo->reCkBlock = false;
×
4229
        printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
4230
        (*ppRes) = pInfo->pCheckpointRes;
×
4231
        return code;
×
4232
      }
4233
      clearFunctionContext(&pOperator->exprSupp);
137✔
4234
      // semi session operator clear disk buffer
4235
      clearStreamSessionOperator(pInfo);
137✔
4236
      setStreamOperatorCompleted(pOperator);
137✔
4237
      (*ppRes) = NULL;
137✔
4238
      return code;
137✔
4239
    }
4240
  }
4241

4242
  SOperatorInfo* downstream = pOperator->pDownstream[0];
685✔
4243
  if (!pInfo->pUpdated) {
685✔
4244
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
508✔
4245
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
508!
4246
  }
4247
  if (!pInfo->pStUpdated) {
685✔
4248
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
508✔
4249
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
508✔
4250
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
508!
4251
  }
4252
  while (1) {
346✔
4253
    SSDataBlock* pBlock = NULL;
1,031✔
4254
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,031✔
4255
    QUERY_CHECK_CODE(code, lino, _end);
1,031!
4256

4257
    if (pBlock == NULL) {
1,031✔
4258
      pOperator->status = OP_RES_TO_RETURN;
452✔
4259
      break;
452✔
4260
    }
4261
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
579✔
4262
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
579✔
4263

4264
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
579✔
4265
        pBlock->info.type == STREAM_CLEAR) {
528✔
4266
      // gap must be 0
4267
      code = deleteSessionWinState(pAggSup, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, NULL, false);
56✔
4268
      QUERY_CHECK_CODE(code, lino, _end);
56!
4269
      pInfo->clearState = true;
56✔
4270
      break;
56✔
4271
    } else if (pBlock->info.type == STREAM_GET_ALL) {
523!
4272
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
×
4273
      QUERY_CHECK_CODE(code, lino, _end);
×
4274
      continue;
15✔
4275
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
523✔
4276
      (*ppRes) = pBlock;
177✔
4277
      return code;
177✔
4278
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
346✔
4279
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
15✔
4280
      doStreamSessionSaveCheckpoint(pOperator);
15✔
4281
      continue;
15✔
4282
    } else {
4283
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
331!
4284
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4285
        QUERY_CHECK_CODE(code, lino, _end);
×
4286
      }
4287
    }
4288

4289
    if (pInfo->scalarSupp.pExprInfo != NULL) {
331!
4290
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
4291
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
4292
      QUERY_CHECK_CODE(code, lino, _end);
×
4293
    }
4294
    // the pDataBlock are always the same one, no need to call this again
4295
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
331✔
4296
    QUERY_CHECK_CODE(code, lino, _end);
331!
4297
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
331✔
4298
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
331✔
4299
  }
4300

4301
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
508✔
4302
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
508✔
4303

4304
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
508✔
4305
  QUERY_CHECK_CODE(code, lino, _end);
508!
4306

4307
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
508✔
4308

4309
  if (pInfo->isHistoryOp) {
508✔
4310
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
15✔
4311
    QUERY_CHECK_CODE(code, lino, _end);
15!
4312
  }
4313

4314
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
508✔
4315
  pInfo->pUpdated = NULL;
508✔
4316
  code = blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
508✔
4317
  QUERY_CHECK_CODE(code, lino, _end);
508!
4318

4319
  SSDataBlock* opRes = NULL;
508✔
4320
  code = buildSessionResult(pOperator, &opRes);
508✔
4321
  QUERY_CHECK_CODE(code, lino, _end);
508!
4322
  if (opRes) {
508✔
4323
    (*ppRes) = opRes;
193✔
4324
    return code;
193✔
4325
  }
4326

4327
_end:
315✔
4328
  if (code != TSDB_CODE_SUCCESS) {
315!
4329
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4330
    pTaskInfo->code = code;
×
4331
    T_LONG_JMP(pTaskInfo->env, code);
×
4332
  }
4333

4334
  clearFunctionContext(&pOperator->exprSupp);
315✔
4335
  // semi session operator clear disk buffer
4336
  clearStreamSessionOperator(pInfo);
315✔
4337
  setStreamOperatorCompleted(pOperator);
315✔
4338
  (*ppRes) = NULL;
315✔
4339
  return code;
315✔
4340
}
4341

4342
static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
×
4343
  SSDataBlock* pRes = NULL;
×
4344
  int32_t      code = doStreamSessionSemiAggNext(pOperator, &pRes);
×
4345
  return pRes;
×
4346
}
4347

4348
int32_t createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
274✔
4349
                                                SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle,
4350
                                                SOperatorInfo** pOptrInfo) {
4351
  QRY_PARAM_CHECK(pOptrInfo);
274!
4352

4353
  int32_t        code = TSDB_CODE_SUCCESS;
274✔
4354
  int32_t        lino = 0;
274✔
4355
  SOperatorInfo* pOperator = NULL;
274✔
4356
  code = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, &pOperator);
274✔
4357
  if (pOperator == NULL || code != 0) {
274!
4358
    downstream = NULL;
×
4359
    QUERY_CHECK_CODE(code, lino, _error);
×
4360
  }
4361

4362
  SStorageAPI*                   pAPI = &pTaskInfo->storageAPI;
274✔
4363
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
274✔
4364
  pOperator->operatorType = pPhyNode->type;
274✔
4365
  pInfo->pOperator = pOperator;
274✔
4366

4367
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
274✔
4368
    pOperator->fpSet =
119✔
4369
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAggNext, NULL, destroyStreamSessionAggOperatorInfo,
119✔
4370
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4371
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionSemiReloadState);
119✔
4372
  }
4373

4374
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
274✔
4375
  QUERY_CHECK_CODE(code, lino, _error);
274!
4376

4377
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), pPhyNode->type, false, OP_NOT_OPENED, pInfo,
274✔
4378
                  pTaskInfo);
4379

4380
  if (numOfChild > 0) {
274✔
4381
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
36✔
4382
    QUERY_CHECK_NULL(pInfo->pChildren, code, lino, _error, terrno);
36!
4383
    for (int32_t i = 0; i < numOfChild; i++) {
155✔
4384
      SOperatorInfo* pChildOp = NULL;
119✔
4385
      code = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0, pHandle, &pChildOp);
119✔
4386
      if (pChildOp == NULL || code != 0) {
119!
4387
        QUERY_CHECK_CODE(code, lino, _error);
×
4388
      }
4389

4390
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
119✔
4391
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
119✔
4392
      pAPI->stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i, pInfo->primaryTsIndex);
119✔
4393
      void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
119✔
4394
      if (!tmp) {
119!
4395
        code = terrno;
×
4396
        QUERY_CHECK_CODE(code, lino, _error);
×
4397
      }
4398
    }
4399

4400
    void*   buff = NULL;
36✔
4401
    int32_t len = 0;
36✔
4402
    int32_t res =
4403
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
36✔
4404
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4405
    if (res == TSDB_CODE_SUCCESS) {
36!
4406
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4407
      taosMemoryFree(buff);
×
4408
      QUERY_CHECK_CODE(code, lino, _error);
×
4409
    }
4410
  }
4411

4412
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
274✔
4413
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
238✔
4414
  }
4415

4416
  *pOptrInfo = pOperator;
274✔
4417
  return code;
274✔
4418

4419
_error:
×
4420
  if (pInfo != NULL) {
×
4421
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4422
  }
4423
  if (pOperator != NULL) {
×
4424
    pOperator->info = NULL;
×
4425
    destroyOperator(pOperator);
×
4426
  }
4427
  pTaskInfo->code = code;
×
4428
  if (code != TSDB_CODE_SUCCESS) {
×
4429
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4430
  }
4431
  return code;
×
4432
}
4433

4434
void destroyStreamStateOperatorInfo(void* param) {
326✔
4435
  if (param == NULL) {
326!
4436
    return;
×
4437
  }
4438
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
326✔
4439
  cleanupBasicInfo(&pInfo->binfo);
326✔
4440
  if (pInfo->pOperator) {
326!
4441
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
326✔
4442
                              &pInfo->groupResInfo);
4443
    pInfo->pOperator = NULL;
326✔
4444
  }
4445

4446
  destroyStreamBasicInfo(&pInfo->basic);
326✔
4447
  clearGroupResInfo(&pInfo->groupResInfo);
326✔
4448
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
326✔
4449
  pInfo->pUpdated = NULL;
326✔
4450
  destroyStreamAggSupporter(&pInfo->streamAggSup);
326✔
4451

4452
  cleanupExprSupp(&pInfo->scalarSupp);
326✔
4453
  if (pInfo->pChildren != NULL) {
326!
4454
    int32_t size = taosArrayGetSize(pInfo->pChildren);
×
4455
    for (int32_t i = 0; i < size; i++) {
×
4456
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
×
4457
      destroyOperator(pChild);
×
4458
    }
4459
    taosArrayDestroy(pInfo->pChildren);
×
4460
  }
4461
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
326✔
4462
  blockDataDestroy(pInfo->pDelRes);
326✔
4463
  tSimpleHashCleanup(pInfo->pSeUpdated);
326✔
4464
  tSimpleHashCleanup(pInfo->pSeDeleted);
326✔
4465
  cleanupGroupResInfo(&pInfo->groupResInfo);
326✔
4466

4467
  taosArrayDestroy(pInfo->historyWins);
326✔
4468
  blockDataDestroy(pInfo->pCheckpointRes);
326✔
4469
  tSimpleHashCleanup(pInfo->pPkDeleted);
326✔
4470

4471
  taosMemoryFreeClear(param);
326!
4472
}
4473

4474
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
3,820✔
4475
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
3,820✔
4476
    return true;
1,243✔
4477
  }
4478
  return false;
2,577✔
4479
}
4480

4481
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
6,288✔
4482
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
6,288!
4483
}
4484

4485
bool compareStateKey(void* data, void* key) {
2,585✔
4486
  if (!data || !key) {
2,585!
4487
    return true;
×
4488
  }
4489
  SStateKeys* stateKey = (SStateKeys*)key;
2,585✔
4490
  stateKey->pData = (char*)key + sizeof(SStateKeys);
2,585✔
4491
  return compareVal(data, stateKey);
2,585✔
4492
}
4493

4494
bool compareWinStateKey(SStateKeys* left, SStateKeys* right) {
107✔
4495
  if (!left || !right) {
107!
4496
    return false;
107✔
4497
  }
4498
  return compareVal(left->pData, right);
×
4499
}
4500

4501
static void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
3,222✔
4502
  SStreamStateCur* pCur = NULL;
3,222✔
4503

4504
  if (pAggSup == NULL || pNextWin == NULL) {
3,222!
4505
    return;
×
4506
  }
4507

4508
  if (asc)
3,222!
4509
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
3,222✔
4510
  else
4511
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyPrev(pAggSup->pState, &pNextWin->winInfo.sessionWin);
×
4512
  int32_t nextSize = pAggSup->resultRowSize;
3,223✔
4513
  int32_t winCode = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin,
3,223✔
4514
                                                                     (void**)&pNextWin->winInfo.pStatePos, &nextSize);
3,223✔
4515
  if (winCode != TSDB_CODE_SUCCESS) {
3,223✔
4516
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
3,050✔
4517
  } else {
4518
    pNextWin->pStateKey =
173✔
4519
        (SStateKeys*)((char*)pNextWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
173✔
4520
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
173✔
4521
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
173✔
4522
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
173✔
4523
    pNextWin->pStateKey->isNull = false;
173✔
4524
    pNextWin->winInfo.isOutput = true;
173✔
4525
  }
4526
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,223✔
4527
}
4528

4529
int32_t getStateWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SStateWindowInfo* pCurWin,
107✔
4530
                                SStateWindowInfo* pNextWin) {
4531
  int32_t code = TSDB_CODE_SUCCESS;
107✔
4532
  int32_t lino = 0;
107✔
4533
  int32_t size = pAggSup->resultRowSize;
107✔
4534
  pCurWin->winInfo.sessionWin.groupId = pKey->groupId;
107✔
4535
  pCurWin->winInfo.sessionWin.win.skey = pKey->win.skey;
107✔
4536
  pCurWin->winInfo.sessionWin.win.ekey = pKey->win.ekey;
107✔
4537
  code = getSessionWindowInfoByKey(pAggSup, pKey, &pCurWin->winInfo);
107✔
4538
  QUERY_CHECK_CODE(code, lino, _end);
107!
4539
  QUERY_CHECK_CONDITION((IS_VALID_SESSION_WIN(pCurWin->winInfo)), code, lino, _end,
107!
4540
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4541

4542
  pCurWin->pStateKey =
107✔
4543
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
107✔
4544
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
107✔
4545
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
107✔
4546
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
107✔
4547
  pCurWin->pStateKey->isNull = false;
107✔
4548
  pCurWin->winInfo.isOutput = true;
107✔
4549
  if (pCurWin->winInfo.pStatePos->needFree) {
107!
4550
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
107✔
4551
  }
4552

4553
  qDebug("===stream===get state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
107✔
4554
         pCurWin->winInfo.sessionWin.win.ekey);
4555

4556
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
107✔
4557
  getNextStateWin(pAggSup, pNextWin, true);
107✔
4558

4559
_end:
107✔
4560
  qDebug("===stream===get state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
107✔
4561
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4562
  if (code != TSDB_CODE_SUCCESS) {
107!
4563
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4564
  }
4565
  return code;
107✔
4566
}
4567

4568
int32_t setStateOutputBuf(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
3,115✔
4569
                          SStateWindowInfo* pCurWin, SStateWindowInfo* pNextWin, int32_t* pWinCode) {
4570
  int32_t size = pAggSup->resultRowSize;
3,115✔
4571
  pCurWin->winInfo.sessionWin.groupId = groupId;
3,115✔
4572
  pCurWin->winInfo.sessionWin.win.skey = ts;
3,115✔
4573
  pCurWin->winInfo.sessionWin.win.ekey = ts;
3,115✔
4574
  int32_t code = TSDB_CODE_SUCCESS;
3,115✔
4575
  int32_t lino = 0;
3,115✔
4576
  int32_t winCode = TSDB_CODE_SUCCESS;
3,115✔
4577
  code = pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData,
3,115✔
4578
                                                           pAggSup->stateKeySize, compareStateKey,
4579
                                                           (void**)&pCurWin->winInfo.pStatePos, &size, &winCode);
3,115✔
4580
  QUERY_CHECK_CODE(code, lino, _end);
3,115!
4581

4582
  pCurWin->pStateKey =
3,115✔
4583
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
3,115✔
4584
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
3,115✔
4585
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
3,115✔
4586
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
3,115✔
4587
  pCurWin->pStateKey->isNull = false;
3,115✔
4588

4589
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->winInfo.sessionWin.win)) {
3,115!
4590
    winCode = TSDB_CODE_FAILED;
×
4591
    clearOutputBuf(pAggSup->pState, pCurWin->winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
4592
    pCurWin->pStateKey =
×
4593
        (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
×
4594
    pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
×
4595
    pCurWin->pStateKey->type = pAggSup->stateKeyType;
×
4596
    pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
×
4597
    pCurWin->pStateKey->isNull = false;
×
4598
    pCurWin->winInfo.sessionWin.groupId = groupId;
×
4599
    pCurWin->winInfo.sessionWin.win.skey = ts;
×
4600
    pCurWin->winInfo.sessionWin.win.ekey = ts;
×
4601
    qDebug("===stream===reset state win key. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
×
4602
           pCurWin->winInfo.sessionWin.win.ekey);
4603
  }
4604

4605
  if (winCode == TSDB_CODE_SUCCESS) {
3,115✔
4606
    pCurWin->winInfo.isOutput = true;
1,925✔
4607
    if (pCurWin->winInfo.pStatePos->needFree) {
1,925✔
4608
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
64✔
4609
    }
4610
  } else if (pKeyData) {
1,190!
4611
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,190!
4612
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4613
    } else {
4614
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,186✔
4615
    }
4616
  }
4617

4618
  *pWinCode = winCode;
3,115✔
4619

4620
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
3,115✔
4621
         pCurWin->winInfo.sessionWin.win.ekey);
4622

4623
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
3,115✔
4624
  getNextStateWin(pAggSup, pNextWin, true);
3,115✔
4625
  qDebug("===stream===set state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
3,115✔
4626
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4627
_end:
1,362✔
4628
  if (code != TSDB_CODE_SUCCESS) {
3,115!
4629
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4630
  }
4631
  return code;
3,116✔
4632
}
4633

4634
int32_t updateStateWindowInfo(SStreamAggSupporter* pAggSup, SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin,
3,116✔
4635
                              TSKEY* pTs, uint64_t groupId, SColumnInfoData* pKeyCol, int32_t rows, int32_t start,
4636
                              bool* allEqual, SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted,
4637
                              int32_t* pWinRows) {
4638
  int32_t code = TSDB_CODE_SUCCESS;
3,116✔
4639
  int32_t lino = 0;
3,116✔
4640
  *allEqual = true;
3,116✔
4641
  for (int32_t i = start; i < rows; ++i) {
6,827✔
4642
    char* pKeyData = colDataGetData(pKeyCol, i);
3,820!
4643
    if (!isTsInWindow(pWinInfo, pTs[i])) {
3,820✔
4644
      if (isEqualStateKey(pWinInfo, pKeyData)) {
2,577✔
4645
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
2,468✔
4646
          // ts belongs to the next window
4647
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
137!
4648
            (*pWinRows) = i - start;
×
4649
            goto _end;
×
4650
          }
4651
        }
4652
      } else {
4653
        (*pWinRows) = i - start;
109✔
4654
        goto _end;
109✔
4655
      }
4656
    }
4657

4658
    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
3,711✔
4659
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
6!
4660
        code = saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
6✔
4661
        QUERY_CHECK_CODE(code, lino, _end);
6!
4662
      }
4663
      removeSessionResult(pAggSup, pSeUpdated, pResultRows, &pWinInfo->winInfo.sessionWin);
6✔
4664
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
6✔
4665
    }
4666
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
3,711✔
4667
    memcpy(pWinInfo->winInfo.pStatePos->pKey, &pWinInfo->winInfo.sessionWin, sizeof(SSessionKey));
3,711✔
4668
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
3,711✔
4669
      *allEqual = false;
23✔
4670
    }
4671
  }
4672
  (*pWinRows) = rows - start;
3,007✔
4673

4674
_end:
3,116✔
4675
  if (code != TSDB_CODE_SUCCESS) {
3,116!
4676
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4677
  }
4678
  return code;
3,116✔
4679
}
4680

4681
static bool isWinResult(SSessionKey* pKey, SSHashObj* pSeUpdate, SSHashObj* pResults) {
3,116✔
4682
  SSessionKey checkKey = {0};
3,116✔
4683
  getSessionHashKey(pKey, &checkKey);
3,116✔
4684
  if (tSimpleHashGet(pSeUpdate, &checkKey, sizeof(SSessionKey)) != NULL) {
3,114✔
4685
    return true;
30✔
4686
  }
4687

4688
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
3,086✔
4689
    return true;
17✔
4690
  }
4691
  return false;
3,069✔
4692
}
4693

4694
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
3,019✔
4695
                                 SSHashObj* pStDeleted) {
4696
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3,019✔
4697
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
3,019✔
4698

4699
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,019✔
4700
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
3,019✔
4701
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
3,019✔
4702
  int32_t                      code = TSDB_CODE_SUCCESS;
3,019✔
4703
  int32_t                      lino = 0;
3,019✔
4704
  TSKEY*                       tsCols = NULL;
3,019✔
4705
  SResultRow*                  pResult = NULL;
3,019✔
4706
  int32_t                      winRows = 0;
3,019✔
4707
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
3,019✔
4708
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
3,019✔
4709
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
3,019✔
4710

4711
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,019✔
4712
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,019✔
4713
  if (pAggSup->winRange.ekey <= 0) {
3,019!
4714
    pAggSup->winRange.ekey = INT64_MAX;
×
4715
  }
4716

4717
  if (pSDataBlock->pDataBlock != NULL) {
3,019!
4718
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,019✔
4719
    if (!pColDataInfo) {
3,019!
4720
      code = TSDB_CODE_FAILED;
×
4721
      QUERY_CHECK_CODE(code, lino, _end);
×
4722
    }
4723
    tsCols = (int64_t*)pColDataInfo->pData;
3,019✔
4724
  } else {
4725
    return;
×
4726
  }
4727

4728
  int32_t rows = pSDataBlock->info.rows;
3,019✔
4729
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
3,019✔
4730
  QUERY_CHECK_CODE(code, lino, _end);
3,019!
4731

4732
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
3,019✔
4733
  for (int32_t i = 0; i < rows; i += winRows) {
6,156✔
4734
    if (pInfo->ignoreExpiredData && checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo,
3,201✔
4735
                                                     &pInfo->twAggSup, pSDataBlock->info.id.uid, tsCols[i], NULL, 0) ||
64✔
4736
        colDataIsNull_s(pKeyColInfo, i)) {
6,248✔
4737
      i++;
21✔
4738
      continue;
41✔
4739
    }
4740
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
3,116!
4741
    int32_t          winIndex = 0;
3,116✔
4742
    bool             allEqual = true;
3,116✔
4743
    SStateWindowInfo curWin = {0};
3,116✔
4744
    SStateWindowInfo nextWin = {0};
3,116✔
4745
    int32_t          winCode = TSDB_CODE_SUCCESS;
3,116✔
4746
    code = setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin, &winCode);
3,116✔
4747
    QUERY_CHECK_CODE(code, lino, _end);
3,116!
4748

4749
    if (winCode != TSDB_CODE_SUCCESS && pTaskInfo->streamInfo.eventTypes) {
3,116!
4750
      SStateWindowInfo prevWin = {.winInfo.sessionWin = curWin.winInfo.sessionWin};
×
4751
      getNextStateWin(pAggSup, &prevWin, false);
×
4752
      qDebug("===stream===get state prev win buff. skey:%" PRId64 ", endkey:%" PRId64,
×
4753
             prevWin.winInfo.sessionWin.win.skey, prevWin.winInfo.sessionWin.win.ekey);
4754
      releaseOutputBuf(pAggSup->pState, prevWin.winInfo.pStatePos, &pAPI->stateStore);
×
4755
      // For ordered data, the previous window's closure did not record the corresponding state values, so they need to
4756
      // be added here.
4757
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE) &&
×
4758
          IS_VALID_SESSION_WIN(prevWin.winInfo)) {
×
4759
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &prevWin.winInfo.sessionWin, prevWin.pStateKey,
×
4760
                                      curWin.pStateKey, true, pNotifySup, pNotifyEventStat);
×
4761
        QUERY_CHECK_CODE(code, lino, _end);
×
4762
      }
4763
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
×
4764
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4765
                                      prevWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4766
        QUERY_CHECK_CODE(code, lino, _end);
×
4767
      }
4768
    }
4769

4770
    if (isWinResult(&nextWin.winInfo.sessionWin, pSeUpdated, pAggSup->pResultRows) == false) {
3,116✔
4771
      releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,069✔
4772
    }
4773

4774
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
3,116✔
4775
    code = updateStateWindowInfo(pAggSup, &curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
3,116✔
4776
                                 pAggSup->pResultRows, pSeUpdated, pStDeleted, &winRows);
4777
    QUERY_CHECK_CODE(code, lino, _end);
3,116!
4778

4779
    if (!allEqual) {
3,116✔
4780
      uint64_t uid = 0;
20✔
4781
      code = appendDataToSpecialBlock(pAggSup->pScanBlock, &curWin.winInfo.sessionWin.win.skey,
20✔
4782
                                      &curWin.winInfo.sessionWin.win.ekey, &uid, &groupId, NULL);
4783
      QUERY_CHECK_CODE(code, lino, _end);
20!
4784
      int32_t tmpRes = tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
20✔
4785
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
20!
4786

4787
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
20✔
4788
      releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
20✔
4789
      continue;
20✔
4790
    }
4791

4792
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
3,096✔
4793
                              pOperator, 0);
4794
    QUERY_CHECK_CODE(code, lino, _end);
3,096!
4795

4796
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,096✔
4797
    QUERY_CHECK_CODE(code, lino, _end);
3,096!
4798

4799
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
3,096!
4800
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
1✔
4801
      QUERY_CHECK_CODE(code, lino, _end);
1!
4802
    }
4803

4804
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,096✔
4805
      code = saveResult(curWin.winInfo, pSeUpdated);
2,783✔
4806
      QUERY_CHECK_CODE(code, lino, _end);
2,783!
4807
    }
4808

4809
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,096✔
4810
      curWin.winInfo.pStatePos->beUpdated = true;
313✔
4811
      SSessionKey key = {0};
313✔
4812
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
313✔
4813
      code =
4814
          tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
313✔
4815
      QUERY_CHECK_CODE(code, lino, _end);
313!
4816
    }
4817

4818
    // If this is a windown recalculation, add the corresponding state values here since the next window may not require
4819
    // recalculation.
4820
    if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE)) {
3,096!
4821
      code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4822
                                    nextWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4823
      QUERY_CHECK_CODE(code, lino, _end);
×
4824
    }
4825
  }
4826

4827
_end:
3,019✔
4828
  if (code != TSDB_CODE_SUCCESS) {
3,019!
4829
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4830
  }
4831
}
4832

4833
int32_t doStreamStateEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
2✔
4834
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
2✔
4835
  if (!pInfo) {
2!
4836
    return 0;
×
4837
  }
4838

4839
  void* pData = (buf == NULL) ? NULL : *buf;
2✔
4840

4841
  // 1.streamAggSup.pResultRows
4842
  int32_t tlen = 0;
2✔
4843
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
2✔
4844
  tlen += taosEncodeFixedI32(buf, mapSize);
2✔
4845
  void*   pIte = NULL;
2✔
4846
  size_t  keyLen = 0;
2✔
4847
  int32_t iter = 0;
2✔
4848
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
4✔
4849
    void* key = tSimpleHashGetKey(pIte, &keyLen);
2✔
4850
    tlen += encodeSSessionKey(buf, key);
2✔
4851
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
2✔
4852
  }
4853

4854
  // 2.twAggSup
4855
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
2✔
4856

4857
  // 3.pChildren
4858
  int32_t size = taosArrayGetSize(pInfo->pChildren);
2✔
4859
  tlen += taosEncodeFixedI32(buf, size);
2✔
4860
  for (int32_t i = 0; i < size; i++) {
2!
4861
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4862
    tlen += doStreamStateEncodeOpState(buf, 0, pChOp, false);
×
4863
  }
4864

4865
  // 4.dataVersion
4866
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
2✔
4867

4868
  // 5.basicInfo
4869
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
2✔
4870

4871
  // 6.checksum
4872
  if (isParent) {
2!
4873
    if (buf) {
2✔
4874
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
2!
4875
      tlen += taosEncodeFixedU32(buf, cksum);
1✔
4876
    } else {
4877
      tlen += sizeof(uint32_t);
1✔
4878
    }
4879
  }
4880

4881
  return tlen;
2✔
4882
}
4883

4884
int32_t doStreamStateDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
4885
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
4886
  int32_t                      code = TSDB_CODE_SUCCESS;
×
4887
  int32_t                      lino = 0;
×
4888
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
×
4889
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
4890
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
×
4891
  if (!pInfo) {
×
4892
    code = TSDB_CODE_FAILED;
×
4893
    QUERY_CHECK_CODE(code, lino, _end);
×
4894
  }
4895

4896
  // 6.checksum
4897
  if (isParent) {
×
4898
    int32_t dataLen = len - sizeof(uint32_t);
×
4899
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
4900
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
4901
      qError("stream state_window state is invalid");
×
4902
      code = TSDB_CODE_FAILED;
×
4903
      QUERY_CHECK_CODE(code, lino, _end);
×
4904
    }
4905
    pDataEnd = pCksum;
×
4906
  }
4907

4908
  // 1.streamAggSup.pResultRows
4909
  int32_t mapSize = 0;
×
4910
  buf = taosDecodeFixedI32(buf, &mapSize);
×
4911
  for (int32_t i = 0; i < mapSize; i++) {
×
4912
    SResultWindowInfo winfo = {0};
×
4913
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
4914
    int32_t winCode = TSDB_CODE_SUCCESS;
×
4915
    code = pAggSup->stateStore.streamStateStateAddIfNotExist(
×
4916
        pAggSup->pState, &winfo.sessionWin, NULL, pAggSup->stateKeySize, compareStateKey, (void**)&winfo.pStatePos,
4917
        &pAggSup->resultRowSize, &winCode);
4918
    QUERY_CHECK_CODE(code, lino, _end);
×
4919

4920
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
4921
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
4922
                          sizeof(SResultWindowInfo));
4923
    QUERY_CHECK_CODE(code, lino, _end);
×
4924
  }
4925

4926
  // 2.twAggSup
4927
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
4928

4929
  // 3.pChildren
4930
  int32_t size = 0;
×
4931
  buf = taosDecodeFixedI32(buf, &size);
×
4932
  for (int32_t i = 0; i < size; i++) {
×
4933
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4934
    code = doStreamStateDecodeOpState(buf, 0, pChOp, false, &buf);
×
4935
    QUERY_CHECK_CODE(code, lino, _end);
×
4936
  }
4937

4938
  // 4.dataVersion
4939
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
4940

4941
  if (ppBuf) {
×
4942
    (*ppBuf) = buf;
×
4943
  }
4944

4945
  // 5.basicInfo
4946
  if (buf < pDataEnd) {
×
4947
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
×
4948
    QUERY_CHECK_CODE(code, lino, _end);
×
4949
  }
4950

4951
_end:
×
4952
  if (code != TSDB_CODE_SUCCESS) {
×
4953
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4954
  }
4955
  return code;
×
4956
}
4957

4958
void doStreamStateSaveCheckpoint(SOperatorInfo* pOperator) {
77✔
4959
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
77✔
4960
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
77✔
4961
    int32_t len = doStreamStateEncodeOpState(NULL, 0, pOperator, true);
1✔
4962
    void*   buf = taosMemoryCalloc(1, len);
1!
4963
    if (!buf) {
1!
4964
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
4965
      return;
×
4966
    }
4967
    void* pBuf = buf;
1✔
4968
    len = doStreamStateEncodeOpState(&pBuf, len, pOperator, true);
1✔
4969
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
1✔
4970
                                                       strlen(STREAM_STATE_OP_CHECKPOINT_NAME), buf, len);
4971
    taosMemoryFree(buf);
1!
4972
    saveStreamOperatorStateComplete(&pInfo->basic);
1✔
4973
  }
4974
}
4975

4976
static int32_t buildStateResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
3,602✔
4977
  int32_t                      code = TSDB_CODE_SUCCESS;
3,602✔
4978
  int32_t                      lino = 0;
3,602✔
4979
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,602✔
4980
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
3,602✔
4981
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
3,602✔
4982
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
3,602✔
4983
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
3,602✔
4984
  bool                         addNotifyEvent = false;
3,602✔
4985
  addNotifyEvent = BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
3,602✔
4986
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
3,602✔
4987
  if (pInfo->pDelRes->info.rows > 0) {
3,601✔
4988
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
183✔
4989
    if (addNotifyEvent) {
183!
4990
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
4991
      QUERY_CHECK_CODE(code, lino, _end);
×
4992
    }
4993
    (*ppRes) = pInfo->pDelRes;
183✔
4994
    return code;
183✔
4995
  }
4996

4997
  doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes,
3,418!
4998
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
4999
  if (pBInfo->pRes->info.rows > 0) {
3,419✔
5000
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,201✔
5001
    if (addNotifyEvent) {
1,201!
5002
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
5003
                                     pNotifySup, pNotifyEventStat);
5004
      QUERY_CHECK_CODE(code, lino, _end);
×
5005
    }
5006
    (*ppRes) = pBInfo->pRes;
1,201✔
5007
    return code;
1,201✔
5008
  }
5009

5010
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
2,218✔
5011
  QUERY_CHECK_CODE(code, lino, _end);
2,217!
5012
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
2,217!
5013
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5014
    (*ppRes) = pNotifySup->pEventBlock;
×
5015
    return code;
×
5016
  }
5017

5018
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
2,217✔
5019
  QUERY_CHECK_CODE(code, lino, _end);
2,217!
5020

5021
_end:
2,217✔
5022
  if (code != TSDB_CODE_SUCCESS) {
2,217!
5023
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5024
  }
5025
  (*ppRes) = NULL;
2,217✔
5026
  return code;
2,217✔
5027
}
5028

5029
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
3,956✔
5030
  if (pOperator->status == OP_EXEC_DONE) {
3,956!
5031
    (*ppRes) = NULL;
×
5032
    return TSDB_CODE_SUCCESS;
×
5033
  }
5034

5035
  int32_t                      code = TSDB_CODE_SUCCESS;
3,956✔
5036
  int32_t                      lino = 0;
3,956✔
5037
  SExprSupp*                   pSup = &pOperator->exprSupp;
3,956✔
5038
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,956✔
5039
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
3,956✔
5040
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
3,956✔
5041
  qDebug("===stream=== stream state agg");
3,956✔
5042
  if (pOperator->status == OP_RES_TO_RETURN) {
3,957✔
5043
    SSDataBlock* resBlock = NULL;
1,384✔
5044
    code = buildStateResult(pOperator, &resBlock);
1,384✔
5045
    QUERY_CHECK_CODE(code, lino, _end);
1,384!
5046
    if (resBlock != NULL) {
1,384✔
5047
      (*ppRes) = resBlock;
332✔
5048
      return code;
1,384✔
5049
    }
5050

5051
    if (pInfo->recvGetAll) {
1,052✔
5052
      pInfo->recvGetAll = false;
2✔
5053
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
2✔
5054
    }
5055

5056
    if (pInfo->reCkBlock) {
1,052!
5057
      pInfo->reCkBlock = false;
×
5058
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5059
      (*ppRes) = pInfo->pCheckpointRes;
×
5060
      return code;
×
5061
    }
5062

5063
    setStreamOperatorCompleted(pOperator);
1,052✔
5064
    (*ppRes) = NULL;
1,052✔
5065
    return code;
1,052✔
5066
  }
5067

5068
  SOperatorInfo* downstream = pOperator->pDownstream[0];
2,573✔
5069
  if (!pInfo->pUpdated) {
2,573✔
5070
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,217✔
5071
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,217!
5072
  }
5073
  if (!pInfo->pSeUpdated) {
2,573✔
5074
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,188✔
5075
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,188✔
5076
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,189!
5077
  }
5078
  while (1) {
3,604✔
5079
    SSDataBlock* pBlock = NULL;
6,178✔
5080
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
6,178✔
5081
    QUERY_CHECK_CODE(code, lino, _end);
6,177!
5082

5083
    if (pBlock == NULL) {
6,177✔
5084
      break;
2,217✔
5085
    }
5086
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
3,960✔
5087
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
3,960✔
5088

5089
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
3,960✔
5090
        pBlock->info.type == STREAM_CLEAR) {
3,524✔
5091
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
501!
5092
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
501✔
5093
                                   pInfo->pPkDeleted, add);
5094
      QUERY_CHECK_CODE(code, lino, _end);
501!
5095
      continue;
585✔
5096
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,459✔
5097
      pInfo->recvGetAll = true;
7✔
5098
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
7✔
5099
      QUERY_CHECK_CODE(code, lino, _end);
7!
5100
      continue;
7✔
5101
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,452✔
5102
      (*ppRes) = pBlock;
356✔
5103
      return code;
356✔
5104
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,096✔
5105
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
77✔
5106
      doStreamStateSaveCheckpoint(pOperator);
77✔
5107
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
77✔
5108
      QUERY_CHECK_CODE(code, lino, _end);
77!
5109

5110
      continue;
77✔
5111
    } else {
5112
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
3,019!
5113
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5114
        QUERY_CHECK_CODE(code, lino, _end);
×
5115
      }
5116
    }
5117

5118
    if (pInfo->scalarSupp.pExprInfo != NULL) {
3,019✔
5119
      SExprSupp* pExprSup = &pInfo->scalarSupp;
256✔
5120
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
256✔
5121
      QUERY_CHECK_CODE(code, lino, _end);
256!
5122
    }
5123
    // the pDataBlock are always the same one, no need to call this again
5124
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3,019✔
5125
    QUERY_CHECK_CODE(code, lino, _end);
3,019!
5126
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
3,019✔
5127
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
3,019✔
5128
  }
5129
  // restore the value
5130
  pOperator->status = OP_RES_TO_RETURN;
2,217✔
5131

5132
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,217✔
5133
  QUERY_CHECK_CODE(code, lino, _end);
2,218!
5134

5135
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,218✔
5136
  QUERY_CHECK_CODE(code, lino, _end);
2,218!
5137

5138
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,218✔
5139

5140
  if (pInfo->isHistoryOp) {
2,218✔
5141
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
85✔
5142
    QUERY_CHECK_CODE(code, lino, _end);
85!
5143
  }
5144
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,218!
5145
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
4✔
5146
    QUERY_CHECK_CODE(code, lino, _end);
4!
5147
  }
5148

5149
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,218✔
5150
  pInfo->pUpdated = NULL;
2,218✔
5151
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,218✔
5152
  QUERY_CHECK_CODE(code, lino, _end);
2,218!
5153

5154
  SSDataBlock* resBlock = NULL;
2,218✔
5155
  code = buildStateResult(pOperator, &resBlock);
2,218✔
5156
  QUERY_CHECK_CODE(code, lino, _end);
2,218!
5157
  if (resBlock != NULL) {
2,218✔
5158
    (*ppRes) = resBlock;
1,052✔
5159
    return code;
1,052✔
5160
  }
5161

5162
_end:
1,166✔
5163
  if (code != TSDB_CODE_SUCCESS) {
1,166!
5164
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5165
    pTaskInfo->code = code;
×
5166
    T_LONG_JMP(pTaskInfo->env, code);
×
5167
  }
5168
  setStreamOperatorCompleted(pOperator);
1,166✔
5169
  (*ppRes) = NULL;
1,166✔
5170
  return code;
1,166✔
5171
}
5172

5173
static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
×
5174
  SSDataBlock* pRes = NULL;
×
5175
  int32_t      code = doStreamStateAggNext(pOperator, &pRes);
×
5176
  return pRes;
×
5177
}
5178

5179
void streamStateReleaseState(SOperatorInfo* pOperator) {
73✔
5180
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
73✔
5181
  int32_t                      winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
73✔
5182
  int32_t                      resSize = winSize + sizeof(TSKEY);
73✔
5183
  char*                        pBuff = taosMemoryCalloc(1, resSize);
73!
5184
  if (!pBuff) {
73!
5185
    return;
×
5186
  }
5187
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
73✔
5188
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
73✔
5189
  qDebug("===stream=== relase state. save result count:%d", (int32_t)taosArrayGetSize(pInfo->historyWins));
73✔
5190
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_STATE_NAME,
73✔
5191
                                                     strlen(STREAM_STATE_OP_STATE_NAME), pBuff, resSize);
5192
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
73✔
5193
  taosMemoryFreeClear(pBuff);
73!
5194

5195
  SOperatorInfo* downstream = pOperator->pDownstream[0];
73✔
5196
  if (downstream->fpSet.releaseStreamStateFn) {
73!
5197
    downstream->fpSet.releaseStreamStateFn(downstream);
73✔
5198
  }
5199
}
5200

5201
static int32_t compactStateWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
×
5202
                                  SSHashObj* pStUpdated, SSHashObj* pStDeleted) {
5203
  SExprSupp*                   pSup = &pOperator->exprSupp;
×
5204
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
5205
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
5206
  return compactTimeWindow(pSup, &pInfo->streamAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, pNextWin, pStUpdated,
×
5207
                           pStDeleted, false);
5208
}
5209

5210
void streamStateReloadState(SOperatorInfo* pOperator) {
73✔
5211
  int32_t                      code = TSDB_CODE_SUCCESS;
73✔
5212
  int32_t                      lino = 0;
73✔
5213
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
73✔
5214
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
73✔
5215
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
73✔
5216
  resetWinRange(&pAggSup->winRange);
73✔
5217

5218
  SSessionKey seKey = {.win.skey = INT64_MIN, .win.ekey = INT64_MIN, .groupId = 0};
73✔
5219
  int32_t     size = 0;
73✔
5220
  void*       pBuf = NULL;
73✔
5221
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_STATE_OP_STATE_NAME,
73✔
5222
                                                strlen(STREAM_STATE_OP_STATE_NAME), &pBuf, &size);
5223
  QUERY_CHECK_CODE(code, lino, _end);
73!
5224

5225
  int32_t num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
73✔
5226
  qDebug("===stream=== reload state. get result count:%d", num);
73✔
5227
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
73✔
5228

5229
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
73✔
5230
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
73✔
5231
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
73✔
5232

5233
  if (!pInfo->pSeUpdated && num > 0) {
73!
5234
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
29✔
5235
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
29✔
5236
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
29!
5237
  }
5238
  if (!pInfo->pSeDeleted && num > 0) {
73!
5239
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
5240
    pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
×
5241
    QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _end, terrno);
×
5242
  }
5243
  for (int32_t i = 0; i < num; i++) {
180✔
5244
    SStateWindowInfo curInfo = {0};
107✔
5245
    SStateWindowInfo nextInfo = {0};
107✔
5246
    qDebug("===stream=== reload state. try process result %" PRId64 ", %" PRIu64 ", index:%d", pSeKeyBuf[i].win.skey,
107✔
5247
           pSeKeyBuf[i].groupId, i);
5248
    code = getStateWindowInfoByKey(pAggSup, pSeKeyBuf + i, &curInfo, &nextInfo);
107✔
5249
    QUERY_CHECK_CODE(code, lino, _end);
107!
5250

5251
    bool cpRes = compareWinStateKey(curInfo.pStateKey, nextInfo.pStateKey);
107✔
5252
    qDebug("===stream=== reload state. next window info %" PRId64 ", %" PRIu64 ", compare:%d",
107✔
5253
           nextInfo.winInfo.sessionWin.win.skey, nextInfo.winInfo.sessionWin.groupId, cpRes);
5254
    if (cpRes) {
107!
5255
      code = compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pSeUpdated, pInfo->pSeDeleted);
×
5256
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, curInfo.winInfo.sessionWin.win.skey,
×
5257
             curInfo.winInfo.sessionWin.groupId);
5258
      QUERY_CHECK_CODE(code, lino, _end);
×
5259

5260
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
5261
        code = saveResult(curInfo.winInfo, pInfo->pSeUpdated);
×
5262
        QUERY_CHECK_CODE(code, lino, _end);
×
5263
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
5264
        if (!isCloseWindow(&curInfo.winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
5265
          code = saveDeleteRes(pInfo->pSeDeleted, curInfo.winInfo.sessionWin);
×
5266
          QUERY_CHECK_CODE(code, lino, _end);
×
5267
        }
5268
        SSessionKey key = {0};
×
5269
        getSessionHashKey(&curInfo.winInfo.sessionWin, &key);
×
5270
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curInfo.winInfo,
×
5271
                              sizeof(SResultWindowInfo));
5272
        QUERY_CHECK_CODE(code, lino, _end);
×
5273
      }
5274
    } else if (IS_VALID_SESSION_WIN(nextInfo.winInfo)) {
107!
5275
      releaseOutputBuf(pAggSup->pState, nextInfo.winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
5276
    }
5277

5278
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
107!
5279
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
107✔
5280
      QUERY_CHECK_CODE(code, lino, _end);
107!
5281
    }
5282
  }
5283
  taosMemoryFreeClear(pBuf);
73!
5284

5285
  SOperatorInfo* downstream = pOperator->pDownstream[0];
73✔
5286
  if (downstream->fpSet.reloadStreamStateFn) {
73!
5287
    downstream->fpSet.reloadStreamStateFn(downstream);
73✔
5288
  }
5289
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
73✔
5290

5291
_end:
73✔
5292
  taosMemoryFreeClear(pBuf);
73!
5293
  if (code != TSDB_CODE_SUCCESS) {
73!
5294
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5295
  }
5296
}
73✔
5297

5298
int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
326✔
5299
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5300
  QRY_PARAM_CHECK(pOptrInfo);
326!
5301
  int32_t code = 0;
326✔
5302
  int32_t lino = 0;
326✔
5303

5304
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
326✔
5305
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
326✔
5306
  SColumnNode*                 pColNode = (SColumnNode*)(pStateNode->pStateKey);
326✔
5307
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
326!
5308
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
326!
5309
  if (pInfo == NULL || pOperator == NULL) {
326!
5310
    code = terrno;
×
5311
    QUERY_CHECK_CODE(code, lino, _error);
×
5312
  }
5313

5314
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
326✔
5315
  initResultSizeInfo(&pOperator->resultInfo, 4096);
326✔
5316
  if (pStateNode->window.pExprs != NULL) {
326✔
5317
    int32_t    numOfScalar = 0;
25✔
5318
    SExprInfo* pScalarExprInfo = NULL;
25✔
5319
    code = createExprInfo(pStateNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
25✔
5320
    QUERY_CHECK_CODE(code, lino, _error);
25!
5321

5322
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
25✔
5323
    QUERY_CHECK_CODE(code, lino, _error);
25!
5324
  }
5325

5326
  pInfo->twAggSup = (STimeWindowAggSupp){
326✔
5327
      .waterMark = pStateNode->window.watermark,
326✔
5328
      .calTrigger = pStateNode->window.triggerType,
326✔
5329
      .maxTs = INT64_MIN,
5330
      .minTs = INT64_MAX,
5331
      .deleteMark = getDeleteMark(&pStateNode->window, 0),
326✔
5332
  };
5333

5334
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
326✔
5335
  QUERY_CHECK_CODE(code, lino, _error);
326!
5336

5337
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
326✔
5338
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
326!
5339
  pInfo->binfo.pRes = pResBlock;
326✔
5340

5341
  SExprSupp* pExpSup = &pOperator->exprSupp;
326✔
5342
  int32_t    numOfCols = 0;
326✔
5343
  SExprInfo* pExprInfo = NULL;
326✔
5344
  code = createExprInfo(pStateNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
326✔
5345
  QUERY_CHECK_CODE(code, lino, _error);
326!
5346

5347
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
326✔
5348
  if (code != TSDB_CODE_SUCCESS) {
326!
5349
    goto _error;
×
5350
  }
5351
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
326✔
5352
  int16_t type = pColNode->node.resType.type;
326✔
5353
  pInfo->primaryTsIndex = tsSlotId;
326✔
5354
  code =
5355
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize, type,
326✔
5356
                             &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
326✔
5357
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
5358
  QUERY_CHECK_CODE(code, lino, _error);
326!
5359

5360
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
326✔
5361
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
326✔
5362
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
326!
5363
  pInfo->pDelIterator = NULL;
326✔
5364

5365
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
326✔
5366
  QUERY_CHECK_CODE(code, lino, _error);
326!
5367

5368
  pInfo->pChildren = NULL;
326✔
5369
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
326✔
5370
  pInfo->ignoreExpiredDataSaved = false;
326✔
5371
  pInfo->pUpdated = NULL;
326✔
5372
  pInfo->pSeUpdated = NULL;
326✔
5373
  pInfo->dataVersion = 0;
326✔
5374
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
326✔
5375
  if (!pInfo->historyWins) {
326!
5376
    code = terrno;
×
5377
    QUERY_CHECK_CODE(code, lino, _error);
×
5378
  }
5379

5380
  if (pHandle) {
326!
5381
    pInfo->isHistoryOp = pHandle->fillHistory;
326✔
5382
  }
5383

5384
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
326✔
5385
  QUERY_CHECK_CODE(code, lino, _error);
326!
5386

5387
  pInfo->recvGetAll = false;
326✔
5388
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
326✔
5389
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
326!
5390
  pInfo->destHasPrimaryKey = pStateNode->window.destHasPrimaryKey;
326✔
5391
  pInfo->pOperator = pOperator;
326✔
5392

5393
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
326✔
5394
                  pInfo, pTaskInfo);
5395
  // for stream
5396
  void*   buff = NULL;
326✔
5397
  int32_t len = 0;
326✔
5398
  int32_t res =
5399
      pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
326✔
5400
                                                        strlen(STREAM_STATE_OP_CHECKPOINT_NAME), &buff, &len);
5401
  if (res == TSDB_CODE_SUCCESS) {
326!
5402
    code = doStreamStateDecodeOpState(buff, len, pOperator, true, NULL);
×
5403
    taosMemoryFree(buff);
×
5404
    QUERY_CHECK_CODE(code, lino, _error);
×
5405
  }
5406

5407
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAggNext, NULL, destroyStreamStateOperatorInfo,
326✔
5408
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5409
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
326✔
5410

5411
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
326✔
5412
  QUERY_CHECK_CODE(code, lino, _error);
326!
5413

5414
  code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
326✔
5415
                        &pInfo->twAggSup, &pInfo->basic);
326✔
5416
  QUERY_CHECK_CODE(code, lino, _error);
326!
5417

5418
  code = appendDownstream(pOperator, &downstream, 1);
326✔
5419
  QUERY_CHECK_CODE(code, lino, _error);
326!
5420

5421
  pInfo->trueForLimit = pStateNode->trueForLimit;
326✔
5422

5423
  *pOptrInfo = pOperator;
326✔
5424
  return TSDB_CODE_SUCCESS;
326✔
5425

5426
_error:
×
5427
  if (pInfo != NULL) destroyStreamStateOperatorInfo(pInfo);
×
5428
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5429
  pTaskInfo->code = code;
×
5430
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5431
  return code;
×
5432
}
5433

5434
#ifdef BUILD_NO_CALL
5435
static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type) {
5436
  for (int i = 0; i < num; i++) {
5437
    if (type == STREAM_INVERT) {
5438
      fmSetInvertFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5439
    } else if (type == STREAM_NORMAL) {
5440
      fmSetNormalFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5441
    }
5442
  }
5443
}
5444
#endif
5445

5446
static int32_t doStreamIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
21,968✔
5447
  int32_t                      code = TSDB_CODE_SUCCESS;
21,968✔
5448
  int32_t                      lino = 0;
21,968✔
5449
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
21,968✔
5450
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
21,968✔
5451
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
21,968✔
5452
  SExprSupp*                   pSup = &pOperator->exprSupp;
21,968✔
5453

5454
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
21,968✔
5455

5456
  if (pOperator->status == OP_EXEC_DONE) {
21,969✔
5457
    (*ppRes) = NULL;
666✔
5458
    return code;
666✔
5459
  }
5460

5461
  if (pOperator->status == OP_RES_TO_RETURN) {
21,303✔
5462
    SSDataBlock* resBlock = NULL;
6,368✔
5463
    code = buildIntervalResult(pOperator, &resBlock);
6,368✔
5464
    QUERY_CHECK_CODE(code, lino, _end);
6,368!
5465
    if (resBlock != NULL) {
6,368✔
5466
      (*ppRes) = resBlock;
2,532✔
5467
      return code;
6,368✔
5468
    }
5469

5470
    if (pInfo->recvGetAll) {
3,836✔
5471
      pInfo->recvGetAll = false;
176✔
5472
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
176✔
5473
    }
5474

5475
    if (pInfo->reCkBlock) {
3,836✔
5476
      pInfo->reCkBlock = false;
88✔
5477
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
88✔
5478
      (*ppRes) = pInfo->pCheckpointRes;
88✔
5479
      return code;
88✔
5480
    }
5481

5482
    setStreamOperatorCompleted(pOperator);
3,748✔
5483
    (*ppRes) = NULL;
3,748✔
5484
    return code;
3,748✔
5485
  }
5486

5487
  SOperatorInfo* downstream = pOperator->pDownstream[0];
14,935✔
5488

5489
  if (!pInfo->pUpdated) {
14,935✔
5490
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
12,230✔
5491
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
12,228!
5492
  }
5493

5494
  if (!pInfo->pUpdatedMap) {
14,933✔
5495
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
12,228✔
5496
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
12,228✔
5497
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
12,228!
5498
  }
5499

5500
  while (1) {
745,292✔
5501
    SSDataBlock* pBlock = NULL;
760,225✔
5502
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
760,225✔
5503
    QUERY_CHECK_CODE(code, lino, _end);
760,226✔
5504

5505
    if (pBlock == NULL) {
760,206✔
5506
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
12,231✔
5507
             pInfo->numOfDatapack);
5508
      pInfo->numOfDatapack = 0;
12,230✔
5509
      break;
12,230✔
5510
    }
5511

5512
    pInfo->numOfDatapack++;
747,975✔
5513
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
747,975✔
5514
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
747,975✔
5515

5516
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
747,974✔
5517
        pBlock->info.type == STREAM_CLEAR) {
747,589✔
5518
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,329✔
5519
      QUERY_CHECK_CODE(code, lino, _end);
1,327!
5520
      continue;
3,398✔
5521
    } else if (pBlock->info.type == STREAM_GET_ALL) {
746,645✔
5522
      pInfo->recvGetAll = true;
1,011✔
5523
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
1,011✔
5524
      QUERY_CHECK_CODE(code, lino, _end);
1,011!
5525
      continue;
1,011✔
5526
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
745,634✔
5527
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,629✔
5528
      (*ppRes) = pBlock;
2,629✔
5529
      return code;
2,684✔
5530
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
743,005✔
5531
      doDeleteWindowByGroupId(pOperator, pBlock);
55✔
5532
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
55✔
5533
      (*ppRes) = pBlock;
55✔
5534
      return code;
55✔
5535
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
742,950✔
5536
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,060✔
5537
      doStreamIntervalSaveCheckpoint(pOperator);
1,060✔
5538
      pInfo->reCkBlock = true;
1,060✔
5539
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,060✔
5540
      QUERY_CHECK_CODE(code, lino, _end);
1,060!
5541

5542
      continue;
1,060✔
5543
    } else {
5544
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
741,890!
5545
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5546
        QUERY_CHECK_CODE(code, lino, _end);
×
5547
      }
5548
    }
5549

5550
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
741,890✔
5551
      // set input version
5552
      pTaskInfo->version = pBlock->info.version;
11,079✔
5553
    }
5554

5555
    if (pInfo->scalarSupp.pExprInfo != NULL) {
741,890✔
5556
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5557
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5558
      QUERY_CHECK_CODE(code, lino, _end);
13!
5559
    }
5560

5561
    // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
5562
    // caller. Note that all the time window are not close till now.
5563
    // the pDataBlock are always the same one, no need to call this again
5564
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
741,890✔
5565
    QUERY_CHECK_CODE(code, lino, _end);
741,892!
5566
#ifdef BUILD_NO_CALL
5567
    if (pInfo->invertible) {
5568
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
5569
    }
5570
#endif
5571

5572
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
741,892✔
5573
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
741,894!
5574
      pOperator->status = OP_RES_TO_RETURN;
×
5575
      code = TSDB_CODE_SUCCESS;
×
5576
      break;
×
5577
    }
5578
    QUERY_CHECK_CODE(code, lino, _end);
741,894!
5579
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
741,894✔
5580
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
741,894✔
5581
  }
5582
  pOperator->status = OP_RES_TO_RETURN;
12,230✔
5583
  if (!pInfo->destHasPrimaryKey) {
12,230✔
5584
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
12,212✔
5585
  }
5586
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
12,231✔
5587
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5588
  QUERY_CHECK_CODE(code, lino, _end);
12,232!
5589

5590
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
12,232!
5591
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
17✔
5592
    QUERY_CHECK_CODE(code, lino, _end);
16!
5593
  }
5594

5595
  void*   pIte = NULL;
12,231✔
5596
  int32_t iter = 0;
12,231✔
5597
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
6,542,886✔
5598
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
6,530,655✔
5599
    if (!tmp) {
6,530,655!
5600
      code = terrno;
×
5601
      QUERY_CHECK_CODE(code, lino, _end);
×
5602
    }
5603
  }
5604
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
12,232✔
5605

5606
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
12,233✔
5607
  pInfo->pUpdated = NULL;
12,233✔
5608
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
12,233✔
5609
  QUERY_CHECK_CODE(code, lino, _end);
12,232!
5610

5611
  tSimpleHashCleanup(pInfo->pUpdatedMap);
12,232✔
5612
  pInfo->pUpdatedMap = NULL;
12,233✔
5613

5614
  code = buildIntervalResult(pOperator, ppRes);
12,233✔
5615
  QUERY_CHECK_CODE(code, lino, _end);
12,232!
5616

5617
  return code;
12,232✔
5618

5619
_end:
20✔
5620
  if (code != TSDB_CODE_SUCCESS) {
20!
5621
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
20!
5622
    pTaskInfo->code = code;
20✔
5623
    T_LONG_JMP(pTaskInfo->env, code);
20!
5624
  }
5625
  setStreamOperatorCompleted(pOperator);
×
5626
  (*ppRes) = NULL;
×
5627
  return code;
×
5628
}
5629

5630
static int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
2,886✔
5631
                                                      SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
5632
                                                      SOperatorInfo** pOptrInfo) {
5633
  QRY_PARAM_CHECK(pOptrInfo);
2,886!
5634

5635
  int32_t code = TSDB_CODE_SUCCESS;
2,886✔
5636
  int32_t lino = 0;
2,886✔
5637
  int32_t numOfCols = 0;
2,886✔
5638

5639
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
2,886!
5640
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
2,886!
5641
  if (pInfo == NULL || pOperator == NULL) {
2,886!
5642
    code = terrno;
×
5643
    QUERY_CHECK_CODE(code, lino, _error);
×
5644
  }
5645

5646
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
2,886✔
5647

5648
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
2,886✔
5649
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
2,886!
5650
  initBasicInfo(&pInfo->binfo, pResBlock);
2,886✔
5651

5652
  pInfo->interval = (SInterval){
2,886✔
5653
      .interval = pIntervalPhyNode->interval,
2,886✔
5654
      .sliding = pIntervalPhyNode->sliding,
2,886✔
5655
      .intervalUnit = pIntervalPhyNode->intervalUnit,
2,886✔
5656
      .slidingUnit = pIntervalPhyNode->slidingUnit,
2,886✔
5657
      .offset = pIntervalPhyNode->offset,
2,886✔
5658
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
2,886✔
5659
      .timeRange = pIntervalPhyNode->timeRange,
2,886✔
5660
  };
5661
  calcIntervalAutoOffset(&pInfo->interval);
2,886✔
5662

5663
  pInfo->twAggSup =
2,886✔
5664
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
2,886✔
5665
                           .calTrigger = pIntervalPhyNode->window.triggerType,
2,886✔
5666
                           .maxTs = INT64_MIN,
5667
                           .minTs = INT64_MAX,
5668
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
2,886✔
5669

5670
  pOperator->pTaskInfo = pTaskInfo;
2,886✔
5671
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
2,886✔
5672

5673
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2,886✔
5674
  pInfo->ignoreExpiredDataSaved = false;
2,886✔
5675

5676
  SExprSupp* pSup = &pOperator->exprSupp;
2,886✔
5677
  pSup->hasWindowOrGroup = true;
2,886✔
5678

5679
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2,886✔
5680
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5681

5682
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
2,886✔
5683
  initResultSizeInfo(&pOperator->resultInfo, 4096);
2,886✔
5684

5685
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
2,886!
5686
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
2,886!
5687
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2,886✔
5688
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
2,886✔
5689

5690
  size_t     keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
2,886✔
5691
  SExprInfo* pExprInfo = NULL;
2,886✔
5692
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
2,886✔
5693
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5694
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str, pInfo->pState,
2,886✔
5695
                    &pTaskInfo->storageAPI.functionStore);
5696
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5697

5698
  if (pIntervalPhyNode->window.pExprs != NULL) {
2,886✔
5699
    int32_t    numOfScalar = 0;
1✔
5700
    SExprInfo* pScalarExprInfo = NULL;
1✔
5701

5702
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5703
    QUERY_CHECK_CODE(code, lino, _error);
1!
5704

5705
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
5706
    QUERY_CHECK_CODE(code, lino, _error);
1!
5707
  }
5708

5709
  pInfo->invertible = false;
2,886✔
5710
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
2,886✔
5711
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
2,886!
5712
  pInfo->delIndex = 0;
2,886✔
5713

5714
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
2,886✔
5715
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5716

5717
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2,886✔
5718

5719
  pInfo->pPhyNode = NULL;  // create new child
2,886✔
5720
  pInfo->pPullDataMap = NULL;
2,886✔
5721
  pInfo->pFinalPullDataMap = NULL;
2,886✔
5722
  pInfo->pPullWins = NULL;  // SPullWindowInfo
2,886✔
5723
  pInfo->pullIndex = 0;
2,886✔
5724
  pInfo->pPullDataRes = NULL;
2,886✔
5725
  pInfo->numOfChild = 0;
2,886✔
5726
  pInfo->delKey.ts = INT64_MAX;
2,886✔
5727
  pInfo->delKey.groupId = 0;
2,886✔
5728
  pInfo->numOfDatapack = 0;
2,886✔
5729
  pInfo->pUpdated = NULL;
2,886✔
5730
  pInfo->pUpdatedMap = NULL;
2,886✔
5731
  int32_t funResSize = getMaxFunResSize(pSup, numOfCols);
2,886✔
5732

5733
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
2,886✔
5734
  pInfo->pState->pFileState = NULL;
2,886✔
5735

5736
  // used for backward compatibility of function's result info
5737
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
2,886✔
5738
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
2,886✔
5739
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
2,886✔
5740

5741
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
2,886✔
5742
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
2,886✔
5743
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
2,886✔
5744
      &pInfo->pState->pFileState);
2,886✔
5745
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5746

5747
  pInfo->pOperator = pOperator;
2,886✔
5748
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
2,886✔
5749
                  pInfo, pTaskInfo);
5750
  pOperator->fpSet =
5751
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
2,886✔
5752
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5753
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
2,886✔
5754

5755
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
2,886✔
5756
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5757

5758
  pInfo->recvGetAll = false;
2,886✔
5759

5760
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
2,886✔
5761
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5762

5763
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,886✔
5764
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
2,886✔
5765
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
2,886!
5766
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
2,886✔
5767

5768
  // for stream
5769
  void*   buff = NULL;
2,886✔
5770
  int32_t len = 0;
2,886✔
5771
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
2,886✔
5772
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
5773
  if (res == TSDB_CODE_SUCCESS) {
2,886✔
5774
    doStreamIntervalDecodeOpState(buff, len, pOperator);
3✔
5775
    taosMemoryFree(buff);
3!
5776
  }
5777

5778
  pInfo->basic.primaryPkIndex = -1;
2,886✔
5779
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
2,886✔
5780
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5781

5782
  code = appendDownstream(pOperator, &downstream, 1);
2,886✔
5783
  QUERY_CHECK_CODE(code, lino, _error);
2,886!
5784

5785
  *pOptrInfo = pOperator;
2,886✔
5786
  return TSDB_CODE_SUCCESS;
2,886✔
5787

5788
_error:
×
5789
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
5790
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5791
  pTaskInfo->code = code;
×
5792
  return code;
×
5793
}
5794

5795
int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
2,956✔
5796
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5797
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
2,956✔
5798
  if (pIntervalPhyNode->window.triggerType == STREAM_TRIGGER_FORCE_WINDOW_CLOSE) {
2,956✔
5799
    return createStreamIntervalSliceOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
70✔
5800
  } else {
5801
    return createStreamSingleIntervalOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
2,886✔
5802
  }
5803
  return TSDB_CODE_SUCCESS;
5804
}
5805

5806
static void doStreamMidIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pUpdatedMap) {
38✔
5807
  int32_t                      code = TSDB_CODE_SUCCESS;
38✔
5808
  int32_t                      lino = 0;
38✔
5809
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
38✔
5810
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
38✔
5811

5812
  SResultRowInfo*  pResultRowInfo = &(pInfo->binfo.resultRowInfo);
38✔
5813
  SExecTaskInfo*   pTaskInfo = pOperator->pTaskInfo;
38✔
5814
  SExprSupp*       pSup = &pOperator->exprSupp;
38✔
5815
  int32_t          numOfOutput = pSup->numOfExprs;
38✔
5816
  int32_t          step = 1;
38✔
5817
  SRowBuffPos*     pResPos = NULL;
38✔
5818
  SResultRow*      pResult = NULL;
38✔
5819
  int32_t          forwardRows = 1;
38✔
5820
  uint64_t         groupId = pSDataBlock->info.id.groupId;
38✔
5821
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
38✔
5822
  TSKEY*           tsCol = (int64_t*)pColDataInfo->pData;
38✔
5823

5824
  int32_t     startPos = 0;
38✔
5825
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
38✔
5826
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
38✔
5827

5828
  while (1) {
1,266✔
5829
    SWinKey key = {
1,304✔
5830
        .ts = nextWin.skey,
1,304✔
5831
        .groupId = groupId,
5832
    };
5833
    void*   chIds = taosHashGet(pInfo->pPullDataMap, &key, sizeof(SWinKey));
1,304✔
5834
    int32_t index = -1;
1,304✔
5835
    SArray* chArray = NULL;
1,304✔
5836
    int32_t chId = 0;
1,304✔
5837
    if (chIds) {
1,304✔
5838
      chArray = *(void**)chIds;
4✔
5839
      chId = getChildIndex(pSDataBlock);
4✔
5840
      index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
4✔
5841
    }
5842
    if (!(index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA)) {
1,304!
5843
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, startPos);
×
5844
      if (startPos < 0) {
×
5845
        break;
38✔
5846
      }
5847
      continue;
×
5848
    }
5849

5850
    if (!inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,304!
5851
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCol, startPos, nextWin.ekey, &nextWin);
×
5852
      if (startPos < 0) {
×
5853
        break;
×
5854
      }
5855
      continue;
×
5856
    }
5857

5858
    int32_t winCode = TSDB_CODE_SUCCESS;
1,304✔
5859
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
1,304✔
5860
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
5861
    QUERY_CHECK_CODE(code, lino, _end);
1,304!
5862

5863
    pResult = (SResultRow*)pResPos->pRowBuff;
1,304✔
5864

5865
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,304!
5866
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,304✔
5867
      QUERY_CHECK_CODE(code, lino, _end);
1,304!
5868
    }
5869

5870
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,304!
5871
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
×
5872
      QUERY_CHECK_CODE(code, lino, _end);
×
5873
    }
5874

5875
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
1,304✔
5876
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
1,304✔
5877
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
1,304✔
5878
    QUERY_CHECK_CODE(code, lino, _end);
1,304!
5879
    key.ts = nextWin.skey;
1,304✔
5880

5881
    if (pInfo->delKey.ts > key.ts) {
1,304✔
5882
      pInfo->delKey = key;
10✔
5883
    }
5884
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
1,304✔
5885
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
1,304!
5886
      qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64
×
5887
             ",maxKey %" PRId64,
5888
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5889
      code = blockDataUpdateTsWindow(pSDataBlock, 0);
×
5890
      QUERY_CHECK_CODE(code, lino, _end);
×
5891

5892
      // timestamp of the data is incorrect
5893
      if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
5894
        qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
5895
               pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5896
      }
5897
    }
5898
    startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, prevEndPos);
1,304✔
5899
    if (startPos < 0) {
1,304✔
5900
      break;
38✔
5901
    }
5902
  }
5903

5904
_end:
38✔
5905
  if (code != TSDB_CODE_SUCCESS) {
38!
5906
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5907
  }
5908
}
38✔
5909

5910
static int32_t addMidRetriveWindow(SArray* wins, SHashObj* pMidPullMap, int32_t numOfChild) {
12✔
5911
  int32_t code = TSDB_CODE_SUCCESS;
12✔
5912
  int32_t lino = 0;
12✔
5913
  int32_t size = taosArrayGetSize(wins);
12✔
5914
  for (int32_t i = 0; i < size; i++) {
18✔
5915
    SWinKey* winKey = taosArrayGet(wins, i);
6✔
5916
    void*    chIds = taosHashGet(pMidPullMap, winKey, sizeof(SWinKey));
6✔
5917
    if (!chIds) {
6!
5918
      code = addPullWindow(pMidPullMap, winKey, numOfChild);
6✔
5919
      qDebug("===stream===prepare mid operator retrive for delete %" PRId64 ", size:%d", winKey->ts, numOfChild);
6!
5920
      QUERY_CHECK_CODE(code, lino, _end);
6!
5921
    }
5922
  }
5923
_end:
12✔
5924
  if (code != TSDB_CODE_SUCCESS) {
12!
5925
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5926
  }
5927
  return code;
12✔
5928
}
5929

5930
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
106✔
5931
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
106✔
5932
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
106✔
5933
  uint16_t                     opType = pOperator->operatorType;
106✔
5934

5935
  if (pInfo->recvPullover) {
106✔
5936
    pInfo->recvPullover = false;
6✔
5937
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5938
    return pInfo->pMidPulloverRes;
6✔
5939
  }
5940

5941
  qDebug("===stream=== build mid interval result");
100!
5942
  doBuildDeleteResult(pInfo, pInfo->pMidPullDatas, &pInfo->midDelIndex, pInfo->pDelRes);
100✔
5943
  if (pInfo->pDelRes->info.rows != 0) {
100!
5944
    // process the rest of the data
5945
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
×
5946
    return pInfo->pDelRes;
×
5947
  }
5948

5949
  if (pInfo->recvRetrive) {
100✔
5950
    pInfo->recvRetrive = false;
12✔
5951
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5952
    return pInfo->pMidRetriveRes;
12✔
5953
  }
5954

5955
  return NULL;
88✔
5956
}
5957

5958
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
104✔
5959
  int32_t                      code = TSDB_CODE_SUCCESS;
104✔
5960
  int32_t                      lino = 0;
104✔
5961
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
104✔
5962
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
104✔
5963
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
104✔
5964
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
104✔
5965
  SExprSupp*                   pSup = &pOperator->exprSupp;
104✔
5966

5967
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
104!
5968

5969
  if (pOperator->status == OP_EXEC_DONE) {
104!
5970
    (*ppRes) = NULL;
×
5971
    return code;
×
5972
  } else if (pOperator->status == OP_RES_TO_RETURN) {
104✔
5973
    SSDataBlock* resBlock = NULL;
35✔
5974
    code = buildIntervalResult(pOperator, &resBlock);
35✔
5975
    QUERY_CHECK_CODE(code, lino, _end);
35!
5976
    if (resBlock != NULL) {
35✔
5977
      (*ppRes) = resBlock;
10✔
5978
      return code;
35✔
5979
    }
5980

5981
    setOperatorCompleted(pOperator);
25✔
5982
    clearFunctionContext(&pOperator->exprSupp);
25✔
5983
    clearStreamIntervalOperator(pInfo);
25✔
5984
    qDebug("stask:%s  ===stream===%s clear", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType));
25!
5985
    (*ppRes) = NULL;
25✔
5986
    return code;
25✔
5987
  } else {
5988
    SSDataBlock* resBlock = NULL;
69✔
5989
    code = buildIntervalResult(pOperator, &resBlock);
69✔
5990
    QUERY_CHECK_CODE(code, lino, _end);
69!
5991
    if (resBlock != NULL) {
69!
5992
      (*ppRes) = resBlock;
×
5993
      return code;
2✔
5994
    }
5995

5996
    resBlock = buildMidIntervalResult(pOperator);
69✔
5997
    if (resBlock != NULL) {
69✔
5998
      (*ppRes) = resBlock;
2✔
5999
      return code;
2✔
6000
    }
6001

6002
    if (pInfo->clearState) {
67✔
6003
      pInfo->clearState = false;
18✔
6004
      clearFunctionContext(&pOperator->exprSupp);
18✔
6005
      clearStreamIntervalOperator(pInfo);
18✔
6006
    }
6007
  }
6008

6009
  if (!pInfo->pUpdated) {
67✔
6010
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
64✔
6011
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
64!
6012
  }
6013
  if (!pInfo->pUpdatedMap) {
67✔
6014
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
64✔
6015
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
64✔
6016
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
64!
6017
  }
6018

6019
  while (1) {
54✔
6020
    if (isTaskKilled(pTaskInfo)) {
121!
6021
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
6022
      (*ppRes) = NULL;
×
6023
      return code;
3✔
6024
    }
6025

6026
    SSDataBlock* pBlock = NULL;
121✔
6027
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
121✔
6028
    QUERY_CHECK_CODE(code, lino, _end);
121!
6029

6030
    if (pBlock == NULL) {
121✔
6031
      pOperator->status = OP_RES_TO_RETURN;
46✔
6032
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
46!
6033
             pInfo->numOfDatapack);
6034
      pInfo->numOfDatapack = 0;
46✔
6035
      break;
46✔
6036
    }
6037
    pInfo->numOfDatapack++;
75✔
6038
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
75✔
6039
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
75✔
6040

6041
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
75✔
6042
      pInfo->binfo.pRes->info.type = pBlock->info.type;
8✔
6043
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
67!
6044
               pBlock->info.type == STREAM_CLEAR) {
65✔
6045
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
3✔
6046
      if (!delWins) {
3!
6047
        code = terrno;
×
6048
        QUERY_CHECK_CODE(code, lino, _end);
×
6049
      }
6050
      code =
6051
          doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, pInfo->pFinalPullDataMap);
3✔
6052
      QUERY_CHECK_CODE(code, lino, _end);
3!
6053

6054
      removeResults(delWins, pInfo->pUpdatedMap);
3✔
6055
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
3✔
6056
      if (!tmp && taosArrayGetSize(delWins) > 0) {
3!
6057
        code = TSDB_CODE_OUT_OF_MEMORY;
×
6058
        QUERY_CHECK_CODE(code, lino, _end);
×
6059
      }
6060
      taosArrayDestroy(delWins);
3✔
6061

6062
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
3✔
6063
      if (pInfo->pDelRes->info.rows != 0) {
3!
6064
        // process the rest of the data
6065
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
3✔
6066
        if (pBlock->info.type == STREAM_CLEAR) {
3✔
6067
          pInfo->pDelRes->info.type = STREAM_CLEAR;
1✔
6068
        } else {
6069
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
2✔
6070
        }
6071
        (*ppRes) = pInfo->pDelRes;
3✔
6072
        return code;
3✔
6073
      }
6074
      continue;
16✔
6075
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
64!
6076
      (*ppRes) = pBlock;
×
6077
      return code;
×
6078
    } else if (pBlock->info.type == STREAM_PULL_OVER) {
64✔
6079
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
12✔
6080
                             pInfo->numOfChild, pOperator, &pInfo->recvPullover);
6081
      QUERY_CHECK_CODE(code, lino, _end);
12!
6082

6083
      if (pInfo->recvPullover) {
12✔
6084
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
6085
        QUERY_CHECK_CODE(code, lino, _end);
6!
6086

6087
        pInfo->clearState = true;
6✔
6088
        break;
6✔
6089
      }
6090
      continue;
6✔
6091
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
52✔
6092
      pAPI->stateStore.streamStateCommit(pInfo->pState);
10✔
6093
      doStreamIntervalSaveCheckpoint(pOperator);
10✔
6094
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
10✔
6095
      QUERY_CHECK_CODE(code, lino, _end);
10!
6096

6097
      continue;
10✔
6098
    } else if (pBlock->info.type == STREAM_MID_RETRIEVE) {
42✔
6099
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
12✔
6100
      if (!delWins) {
12!
6101
        code = terrno;
×
6102
        QUERY_CHECK_CODE(code, lino, _end);
×
6103
      }
6104
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, NULL);
12✔
6105
      QUERY_CHECK_CODE(code, lino, _end);
12!
6106

6107
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
6108
      QUERY_CHECK_CODE(code, lino, _end);
12!
6109

6110
      taosArrayDestroy(delWins);
12✔
6111
      pInfo->recvRetrive = true;
12✔
6112
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
12✔
6113
      QUERY_CHECK_CODE(code, lino, _end);
12!
6114

6115
      pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
12✔
6116
      pInfo->clearState = true;
12✔
6117
      break;
12✔
6118
    } else {
6119
      if (pBlock->info.type != STREAM_INVALID) {
30!
6120
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
6121
        QUERY_CHECK_CODE(code, lino, _end);
×
6122
      }
6123
    }
6124

6125
    if (pInfo->scalarSupp.pExprInfo != NULL) {
38!
6126
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
6127
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
6128
      QUERY_CHECK_CODE(code, lino, _end);
×
6129
    }
6130
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
38✔
6131
    QUERY_CHECK_CODE(code, lino, _end);
38!
6132
    doStreamMidIntervalAggImpl(pOperator, pBlock, pInfo->pUpdatedMap);
38✔
6133
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
38✔
6134
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
38✔
6135
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
38✔
6136
  }
6137

6138
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
64✔
6139
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
64✔
6140

6141
  void*   pIte = NULL;
64✔
6142
  int32_t iter = 0;
64✔
6143
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,363✔
6144
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,299✔
6145
    if (!tmp) {
1,299!
6146
      code = terrno;
×
6147
      QUERY_CHECK_CODE(code, lino, _end);
×
6148
    }
6149
  }
6150

6151
  tSimpleHashCleanup(pInfo->pUpdatedMap);
64✔
6152
  pInfo->pUpdatedMap = NULL;
64✔
6153
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
64✔
6154

6155
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
64✔
6156
  pInfo->pUpdated = NULL;
64✔
6157
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
64✔
6158
  QUERY_CHECK_CODE(code, lino, _end);
64!
6159

6160
  SSDataBlock* resBlock = NULL;
64✔
6161
  code = buildIntervalResult(pOperator, &resBlock);
64✔
6162
  QUERY_CHECK_CODE(code, lino, _end);
64!
6163
  if (resBlock != NULL) {
64✔
6164
    (*ppRes) = resBlock;
27✔
6165
    return code;
27✔
6166
  }
6167

6168
  resBlock = buildMidIntervalResult(pOperator);
37✔
6169
  if (resBlock != NULL) {
37✔
6170
    (*ppRes) = resBlock;
16✔
6171
    return code;
16✔
6172
  }
6173

6174
  if (pInfo->clearState) {
21!
6175
    pInfo->clearState = false;
×
6176
    clearFunctionContext(&pOperator->exprSupp);
×
6177
    clearStreamIntervalOperator(pInfo);
×
6178
  }
6179

6180
_end:
21✔
6181
  if (code != TSDB_CODE_SUCCESS) {
21!
6182
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
6183
    pTaskInfo->code = code;
×
6184
    T_LONG_JMP(pTaskInfo->env, code);
×
6185
  }
6186
  (*ppRes) = NULL;
21✔
6187
  return code;
21✔
6188
}
6189

6190
static SSDataBlock* doStreamMidIntervalAgg(SOperatorInfo* pOperator) {
×
6191
  SSDataBlock* pRes = NULL;
×
6192
  int32_t      code = doStreamMidIntervalAggNext(pOperator, &pRes);
×
6193
  return pRes;
×
6194
}
6195

6196
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
20,181✔
6197
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
20,181✔
6198
         getStreamOpName(pOperator->operatorType), pOperator->status);
6199
  setOperatorCompleted(pOperator);
20,181✔
6200
}
20,183✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc