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

taosdata / TDengine / #3630

06 Mar 2025 11:35AM UTC coverage: 63.629% (-0.06%) from 63.692%
#3630

push

travis-ci

web-flow
Merge pull request #30042 from taosdata/doc/internal

docs: format

149060 of 300532 branches covered (49.6%)

Branch coverage included in aggregate %.

233739 of 301077 relevant lines covered (77.63%)

17473135.72 hits per line

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

71.06
/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,134✔
62
  int firstPos = 0, lastPos = num - 1, midPos = -1;
1,134✔
63
  int numOfRows = 0;
1,134✔
64

65
  if (num <= 0) return -1;
1,134✔
66
  if (order == TSDB_ORDER_DESC) {
952!
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;
985✔
70
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
173✔
71
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
101✔
72

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

76
      if (comparefn(pKey, keyList, midPos) < 0) {
63✔
77
        lastPos = midPos - 1;
20✔
78
      } else if (comparefn(pKey, keyList, midPos) > 0) {
43✔
79
        firstPos = midPos + 1;
13✔
80
      } else {
81
        break;
30✔
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;
30✔
113
}
114

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

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

133
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
208✔
134
  int32_t size = taosArrayGetSize(pPullWins);
208✔
135
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
208✔
136
  if (index == -1) {
208✔
137
    index = 0;
161✔
138
  } else {
139
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
47✔
140
    if (code == 0) {
47✔
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) {
44!
148
      index++;
44✔
149
    }
150
  }
151
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
205!
152
    return terrno;
×
153
  }
154
  return TSDB_CODE_SUCCESS;
205✔
155
}
156

157
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
10,412✔
158
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
10,412!
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;
10,413✔
163
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
10,413✔
164
}
165

166
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
9,802,553✔
167
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
9,802,553!
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);
9,802,444✔
172
}
173

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

179
static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) {
192✔
180
  int32_t size = taosArrayGetSize(pWins);
192✔
181
  for (int32_t i = 0; i < size; i++) {
426✔
182
    SWinKey* pW = taosArrayGet(pWins, i);
234✔
183
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
234✔
184
    if (tmp) {
234!
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
}
192✔
192

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

198
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
26,933✔
199
  taosArraySort(pDelWins, winKeyCmprImpl);
26,933✔
200
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
26,931✔
201
  int32_t delSize = taosArrayGetSize(pDelWins);
26,930✔
202
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
26,930✔
203
    return;
26,502✔
204
  }
205
  void*   pIte = NULL;
429✔
206
  int32_t iter = 0;
429✔
207
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,110✔
208
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
681✔
209
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
681✔
210
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
681✔
211
      taosArrayRemove(pDelWins, index);
546✔
212
      delSize = taosArrayGetSize(pDelWins);
546✔
213
    }
214
  }
215
}
216

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

221
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
40,561,757✔
222

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

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

233
static int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,401✔
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,
1,849✔
259
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
260
  int32_t                      code = TSDB_CODE_SUCCESS;
1,849✔
261
  int32_t                      lino = 0;
1,849✔
262
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,849✔
263
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1,849✔
264
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,849✔
265
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
1,850✔
266
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,850✔
267
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
1,850✔
268
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
1,850✔
269
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
1,850✔
270
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
1,850✔
271
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
1,850✔
272
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,850✔
273
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
1,850✔
274
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
4,015✔
275
    SResultRowInfo dumyInfo = {0};
2,165✔
276
    dumyInfo.cur.pageId = -1;
2,165✔
277

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

476
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
6,421✔
477
  int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
6,421✔
478
  for (int32_t i = pGroupResInfo->index; i < size; i++) {
1,020,113✔
479
    void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
1,013,692✔
480
    destroyFlusedPos(pPos);
1,013,692✔
481
  }
482
  pGroupResInfo->freeItem = false;
6,421✔
483
  taosArrayDestroy(pGroupResInfo->pRows);
6,421✔
484
  pGroupResInfo->pRows = NULL;
6,422✔
485
  pGroupResInfo->index = 0;
6,422✔
486
  pGroupResInfo->delIndex = 0;
6,422✔
487
}
6,422✔
488

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

501
  destroyStreamBasicInfo(&pInfo->basic);
3,965✔
502
  cleanupAggSup(&pInfo->aggSup);
3,965✔
503
  clearGroupResInfo(&pInfo->groupResInfo);
3,964✔
504
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
3,965✔
505
  pInfo->pUpdated = NULL;
3,965✔
506

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

527
  if (pInfo->stateStore.streamFileStateDestroy != NULL) {
3,965!
528
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
3,965✔
529
  }
530
  taosArrayDestroy(pInfo->pMidPullDatas);
3,965✔
531

532
  if (pInfo->pState != NULL && pInfo->pState->dump == 1) {
3,965!
533
    taosMemoryFreeClear(pInfo->pState->pTdbState->pOwner);
992!
534
    taosMemoryFreeClear(pInfo->pState->pTdbState);
992!
535
  }
536
  taosMemoryFreeClear(pInfo->pState);
3,965!
537

538
  nodesDestroyNode((SNode*)pInfo->pPhyNode);
3,965✔
539
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
3,965✔
540
  cleanupExprSupp(&pInfo->scalarSupp);
3,964✔
541
  tSimpleHashCleanup(pInfo->pDeletedMap);
3,964✔
542

543
  blockDataDestroy(pInfo->pCheckpointRes);
3,965✔
544

545
  taosMemoryFreeClear(param);
3,965!
546
}
547

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

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

562
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
1,355✔
563
    reloadFromDownStream(downstream->pDownstream[0], pInfo);
64✔
564
    return;
64✔
565
  }
566

567
  SStreamScanInfo* pScanInfo = downstream->info;
1,291✔
568
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
1,291✔
569
}
570

571
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
10,951,562✔
572

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

580
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
3,964✔
581
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
252✔
582
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
252✔
583
  }
584

585
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
3,964✔
586
    return initIntervalDownStream(downstream->pDownstream[0], type, pInfo, pBasic);
252✔
587
  }
588

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

598
  pScanInfo->interval = pInfo->interval;
3,713✔
599
  pScanInfo->twAggSup = pInfo->twAggSup;
3,713✔
600
  pScanInfo->pState = pInfo->pState;
3,713✔
601
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
3,713✔
602
  if (!hasSrcPrimaryKeyCol(pBasic)) {
3,713✔
603
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
3,710✔
604
  }
605

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

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

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

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

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

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

655
bool hasIntervalWindow(void* pState, SWinKey* pKey, SStateStore* pStore) {
25✔
656
  return pStore->streamStateCheck(pState, pKey);
25✔
657
}
658

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

668
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
9,807,319✔
669
  QUERY_CHECK_CODE(code, lino, _end);
9,807,798!
670

671
  *pResult = (SRowBuffPos*)value;
9,807,798✔
672
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
9,807,798✔
673

674
  // set time window for current result
675
  res->win = (*win);
9,807,798✔
676
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
9,807,798✔
677
  QUERY_CHECK_CODE(code, lino, _end);
9,807,308!
678

679
_end:
9,807,308✔
680
  if (code != TSDB_CODE_SUCCESS) {
9,807,308!
681
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
682
  }
683
  return code;
9,807,295✔
684
}
685

686
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
30,903,928✔
687
                           SStateStore* pStore) {
688
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
30,903,928✔
689
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
25✔
690
    if (!hasIntervalWindow(pState, &key, pStore)) {
25✔
691
      return true;
15✔
692
    }
693
    return false;
10✔
694
  }
695
  return false;
30,903,903✔
696
}
697

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

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

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

735
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
3,973✔
736
  if (pBlock->info.rows <= 0) {
3,973✔
737
    return;
3,830✔
738
  }
739
  blockDataCleanup(pBlock);
143✔
740
}
741

742
static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
3,973✔
743
  int32_t code = TSDB_CODE_SUCCESS;
3,973✔
744
  int32_t lino = 0;
3,973✔
745
  clearSpecialDataBlock(pBlock);
3,973✔
746
  int32_t size = taosArrayGetSize(array);
3,973✔
747
  if (size - (*pIndex) == 0) {
3,973✔
748
    goto _end;
3,830✔
749
  }
750
  code = blockDataEnsureCapacity(pBlock, size - (*pIndex));
143✔
751
  QUERY_CHECK_CODE(code, lino, _end);
143!
752

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

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

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

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

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

780
    colDataSetNULL(pTbName, pBlock->info.rows);
205!
781
    if (pPrimaryKey != NULL) {
205!
782
      colDataSetNULL(pPrimaryKey, pBlock->info.rows);
×
783
    }
784

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

794
_end:
143✔
795
  if (code != TSDB_CODE_SUCCESS) {
3,973!
796
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
797
  }
798
}
3,973✔
799

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

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

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

860
                code = addPullWindow(pMap, &winRes, numOfCh);
28✔
861
                QUERY_CHECK_CODE(code, lino, _end);
28!
862

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

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

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

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

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

928
static void clearFunctionContext(SExprSupp* pSup) {
2,263✔
929
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
24,691✔
930
    pSup->pCtx[i].saveHandle.currentPage = -1;
22,428✔
931
  }
932
}
2,263✔
933

934
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
8,417,053✔
935
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
8,417,053✔
936
}
937

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

949
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
108,028✔
950

951
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
8,433,967✔
952
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
8,417,053✔
953
    SResultRow*  pRow = NULL;
8,417,053✔
954
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
8,417,053✔
955
    QUERY_CHECK_CODE(code, lino, _end);
8,417,056!
956
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
8,417,056✔
957
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
8,417,056✔
958
    // no results, continue to check the next one
959
    if (pRow->numOfRows == 0) {
8,417,039!
960
      pGroupResInfo->index += 1;
×
961
      continue;
×
962
    }
963
    if (pBlock->info.id.groupId == 0) {
8,417,039✔
964
      pBlock->info.id.groupId = groupId;
558,697✔
965
      void*   tbname = NULL;
558,697✔
966
      int32_t winCode = TSDB_CODE_SUCCESS;
558,697✔
967
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
558,697✔
968
                                                    false, &winCode);
969
      QUERY_CHECK_CODE(code, lino, _end);
558,703!
970
      if (winCode != TSDB_CODE_SUCCESS) {
558,703✔
971
        pBlock->info.parTbName[0] = 0;
552,768✔
972
      } else {
973
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
5,935✔
974
      }
975
      pAPI->stateStore.streamStateFreeVal(tbname);
558,703✔
976
    } else {
977
      // current value belongs to different group, it can't be packed into one datablock
978
      if (pBlock->info.id.groupId != groupId) {
7,858,342✔
979
        break;
91,110✔
980
      }
981
    }
982

983
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
8,327,130✔
984
      break;
1,194✔
985
    }
986
    pGroupResInfo->index += 1;
8,325,936✔
987

988
    for (int32_t j = 0; j < numOfExprs; ++j) {
67,814,960✔
989
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
59,489,021✔
990

991
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
59,489,021✔
992

993
      if (pCtx[j].fpSet.finalize) {
59,489,024✔
994
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
39,509,157✔
995
        if (TAOS_FAILED(tmpRes)) {
39,509,158!
996
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
997
          QUERY_CHECK_CODE(code, lino, _end);
×
998
        }
999
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
19,979,867✔
1000
        // do nothing, todo refactor
1001
      } else {
1002
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
1003
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
1004
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
19,933,450✔
1005
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
19,933,450✔
1006
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
39,866,902✔
1007
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
19,933,449✔
1008
          QUERY_CHECK_CODE(code, lino, _end);
19,933,452!
1009
        }
1010
      }
1011
    }
1012

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

1021
    pBlock->info.rows += pRow->numOfRows;
8,325,939✔
1022
  }
1023

1024
  pBlock->info.dataLoad = 1;
108,024✔
1025
  code = blockDataUpdateTsWindow(pBlock, 0);
108,024✔
1026
  QUERY_CHECK_CODE(code, lino, _end);
108,026!
1027

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

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

1040
  blockDataCleanup(pBlock);
145,305✔
1041
  taosArrayClear(pSessionKeys);
145,301✔
1042
  if (!hasRemainResults(pGroupResInfo)) {
145,302✔
1043
    return;
37,277✔
1044
  }
1045

1046
  // clear the existed group id
1047
  pBlock->info.id.groupId = 0;
108,028✔
1048
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
108,028✔
1049
}
1050

1051
static int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
232,745✔
1052
                                           TSKEY* primaryKeys, int32_t prevPosition) {
1053
  int32_t startPos = prevPosition + 1;
232,745✔
1054
  if (startPos == pDataBlockInfo->rows) {
232,745✔
1055
    startPos = -1;
2,513✔
1056
  } else {
1057
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
230,232✔
1058
  }
1059
  return startPos;
232,745✔
1060
}
1061

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

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

1080
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,130,702✔
1081
  tsCols = (int64_t*)pColDataInfo->pData;
1,130,704✔
1082

1083
  void*            pPkVal = NULL;
1,130,704✔
1084
  int32_t          pkLen = 0;
1,130,704✔
1085
  SColumnInfoData* pPkColDataInfo = NULL;
1,130,704✔
1086
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
1,130,704✔
1087
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
367,296✔
1088
  }
1089

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

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

1103
  int32_t     startPos = 0;
1,130,704✔
1104
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
1,130,704✔
1105
  STimeWindow nextWin = {0};
1,130,703✔
1106
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,130,703✔
1107
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,475✔
1108
  } else {
1109
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
1,128,228✔
1110
  }
1111
  while (1) {
8,675,658✔
1112
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
9,806,355✔
1113
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
9,806,212!
1114
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1115
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1116
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1117
    }
1118

1119
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
9,807,342✔
1120
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
1,144✔
1121
                          nextWin.ekey, pPkVal, pkLen)) ||
9,806,089✔
1122
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
9,806,172✔
1123
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
38✔
1124
      if (startPos < 0) {
45✔
1125
        break;
1,130,701✔
1126
      }
1127
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
19!
1128
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1129
      continue;
56✔
1130
    }
1131

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

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

1167
      if (ignore) {
231,441✔
1168
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
131✔
1169
        if (startPos < 0) {
131✔
1170
          break;
94✔
1171
        }
1172
        continue;
37✔
1173
      }
1174
    }
1175

1176
    int32_t winCode = TSDB_CODE_SUCCESS;
9,805,946✔
1177
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
9,805,946✔
1178
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1179
    QUERY_CHECK_CODE(code, lino, _end);
9,805,991!
1180

1181
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator) &&
9,805,991✔
1182
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
8,911,694!
1183
      SSessionKey key = {.win = nextWin, .groupId = groupId};
×
1184
      code = addIntervalAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &key, &pInfo->basic.notifyEventSup,
×
1185
                                       pTaskInfo->streamInfo.pNotifyEventStat);
1186
      QUERY_CHECK_CODE(code, lino, _end);
×
1187
    }
1188

1189
    pResult = (SResultRow*)pResPos->pRowBuff;
9,805,991✔
1190

1191
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,805,991✔
1192
      forwardRows = 1;
231,310✔
1193
    } else {
1194
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
9,574,681✔
1195
                                             NULL, TSDB_ORDER_ASC);
1196
    }
1197

1198
    SWinKey key = {
9,807,354✔
1199
        .ts = pResult->win.skey,
9,807,354✔
1200
        .groupId = groupId,
1201
    };
1202

1203
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
9,807,354!
1204
      code = tSimpleHashPut(pDeletedMap, &key, sizeof(SWinKey), NULL, 0);
6✔
1205
      QUERY_CHECK_CODE(code, lino, _end);
6!
1206
    }
1207

1208
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
9,807,354!
1209
      code = saveWinResult(&key, pResPos, pUpdatedMap);
9,798,655✔
1210
      QUERY_CHECK_CODE(code, lino, _end);
9,797,877!
1211
    }
1212

1213
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
9,806,576✔
1214
      pResPos->beUpdated = true;
8,464✔
1215
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
8,464✔
1216
      QUERY_CHECK_CODE(code, lino, _end);
8,463!
1217
    }
1218

1219
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
9,806,575✔
1220
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
9,805,844✔
1221
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
9,805,844✔
1222
    QUERY_CHECK_CODE(code, lino, _end);
9,807,348!
1223
    key.ts = nextWin.skey;
9,807,348✔
1224

1225
    if (pInfo->delKey.ts > key.ts) {
9,807,348✔
1226
      pInfo->delKey = key;
1,977✔
1227
    }
1228
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
9,807,348✔
1229
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,807,348✔
1230
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
231,310✔
1231
    } else {
1232
      startPos =
1233
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
9,576,038✔
1234
    }
1235
    if (startPos < 0) {
9,806,183✔
1236
      break;
1,130,581✔
1237
    }
1238
  }
1239
_end:
1,130,701✔
1240
  if (code != TSDB_CODE_SUCCESS) {
1,130,701!
1241
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1242
  }
1243
  return code;
1,130,700✔
1244
}
1245

1246
int winPosCmprImpl(const void* pKey1, const void* pKey2) {
132,025,136✔
1247
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
132,025,136✔
1248
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
132,025,136✔
1249
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
132,025,136✔
1250
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
132,025,136✔
1251

1252
  if (pWin1->groupId > pWin2->groupId) {
132,025,136✔
1253
    return 1;
23,107,915✔
1254
  } else if (pWin1->groupId < pWin2->groupId) {
108,917,221✔
1255
    return -1;
21,754,140✔
1256
  }
1257

1258
  if (pWin1->ts > pWin2->ts) {
87,163,081✔
1259
    return 1;
43,894,971✔
1260
  } else if (pWin1->ts < pWin2->ts) {
43,268,110!
1261
    return -1;
43,268,110✔
1262
  }
1263

1264
  return 0;
×
1265
}
1266

1267
static void resetUnCloseWinInfo(SSHashObj* winMap) {
259✔
1268
  void*   pIte = NULL;
259✔
1269
  int32_t iter = 0;
259✔
1270
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
579✔
1271
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
320✔
1272
    pPos->beUsed = true;
320✔
1273
  }
1274
}
259✔
1275

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

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

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

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

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

1309
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
10✔
1310
  buf = taosDecodeFixedI64(buf, &pWin->skey);
10!
1311
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
10!
1312
  return buf;
10✔
1313
}
1314

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

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

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

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

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

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

1370
  void* pData = (buf == NULL) ? NULL : *buf;
82✔
1371

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

1384
  // 2.twAggSup
1385
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
82✔
1386

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

1404
  // 4.pPullWins
1405
  tlen += encodeSPullWindowInfoArray(buf, pInfo->pPullWins);
82✔
1406

1407
  // 5.dataVersion
1408
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
82✔
1409

1410
  // 6.basicInfo
1411
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
82✔
1412

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

1421
  return tlen;
82✔
1422
}
1423

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

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

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

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

1461
  // 2.twAggSup
1462
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
27✔
1463

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

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

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

1495
  // 5.dataVersion
1496
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
27!
1497

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

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

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

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

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

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

1560
  // check if query task is closed or not
1561
  if (isTaskKilled(pTaskInfo)) {
144,075✔
1562
    (*ppRes) = NULL;
2✔
1563
    return code;
2✔
1564
  }
1565

1566
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
275,330✔
1567
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
131,259!
1568
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
144,071✔
1569
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
3,973✔
1570
    if (pInfo->pPullDataRes->info.rows != 0) {
3,973✔
1571
      // process the rest of the data
1572
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
143✔
1573
      (*ppRes) = pInfo->pPullDataRes;
143✔
1574
      return code;
143✔
1575
    }
1576
  }
1577

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

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

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

1611
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
35,658✔
1612
  QUERY_CHECK_CODE(code, lino, _end);
35,655!
1613

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

1622
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
18,375✔
1623
  int32_t code = TSDB_CODE_SUCCESS;
18,375✔
1624
  int32_t lino = 0;
18,375✔
1625
  void*   pIte = NULL;
18,375✔
1626
  int32_t iter = 0;
18,375✔
1627
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
487,563✔
1628
    void* tmp = taosArrayPush(pUpdated, pIte);
469,188✔
1629
    if (!tmp) {
469,188!
1630
      code = terrno;
×
1631
      QUERY_CHECK_CODE(code, lino, _end);
×
1632
    }
1633
  }
1634
  taosArraySort(pUpdated, compar);
18,382✔
1635
  tSimpleHashCleanup(*ppWinUpdated);
18,377✔
1636
  *ppWinUpdated = NULL;
18,383✔
1637

1638
_end:
18,383✔
1639
  if (code != TSDB_CODE_SUCCESS) {
18,383!
1640
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1641
  }
1642
  return code;
18,384✔
1643
}
1644

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

1652
  SOperatorInfo* downstream = pOperator->pDownstream[0];
13,759✔
1653
  SExprSupp*     pSup = &pOperator->exprSupp;
13,759✔
1654

1655
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
13,759✔
1656

1657
  if (pOperator->status == OP_EXEC_DONE) {
13,758!
1658
    (*ppRes) = NULL;
×
1659
    return code;
×
1660
  } else if (pOperator->status == OP_RES_TO_RETURN) {
13,758✔
1661
    SSDataBlock* resBlock = NULL;
4,794✔
1662
    code = buildIntervalResult(pOperator, &resBlock);
4,794✔
1663
    QUERY_CHECK_CODE(code, lino, _end);
4,790!
1664
    if (resBlock != NULL) {
4,790✔
1665
      (*ppRes) = resBlock;
1,762✔
1666
      return code;
4,790✔
1667
    }
1668

1669
    if (pInfo->recvGetAll) {
3,028✔
1670
      pInfo->recvGetAll = false;
82✔
1671
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
82✔
1672
    }
1673

1674
    if (pInfo->reCkBlock) {
3,028!
1675
      pInfo->reCkBlock = false;
×
1676
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1677
      (*ppRes) = pInfo->pCheckpointRes;
×
1678
      return code;
×
1679
    }
1680

1681
    setStreamOperatorCompleted(pOperator);
3,028✔
1682
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
3,028✔
1683
      clearFunctionContext(&pOperator->exprSupp);
1,681✔
1684
      // semi interval operator clear disk buffer
1685
      clearStreamIntervalOperator(pInfo);
1,681✔
1686
      qDebug("===stream===clear semi operator");
1,681✔
1687
    }
1688
    (*ppRes) = NULL;
3,028✔
1689
    return code;
3,028✔
1690
  } else {
1691
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
8,964✔
1692
      SSDataBlock* resBlock = NULL;
5,854✔
1693
      code = buildIntervalResult(pOperator, &resBlock);
5,854✔
1694
      QUERY_CHECK_CODE(code, lino, _end);
5,854!
1695
      if (resBlock != NULL) {
5,854!
1696
        (*ppRes) = resBlock;
×
1697
        return code;
×
1698
      }
1699

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

1709
  if (!pInfo->pUpdated) {
8,964✔
1710
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5,972✔
1711
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
5,972!
1712
  }
1713
  if (!pInfo->pUpdatedMap) {
8,964✔
1714
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5,972✔
1715
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5,973✔
1716
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
5,975!
1717
  }
1718

1719
  while (1) {
22,449✔
1720
    if (isTaskKilled(pTaskInfo)) {
31,416✔
1721
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
5!
1722
      (*ppRes) = NULL;
5✔
1723
      return code;
2,994✔
1724
    }
1725

1726
    SSDataBlock* pBlock = NULL;
31,409✔
1727
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
31,409✔
1728
    QUERY_CHECK_CODE(code, lino, _end);
31,405!
1729

1730
    if (pBlock == NULL) {
31,405✔
1731
      pOperator->status = OP_RES_TO_RETURN;
5,475✔
1732
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
5,475✔
1733
             pInfo->numOfDatapack);
1734
      pInfo->numOfDatapack = 0;
5,476✔
1735
      break;
5,476✔
1736
    }
1737

1738
    pInfo->numOfDatapack++;
25,930✔
1739
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
25,930✔
1740
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
25,930✔
1741

1742
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
25,932✔
1743
      pInfo->binfo.pRes->info.type = pBlock->info.type;
19,775✔
1744
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
6,157✔
1745
               pBlock->info.type == STREAM_CLEAR) {
5,949✔
1746
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
378✔
1747
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
378!
1748
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
378✔
1749
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
378✔
1750
      QUERY_CHECK_CODE(code, lino, _end);
378!
1751

1752
      if (IS_FINAL_INTERVAL_OP(pOperator)) {
378✔
1753
        int32_t chId = getChildIndex(pBlock);
189✔
1754
        code = addRetriveWindow(delWins, pInfo, chId);
189✔
1755
        QUERY_CHECK_CODE(code, lino, _end);
189!
1756

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

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

1788
      break;
×
1789
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
5,779!
1790
      pInfo->recvGetAll = true;
82✔
1791
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
82✔
1792
      QUERY_CHECK_CODE(code, lino, _end);
82!
1793
      continue;
82✔
1794
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
5,697✔
1795
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
491!
1796
        pInfo->recvRetrive = true;
491✔
1797
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
491✔
1798
        QUERY_CHECK_CODE(code, lino, _end);
491!
1799

1800
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
491✔
1801
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
491✔
1802
        QUERY_CHECK_CODE(code, lino, _end);
491!
1803
        break;
491✔
1804
      }
1805
      continue;
×
1806
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
5,206!
1807
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
485✔
1808
                             pInfo->numOfChild, pOperator, NULL);
1809
      QUERY_CHECK_CODE(code, lino, _end);
485!
1810
      continue;
485✔
1811
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
4,721✔
1812
      (*ppRes) = pBlock;
2,800✔
1813
      return code;
2,800✔
1814
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,921✔
1815
      pAPI->stateStore.streamStateCommit(pInfo->pState);
724✔
1816
      doStreamIntervalSaveCheckpoint(pOperator);
723✔
1817
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
722✔
1818
      QUERY_CHECK_CODE(code, lino, _end);
724!
1819

1820
      continue;
724✔
1821
    } else if (IS_FINAL_INTERVAL_OP(pOperator) && pBlock->info.type == STREAM_MID_RETRIEVE) {
1,197✔
1822
      continue;
491✔
1823
    } else {
1824
      if (pBlock->info.type != STREAM_INVALID) {
706!
1825
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1826
        QUERY_CHECK_CODE(code, lino, _end);
×
1827
      }
1828
    }
1829

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

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

1849
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
5,967✔
1850
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,707✔
1851
  }
1852
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
5,967✔
1853
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,709✔
1854
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1855
    QUERY_CHECK_CODE(code, lino, _end);
1,709!
1856

1857
    if (pInfo->destHasPrimaryKey) {
1,709✔
1858
      code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
2✔
1859
      QUERY_CHECK_CODE(code, lino, _end);
2!
1860
    }
1861
  }
1862
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
5,967✔
1863

1864
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
5,967✔
1865
  QUERY_CHECK_CODE(code, lino, _end);
5,969!
1866

1867
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
5,969✔
1868
  pInfo->pUpdated = NULL;
5,969✔
1869
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5,969✔
1870
  QUERY_CHECK_CODE(code, lino, _end);
5,969!
1871

1872
  SSDataBlock* resBlock = NULL;
5,969✔
1873
  code = buildIntervalResult(pOperator, &resBlock);
5,969✔
1874
  QUERY_CHECK_CODE(code, lino, _end);
5,969!
1875
  if (resBlock != NULL) {
5,969✔
1876
    (*ppRes) = resBlock;
3,028✔
1877
    return code;
3,028✔
1878
  }
1879

1880
  if (pInfo->recvRetrive) {
2,941✔
1881
    pInfo->recvRetrive = false;
491✔
1882
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
491✔
1883
    (*ppRes) = pInfo->pMidRetriveRes;
491✔
1884
    return code;
491✔
1885
  }
1886

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

1898
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
5,816✔
1899
  if (pWinPhyNode->deleteMark <= 0) {
5,816✔
1900
    return DEAULT_DELETE_MARK;
3,757✔
1901
  }
1902
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
2,059✔
1903
  deleteMark = TMAX(deleteMark, interval);
2,059✔
1904
  return deleteMark;
2,059✔
1905
}
1906

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

1915
TSKEY compareTs(void* pKey) {
30,170,264✔
1916
  SWinKey* pWinKey = (SWinKey*)pKey;
30,170,264✔
1917
  return pWinKey->ts;
30,170,264✔
1918
}
1919

1920
static int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
225,263✔
1921
  if (pCtx->subsidiaries.rowLen == 0) {
225,263!
1922
    int32_t rowLen = 0;
225,264✔
1923
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
225,665✔
1924
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
401✔
1925
      rowLen += pc->pExpr->base.resSchema.bytes;
401✔
1926
    }
1927

1928
    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
225,264✔
1929
  } else {
1930
    return pCtx->subsidiaries.rowLen;
×
1931
  }
1932
}
1933

1934
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
6,043✔
1935
  int32_t size = 0;
6,043✔
1936
  for (int32_t i = 0; i < numOfCols; ++i) {
231,310✔
1937
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
225,261✔
1938
    size = TMAX(size, resSize);
225,267✔
1939
  }
1940
  return size;
6,049✔
1941
}
1942

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

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

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

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

1990
int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
991✔
1991
                                              int32_t numOfChild, SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
1992
  QRY_PARAM_CHECK(pOptrInfo);
991!
1993

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

2004
  pOperator->exprSupp.hasWindowOrGroup = true;
992✔
2005
  pOperator->pTaskInfo = pTaskInfo;
992✔
2006
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
992✔
2007

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

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

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

2039
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
991✔
2040
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
992!
2041
  initBasicInfo(&pInfo->binfo, pResBlock);
992✔
2042

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

2049
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
992!
2050

2051
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
992✔
2052

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

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

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

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

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

2080
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
992✔
2081
  QUERY_CHECK_CODE(code, lino, _error);
992!
2082

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

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

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

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

2111
  pInfo->dataVersion = 0;
992✔
2112
  pInfo->recvGetAll = false;
992✔
2113
  pInfo->recvPullover = false;
992✔
2114
  pInfo->recvRetrive = false;
992✔
2115

2116
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
992✔
2117
  QUERY_CHECK_CODE(code, lino, _error);
991!
2118
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidRetriveRes);
991✔
2119
  QUERY_CHECK_CODE(code, lino, _error);
992!
2120
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidPulloverRes);
992✔
2121
  QUERY_CHECK_CODE(code, lino, _error);
992!
2122

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

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

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

2151
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
992✔
2152
  QUERY_CHECK_CODE(code, lino, _error);
992!
2153

2154
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL ||
992✔
2155
      pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
273✔
2156
    pInfo->basic.primaryPkIndex = -1;
741✔
2157
    code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
741✔
2158
    QUERY_CHECK_CODE(code, lino, _error);
741!
2159
  }
2160
  code = appendDownstream(pOperator, &downstream, 1);
992✔
2161
  QUERY_CHECK_CODE(code, lino, _error);
992!
2162

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

2173
  *pOptrInfo = pOperator;
992✔
2174
  return TSDB_CODE_SUCCESS;
992✔
2175

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

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

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

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

2213
  if (pInfo->pChildren != NULL) {
896✔
2214
    int32_t size = taosArrayGetSize(pInfo->pChildren);
38✔
2215
    for (int32_t i = 0; i < size; i++) {
163✔
2216
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
125✔
2217
      destroyOperator(pChild);
125✔
2218
    }
2219
    taosArrayDestroy(pInfo->pChildren);
38✔
2220
  }
2221

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

2229
  taosArrayDestroy(pInfo->historyWins);
896✔
2230
  blockDataDestroy(pInfo->pCheckpointRes);
896✔
2231
  tSimpleHashCleanup(pInfo->pPkDeleted);
896✔
2232

2233
  taosMemoryFreeClear(param);
896!
2234
}
2235

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

2244
  for (int32_t i = 0; i < numOfCols; ++i) {
28,542✔
2245
    pSup->pCtx[i].saveHandle.pBuf = NULL;
26,755✔
2246
  }
2247

2248
  return TSDB_CODE_SUCCESS;
1,787✔
2249
}
2250

2251
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
2,078✔
2252
  for (int i = 0; i < nums; i++) {
30,118✔
2253
    pDummy[i].functionId = pCtx[i].functionId;
28,040✔
2254
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
28,040✔
2255
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
28,040✔
2256
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
28,040✔
2257
  }
2258
}
2,078✔
2259

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

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

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

2297
static TSKEY sesionTs(void* pKey) {
5,344✔
2298
  SSessionKey* pWinKey = (SSessionKey*)pKey;
5,344✔
2299
  return pWinKey->win.skey;
5,344✔
2300
}
2301

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

2311
  pSup->gap = gap;
2,078✔
2312
  pSup->stateKeySize = keySize;
2,078✔
2313
  pSup->stateKeyType = keyType;
2,078✔
2314
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
2,078!
2315
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
2,077!
2316

2317
  pSup->stateStore = *pStore;
2,077✔
2318
  pSup->pSessionAPI = pApi;
2,077✔
2319

2320
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
2,077✔
2321
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
2,077!
2322
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
2,078!
2323

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

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

2347
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,078✔
2348
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
2,078✔
2349
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
2,078!
2350

2351
  for (int32_t i = 0; i < numOfOutput; ++i) {
30,128✔
2352
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
28,050✔
2353
  }
2354

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

2362
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5,585✔
2363
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5,585✔
2364
    return true;
4,130✔
2365
  }
2366
  return false;
1,455✔
2367
}
2368

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

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

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

2386
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
51,569✔
2387
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
51,569!
2388
    return true;
51,560✔
2389
  }
2390
  return false;
9✔
2391
}
2392

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

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

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

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

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

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

2440
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
32✔
2441
}
2442

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

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

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

2464
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
12,914✔
2465
  pAPI->streamStateReleaseBuf(pState, pPos, false);
12,914✔
2466
}
12,915✔
2467

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

2483
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
13,336✔
2484
  *pHashKey = *pKey;
13,336✔
2485
  pHashKey->win.ekey = pKey->win.skey;
13,336✔
2486
}
13,336✔
2487

2488
void removeSessionDeleteResults(SSHashObj* pHashMap, SArray* pWins) {
10,706✔
2489
  if (tSimpleHashGetSize(pHashMap) == 0) {
10,706✔
2490
    return;
9,693✔
2491
  }
2492
  int32_t size = taosArrayGetSize(pWins);
1,014✔
2493
  for (int32_t i = 0; i < size; i++) {
2,361✔
2494
    SResultWindowInfo* pWin = taosArrayGet(pWins, i);
1,347✔
2495
    if (!pWin) continue;
1,347!
2496
    SSessionKey key = {0};
1,347✔
2497
    getSessionHashKey(&pWin->sessionWin, &key);
1,347✔
2498
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
1,348✔
2499
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,348!
2500
  }
2501
}
2502

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

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

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

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

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

2574
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
12,332✔
2575
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
12,333✔
2576

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

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

2592
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
15,926✔
2593
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
15,926✔
2594
  if (pVal) {
15,926✔
2595
    SResultWindowInfo* pWin = pVal;
744✔
2596
    pWinInfo->isOutput = pWin->isOutput;
744✔
2597
  }
2598
}
15,926✔
2599

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2748
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,155✔
2749
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,155✔
2750
  SColumnInfoData* pEndTsCol = NULL;
3,155✔
2751
  if (hasEndTs) {
3,155✔
2752
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
486✔
2753
  } else {
2754
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,669✔
2755
  }
2756

2757
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
3,154✔
2758

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

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

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

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

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

2806
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL);
3,235✔
2807
    QUERY_CHECK_CODE(code, lino, _end);
3,234✔
2808

2809
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,232✔
2810
    QUERY_CHECK_CODE(code, lino, _end);
3,230!
2811

2812
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
3,230✔
2813
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
5✔
2814
      QUERY_CHECK_CODE(code, lino, _end);
6!
2815
    }
2816
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
3,231✔
2817
      code = saveResult(winInfo, pStUpdated);
2,332✔
2818
      QUERY_CHECK_CODE(code, lino, _end);
2,333!
2819
    }
2820
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,232✔
2821
      winInfo.pStatePos->beUpdated = true;
620✔
2822
      SSessionKey key = {0};
620✔
2823
      getSessionHashKey(&winInfo.sessionWin, &key);
620✔
2824
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
620✔
2825
      QUERY_CHECK_CODE(code, lino, _end);
620!
2826
    }
2827

2828
    i += winRows;
3,232✔
2829
  }
2830

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

2837
int32_t doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
1,156✔
2838
  int32_t          code = TSDB_CODE_SUCCESS;
1,156✔
2839
  int32_t          lino = 0;
1,156✔
2840
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,156✔
2841
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
1,156✔
2842
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,156✔
2843
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
1,156✔
2844
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,156✔
2845
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
1,156✔
2846
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
2,372✔
2847
    while (1) {
1,246✔
2848
      SSessionKey curWin = {0};
2,461✔
2849
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
2,461✔
2850
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
2,465✔
2851
        break;
1,216✔
2852
      }
2853
      doDeleteSessionWindow(pAggSup, &curWin);
1,249✔
2854
      if (result) {
1,248✔
2855
        code = saveDeleteInfo(result, curWin);
1,204✔
2856
        QUERY_CHECK_CODE(code, lino, _end);
1,202!
2857
      }
2858
    }
2859
  }
2860

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

2868
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
6,534✔
2869
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
6,534✔
2870
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
6,534✔
2871
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
6,534✔
2872
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
6,534✔
2873

2874
  if (pWin1->groupId > pWin2->groupId) {
6,534✔
2875
    return 1;
2,132✔
2876
  } else if (pWin1->groupId < pWin2->groupId) {
4,402✔
2877
    return -1;
1,971✔
2878
  }
2879

2880
  if (pWin1->win.skey > pWin2->win.skey) {
2,431✔
2881
    return 1;
1,363✔
2882
  } else if (pWin1->win.skey < pWin2->win.skey) {
1,068!
2883
    return -1;
1,068✔
2884
  }
2885

2886
  return 0;
×
2887
}
2888

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

2894
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
691!
2895
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
691!
2896

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

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

2905
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
691✔
2906
  colDataSetNULL(pUidCol, pBlock->info.rows);
691!
2907

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

2912
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
691✔
2913
  colDataSetNULL(pCalStCol, pBlock->info.rows);
691✔
2914

2915
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
691✔
2916
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
690!
2917

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

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

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

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

2948
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite,
17,540✔
2949
                            SGroupResInfo* pGroupResInfo) {
2950
  int32_t        code = TSDB_CODE_SUCCESS;
17,540✔
2951
  int32_t        lino = 0;
17,540✔
2952
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
17,540✔
2953
  int64_t        minWindowSize = getMinWindowSize(pOp);
17,540✔
2954
  int32_t        numOfRows = getNumOfTotalRes(pGroupResInfo);
17,530✔
2955

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

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

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

2998
_end:
522✔
2999
  if ((*Ite) == NULL) {
540!
3000
    tSimpleHashClear(pStDeleted);
540✔
3001
  }
3002

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3121
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
3,751✔
3122
  int32_t code = TSDB_CODE_SUCCESS;
3,751✔
3123
  int32_t lino = 0;
3,751✔
3124

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

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

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

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

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

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

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

3203
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
5,574✔
3204

3205
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
12,376✔
3206
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
8,618✔
3207
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
8,618✔
3208
    SResultRow*        pRow = NULL;
8,618✔
3209
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
8,618✔
3210

3211
    if (pBlock->info.id.groupId == 0) {
8,618✔
3212
      pBlock->info.id.groupId = pKey->groupId;
6,160✔
3213

3214
      void*   tbname = NULL;
6,160✔
3215
      int32_t winCode = TSDB_CODE_SUCCESS;
6,160✔
3216
      code = pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
6,160✔
3217
                                                    &tbname, false, &winCode);
3218
      QUERY_CHECK_CODE(code, lino, _end);
6,162!
3219

3220
      if (winCode != TSDB_CODE_SUCCESS) {
6,162✔
3221
        pBlock->info.parTbName[0] = 0;
1,765✔
3222
      } else {
3223
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,397✔
3224
      }
3225
      pAPI->stateStore.streamStateFreeVal(tbname);
6,162✔
3226
    } else {
3227
      // current value belongs to different group, it can't be packed into one datablock
3228
      if (pBlock->info.id.groupId != pKey->groupId) {
2,458✔
3229
        break;
1,797✔
3230
      }
3231
    }
3232

3233
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
6,821✔
3234
    QUERY_CHECK_CODE(code, lino, _end);
6,820!
3235

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

3250
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,763!
3251
      break;
×
3252
    }
3253

3254
    pGroupResInfo->index += 1;
6,763✔
3255

3256
    for (int32_t j = 0; j < numOfExprs; ++j) {
112,458✔
3257
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
105,716✔
3258

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

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

3287
    pBlock->info.dataLoad = 1;
6,742✔
3288
    pBlock->info.rows += pRow->numOfRows;
6,742✔
3289
  }
3290
  code = blockDataUpdateTsWindow(pBlock, 0);
5,555✔
3291
  QUERY_CHECK_CODE(code, lino, _end);
5,576!
3292

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

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

3308
  blockDataCleanup(pBlock);
16,984✔
3309
  taosArrayClear(pSessionKeys);
16,990✔
3310
  if (!hasRemainResults(pGroupResInfo)) {
16,990✔
3311
    cleanupGroupResInfo(pGroupResInfo);
11,419✔
3312
    goto _end;
11,435✔
3313
  }
3314

3315
  // clear the existed group id
3316
  pBlock->info.id.groupId = 0;
5,574✔
3317
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
5,574✔
3318
  QUERY_CHECK_CODE(code, lino, _end);
5,576!
3319

3320
  if (pBlock->info.rows == 0) {
5,576!
3321
    cleanupGroupResInfo(pGroupResInfo);
×
3322
  }
3323

3324
_end:
5,576✔
3325
  if (code != TSDB_CODE_SUCCESS) {
17,011!
3326
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3327
  }
3328
}
17,011✔
3329

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

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

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

3379
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
4,990✔
3380
  QUERY_CHECK_CODE(code, lino, _end);
4,988!
3381

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

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

3405
  if (pSeKey->groupId == 0) {
133✔
3406
    goto _end;
17✔
3407
  }
3408
  uint64_t preGpId = pSeKey->groupId;
116✔
3409
  for (int32_t i = size - 2; i >= 0; i--) {
449✔
3410
    pWinInfo = taosArrayGet(pAllWins, i);
333✔
3411
    pSeKey = &pWinInfo->sessionWin;
333✔
3412
    if (preGpId != pSeKey->groupId) {
333✔
3413
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
209✔
3414
      if (!tmp) {
209!
3415
        code = terrno;
×
3416
        QUERY_CHECK_CODE(code, lino, _end);
×
3417
      }
3418
      preGpId = pSeKey->groupId;
209✔
3419
    }
3420
  }
3421

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

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

3436
void* decodeSSessionKey(void* buf, SSessionKey* key) {
10✔
3437
  buf = decodeSTimeWindow(buf, &key->win);
10✔
3438
  buf = taosDecodeFixedU64(buf, &key->groupId);
10!
3439
  return buf;
10✔
3440
}
3441

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

3449
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
5✔
3450
  buf = taosDecodeFixedBool(buf, &key->isOutput);
5✔
3451
  buf = decodeSSessionKey(buf, &key->sessionWin);
5✔
3452
  return buf;
5✔
3453
}
3454

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

3461
  void* pData = (buf == NULL) ? NULL : *buf;
×
3462

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

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

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

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

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

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

3503
  return tlen;
×
3504
}
3505

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3650
    if (pInfo->recvGetAll) {
1,415✔
3651
      pInfo->recvGetAll = false;
83✔
3652
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
83✔
3653
    }
3654

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

3662
    setStreamOperatorCompleted(pOperator);
1,416✔
3663
    (*ppRes) = NULL;
1,414✔
3664
    return code;
1,414✔
3665
  }
3666

3667
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,620✔
3668
  if (!pInfo->pUpdated) {
4,620✔
3669
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
3,756✔
3670
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
3,755!
3671
  }
3672
  if (!pInfo->pStUpdated) {
4,619✔
3673
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,686✔
3674
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
3,687✔
3675
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
3,693!
3676
  }
3677
  while (1) {
3,326✔
3678
    SSDataBlock* pBlock = NULL;
7,952✔
3679
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,952✔
3680
    QUERY_CHECK_CODE(code, lino, _end);
7,946!
3681

3682
    if (pBlock == NULL) {
7,946✔
3683
      break;
3,752✔
3684
    }
3685
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,194✔
3686
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,191✔
3687

3688
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,189✔
3689
        pBlock->info.type == STREAM_CLEAR) {
3,946✔
3690
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
408✔
3691
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
411!
3692
      // gap must be 0
3693
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
411✔
3694
      QUERY_CHECK_CODE(code, lino, _end);
410!
3695

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

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

3711
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
411!
3712
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
2✔
3713
        QUERY_CHECK_CODE(code, lino, _end);
2!
3714
      }
3715
      taosArrayDestroy(pWins);
411✔
3716
      continue;
774✔
3717
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,781✔
3718
      pInfo->recvGetAll = true;
187✔
3719
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
187✔
3720
      QUERY_CHECK_CODE(code, lino, _end);
187!
3721
      continue;
187✔
3722
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,594✔
3723
      (*ppRes) = pBlock;
871✔
3724
      return code;
871✔
3725
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,723✔
3726
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
176✔
3727
      doStreamSessionSaveCheckpoint(pOperator);
176✔
3728
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
176✔
3729
      QUERY_CHECK_CODE(code, lino, _end);
176!
3730

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

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

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

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

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

3781
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
3,752✔
3782
  QUERY_CHECK_CODE(code, lino, _end);
3,750!
3783

3784
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
3,750✔
3785
  QUERY_CHECK_CODE(code, lino, _end);
3,748!
3786

3787
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
3,748✔
3788
  QUERY_CHECK_CODE(code, lino, _end);
3,751!
3789

3790
  if (!pInfo->destHasPrimaryKey) {
3,751✔
3791
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
3,731✔
3792
  }
3793
  if (pInfo->isHistoryOp) {
3,757✔
3794
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
201✔
3795
    QUERY_CHECK_CODE(code, lino, _end);
201!
3796
  }
3797
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
3,757!
3798
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
24✔
3799
    QUERY_CHECK_CODE(code, lino, _end);
24!
3800
  }
3801
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
3,757✔
3802
  pInfo->pUpdated = NULL;
3,727✔
3803
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3,727✔
3804
  QUERY_CHECK_CODE(code, lino, _end);
3,749!
3805

3806
  SSDataBlock* opRes = NULL;
3,749✔
3807
  code = buildSessionResult(pOperator, &opRes);
3,749✔
3808
  QUERY_CHECK_CODE(code, lino, _end);
3,759!
3809
  if (opRes) {
3,759✔
3810
    (*ppRes) = opRes;
1,416✔
3811
    return code;
1,416✔
3812
  }
3813

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

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

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

3851
void resetWinRange(STimeWindow* winRange) {
359✔
3852
  winRange->skey = INT64_MIN;
359✔
3853
  winRange->ekey = INT64_MAX;
359✔
3854
}
359✔
3855

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

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

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

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

3885
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
643✔
3886
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
205✔
3887
    return;
205✔
3888
  }
3889

3890
  SStreamScanInfo* pScanInfo = downstream->info;
438✔
3891
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
438✔
3892
}
3893

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

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

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

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

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

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

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

3952
  QUERY_CHECK_CODE(code, lino, _end);
176!
3953

3954
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
176✔
3955
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
176✔
3956

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

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

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

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

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

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

4012
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
896✔
4013
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4014
  QRY_PARAM_CHECK(pOptrInfo);
896!
4015

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

4027
  pOperator->pTaskInfo = pTaskInfo;
896✔
4028

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

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

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

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

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

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

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

4071
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
896✔
4072
  QUERY_CHECK_CODE(code, lino, _error);
896!
4073

4074
  if (pSessionNode->window.pTsEnd) {
896!
4075
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
896✔
4076
  }
4077

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

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

4101
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
896✔
4102
  QUERY_CHECK_CODE(code, lino, _error);
896!
4103

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

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

4132
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
896✔
4133
  QUERY_CHECK_CODE(code, lino, _error);
896!
4134

4135
  if (downstream) {
896✔
4136
    pInfo->basic.primaryPkIndex = -1;
771✔
4137
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
771✔
4138
                          &pInfo->twAggSup, &pInfo->basic);
771✔
4139
    QUERY_CHECK_CODE(code, lino, _error);
771!
4140

4141
    code = appendDownstream(pOperator, &downstream, 1);
771✔
4142
    QUERY_CHECK_CODE(code, lino, _error);
771!
4143
  }
4144

4145
  *pOptrInfo = pOperator;
896✔
4146
  return TSDB_CODE_SUCCESS;
896✔
4147

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

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

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

4176
  removeSessionResults(pAggSup, pMapUpdate, pWins);
635✔
4177
  code = copyDeleteWindowInfo(pWins, pMapDelete);
635✔
4178
  QUERY_CHECK_CODE(code, lino, _end);
635!
4179

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

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

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

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

4209
  {
4210
    SSDataBlock* opRes = NULL;
992✔
4211
    code = buildSessionResult(pOperator, &opRes);
992✔
4212
    QUERY_CHECK_CODE(code, lino, _end);
992!
4213
    if (opRes) {
992✔
4214
      (*ppRes) = opRes;
97✔
4215
      return code;
243✔
4216
    }
4217

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

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

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

4255
    if (pBlock == NULL) {
1,122✔
4256
      pOperator->status = OP_RES_TO_RETURN;
480✔
4257
      break;
480✔
4258
    }
4259
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
642✔
4260
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
642✔
4261

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

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

4299
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
536✔
4300
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
536✔
4301

4302
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
536✔
4303
  QUERY_CHECK_CODE(code, lino, _end);
538!
4304

4305
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
538✔
4306

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

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

4317
  SSDataBlock* opRes = NULL;
538✔
4318
  code = buildSessionResult(pOperator, &opRes);
538✔
4319
  QUERY_CHECK_CODE(code, lino, _end);
538!
4320
  if (opRes) {
538✔
4321
    (*ppRes) = opRes;
202✔
4322
    return code;
202✔
4323
  }
4324

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

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

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

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

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

4360
  SStorageAPI*                   pAPI = &pTaskInfo->storageAPI;
288✔
4361
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
288✔
4362
  pOperator->operatorType = pPhyNode->type;
288✔
4363
  pInfo->pOperator = pOperator;
288✔
4364

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

4372
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
288✔
4373
  QUERY_CHECK_CODE(code, lino, _error);
288!
4374

4375
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), pPhyNode->type, false, OP_NOT_OPENED, pInfo,
288✔
4376
                  pTaskInfo);
4377

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

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

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

4410
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
288✔
4411
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
250✔
4412
  }
4413

4414
  *pOptrInfo = pOperator;
288✔
4415
  return code;
288✔
4416

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

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

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

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

4465
  taosArrayDestroy(pInfo->historyWins);
354✔
4466
  blockDataDestroy(pInfo->pCheckpointRes);
354✔
4467
  tSimpleHashCleanup(pInfo->pPkDeleted);
354✔
4468

4469
  taosMemoryFreeClear(param);
354!
4470
}
4471

4472
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
4,022✔
4473
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
4,022✔
4474
    return true;
1,318✔
4475
  }
4476
  return false;
2,704✔
4477
}
4478

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

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

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

4499
static void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
3,418✔
4500
  SStreamStateCur* pCur = NULL;
3,418✔
4501

4502
  if (pAggSup == NULL || pNextWin == NULL) {
3,418!
4503
    return;
×
4504
  }
4505

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

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

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

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

4554
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
127✔
4555
  getNextStateWin(pAggSup, pNextWin, true);
127✔
4556

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

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

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

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

4603
  if (winCode == TSDB_CODE_SUCCESS) {
3,291✔
4604
    pCurWin->winInfo.isOutput = true;
2,025✔
4605
    if (pCurWin->winInfo.pStatePos->needFree) {
2,025✔
4606
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
62✔
4607
    }
4608
  } else if (pKeyData) {
1,266!
4609
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,266!
4610
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4611
    } else {
4612
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,262✔
4613
    }
4614
  }
4615

4616
  *pWinCode = winCode;
3,291✔
4617

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

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

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

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

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

4679
static bool isWinResult(SSessionKey* pKey, SSHashObj* pSeUpdate, SSHashObj* pResults) {
3,290✔
4680
  SSessionKey checkKey = {0};
3,290✔
4681
  getSessionHashKey(pKey, &checkKey);
3,290✔
4682
  if (tSimpleHashGet(pSeUpdate, &checkKey, sizeof(SSessionKey)) != NULL) {
3,291✔
4683
    return true;
29✔
4684
  }
4685

4686
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
3,261✔
4687
    return true;
17✔
4688
  }
4689
  return false;
3,245✔
4690
}
4691

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

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

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

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

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

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

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

4768
    if (isWinResult(&nextWin.winInfo.sessionWin, pSeUpdated, pAggSup->pResultRows) == false) {
3,291✔
4769
      releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,245✔
4770
    }
4771

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

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

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

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

4794
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,272✔
4795
    QUERY_CHECK_CODE(code, lino, _end);
3,272!
4796

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

4802
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,272✔
4803
      code = saveResult(curWin.winInfo, pSeUpdated);
2,957✔
4804
      QUERY_CHECK_CODE(code, lino, _end);
2,957!
4805
    }
4806

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

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

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

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

4837
  void* pData = (buf == NULL) ? NULL : *buf;
4✔
4838

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

4852
  // 2.twAggSup
4853
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
4✔
4854

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

4863
  // 4.dataVersion
4864
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
4✔
4865

4866
  // 5.basicInfo
4867
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
4✔
4868

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

4879
  return tlen;
4✔
4880
}
4881

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

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

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

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

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

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

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

4939
  if (ppBuf) {
×
4940
    (*ppBuf) = buf;
×
4941
  }
4942

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

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

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

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

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

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

5016
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
2,709✔
5017
  QUERY_CHECK_CODE(code, lino, _end);
2,706!
5018

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

5027
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,606✔
5028
  if (pOperator->status == OP_EXEC_DONE) {
4,606!
5029
    (*ppRes) = NULL;
×
5030
    return TSDB_CODE_SUCCESS;
×
5031
  }
5032

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

5049
    if (pInfo->recvGetAll) {
1,135✔
5050
      pInfo->recvGetAll = false;
3✔
5051
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
3✔
5052
    }
5053

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

5061
    setStreamOperatorCompleted(pOperator);
1,135✔
5062
    (*ppRes) = NULL;
1,135✔
5063
    return code;
1,135✔
5064
  }
5065

5066
  SOperatorInfo* downstream = pOperator->pDownstream[0];
3,110✔
5067
  if (!pInfo->pUpdated) {
3,110✔
5068
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,710✔
5069
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,705!
5070
  }
5071
  if (!pInfo->pSeUpdated) {
3,105✔
5072
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,672✔
5073
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,673✔
5074
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,677!
5075
  }
5076
  while (1) {
4,178✔
5077
    SSDataBlock* pBlock = NULL;
7,288✔
5078
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,288✔
5079
    QUERY_CHECK_CODE(code, lino, _end);
7,286!
5080

5081
    if (pBlock == NULL) {
7,286✔
5082
      break;
2,708✔
5083
    }
5084
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,578✔
5085
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,579✔
5086

5087
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,578✔
5088
        pBlock->info.type == STREAM_CLEAR) {
4,107✔
5089
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
538!
5090
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
538✔
5091
                                   pInfo->pPkDeleted, add);
5092
      QUERY_CHECK_CODE(code, lino, _end);
538!
5093
      continue;
985✔
5094
    } else if (pBlock->info.type == STREAM_GET_ALL) {
4,040✔
5095
      pInfo->recvGetAll = true;
11✔
5096
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
11✔
5097
      QUERY_CHECK_CODE(code, lino, _end);
11!
5098
      continue;
11✔
5099
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
4,029✔
5100
      (*ppRes) = pBlock;
401✔
5101
      return code;
401✔
5102
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,628✔
5103
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
435✔
5104
      doStreamStateSaveCheckpoint(pOperator);
435✔
5105
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
435✔
5106
      QUERY_CHECK_CODE(code, lino, _end);
436!
5107

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

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

5130
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,708✔
5131
  QUERY_CHECK_CODE(code, lino, _end);
2,707!
5132

5133
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,707✔
5134
  QUERY_CHECK_CODE(code, lino, _end);
2,710!
5135

5136
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,710✔
5137

5138
  if (pInfo->isHistoryOp) {
2,709✔
5139
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
102✔
5140
    QUERY_CHECK_CODE(code, lino, _end);
102!
5141
  }
5142
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,709!
5143
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
3✔
5144
    QUERY_CHECK_CODE(code, lino, _end);
3!
5145
  }
5146

5147
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,709✔
5148
  pInfo->pUpdated = NULL;
2,705✔
5149
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,705✔
5150
  QUERY_CHECK_CODE(code, lino, _end);
2,706!
5151

5152
  SSDataBlock* resBlock = NULL;
2,706✔
5153
  code = buildStateResult(pOperator, &resBlock);
2,706✔
5154
  QUERY_CHECK_CODE(code, lino, _end);
2,706!
5155
  if (resBlock != NULL) {
2,706✔
5156
    (*ppRes) = resBlock;
1,135✔
5157
    return code;
1,135✔
5158
  }
5159

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

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

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

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

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

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

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

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

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

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

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

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

5276
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
127!
5277
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
127✔
5278
      QUERY_CHECK_CODE(code, lino, _end);
127!
5279
    }
5280
  }
5281
  taosMemoryFreeClear(pBuf);
87!
5282

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

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

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

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

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

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

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

5332
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
354✔
5333
  QUERY_CHECK_CODE(code, lino, _error);
354!
5334

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

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

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

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

5363
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
354✔
5364
  QUERY_CHECK_CODE(code, lino, _error);
354!
5365

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

5378
  if (pHandle) {
354!
5379
    pInfo->isHistoryOp = pHandle->fillHistory;
354✔
5380
  }
5381

5382
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
354✔
5383
  QUERY_CHECK_CODE(code, lino, _error);
354!
5384

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

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

5405
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAggNext, NULL, destroyStreamStateOperatorInfo,
354✔
5406
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5407
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
354✔
5408

5409
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
354✔
5410
  QUERY_CHECK_CODE(code, lino, _error);
354!
5411

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

5416
  code = appendDownstream(pOperator, &downstream, 1);
354✔
5417
  QUERY_CHECK_CODE(code, lino, _error);
354!
5418

5419
  pInfo->trueForLimit = pStateNode->trueForLimit;
354✔
5420

5421
  *pOptrInfo = pOperator;
354✔
5422
  return TSDB_CODE_SUCCESS;
354✔
5423

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

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

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

5452
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
130,722✔
5453

5454
  if (pOperator->status == OP_EXEC_DONE) {
130,721✔
5455
    (*ppRes) = NULL;
668✔
5456
    return code;
668✔
5457
  }
5458

5459
  if (pOperator->status == OP_RES_TO_RETURN) {
130,053✔
5460
    SSDataBlock* resBlock = NULL;
103,723✔
5461
    code = buildIntervalResult(pOperator, &resBlock);
103,723✔
5462
    QUERY_CHECK_CODE(code, lino, _end);
103,722!
5463
    if (resBlock != NULL) {
103,722✔
5464
      (*ppRes) = resBlock;
89,455✔
5465
      return code;
103,722✔
5466
    }
5467

5468
    if (pInfo->recvGetAll) {
14,267✔
5469
      pInfo->recvGetAll = false;
177✔
5470
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
177✔
5471
    }
5472

5473
    if (pInfo->reCkBlock) {
14,267✔
5474
      pInfo->reCkBlock = false;
118✔
5475
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
118✔
5476
      (*ppRes) = pInfo->pCheckpointRes;
118✔
5477
      return code;
118✔
5478
    }
5479

5480
    setStreamOperatorCompleted(pOperator);
14,149✔
5481
    (*ppRes) = NULL;
14,149✔
5482
    return code;
14,149✔
5483
  }
5484

5485
  SOperatorInfo* downstream = pOperator->pDownstream[0];
26,330✔
5486

5487
  if (!pInfo->pUpdated) {
26,330✔
5488
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
23,560✔
5489
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
23,565!
5490
  }
5491

5492
  if (!pInfo->pUpdatedMap) {
26,335✔
5493
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
23,566✔
5494
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
23,566✔
5495
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
23,561!
5496
  }
5497

5498
  while (1) {
1,113,526✔
5499
    SSDataBlock* pBlock = NULL;
1,139,856✔
5500
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,139,856✔
5501
    QUERY_CHECK_CODE(code, lino, _end);
1,139,859✔
5502

5503
    if (pBlock == NULL) {
1,139,840✔
5504
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
23,564✔
5505
             pInfo->numOfDatapack);
5506
      pInfo->numOfDatapack = 0;
23,563✔
5507
      break;
23,563✔
5508
    }
5509

5510
    pInfo->numOfDatapack++;
1,116,276✔
5511
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
1,116,276✔
5512
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
1,116,271✔
5513

5514
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
1,116,269✔
5515
        pBlock->info.type == STREAM_CLEAR) {
1,115,861✔
5516
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
962✔
5517
      QUERY_CHECK_CODE(code, lino, _end);
965!
5518
      continue;
3,304✔
5519
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,115,307✔
5520
      pInfo->recvGetAll = true;
983✔
5521
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
983✔
5522
      QUERY_CHECK_CODE(code, lino, _end);
984!
5523
      continue;
984✔
5524
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
1,114,324✔
5525
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,693✔
5526
      (*ppRes) = pBlock;
2,693✔
5527
      return code;
2,748✔
5528
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
1,111,631✔
5529
      doDeleteWindowByGroupId(pOperator, pBlock);
55✔
5530
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
55✔
5531
      (*ppRes) = pBlock;
55✔
5532
      return code;
55✔
5533
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,111,576✔
5534
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,357✔
5535
      doStreamIntervalSaveCheckpoint(pOperator);
1,357✔
5536
      pInfo->reCkBlock = true;
1,356✔
5537
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,356✔
5538
      QUERY_CHECK_CODE(code, lino, _end);
1,355!
5539

5540
      continue;
1,355✔
5541
    } else {
5542
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,110,219!
5543
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5544
        QUERY_CHECK_CODE(code, lino, _end);
×
5545
      }
5546
    }
5547

5548
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
1,110,219✔
5549
      // set input version
5550
      pTaskInfo->version = pBlock->info.version;
320,632✔
5551
    }
5552

5553
    if (pInfo->scalarSupp.pExprInfo != NULL) {
1,110,219✔
5554
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5555
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5556
      QUERY_CHECK_CODE(code, lino, _end);
13!
5557
    }
5558

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

5570
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
1,110,223✔
5571
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
1,110,222!
5572
      pOperator->status = OP_RES_TO_RETURN;
×
5573
      code = TSDB_CODE_SUCCESS;
×
5574
      break;
×
5575
    }
5576
    QUERY_CHECK_CODE(code, lino, _end);
1,110,222!
5577
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
1,110,222✔
5578
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
1,110,222✔
5579
  }
5580
  pOperator->status = OP_RES_TO_RETURN;
23,563✔
5581
  if (!pInfo->destHasPrimaryKey) {
23,563✔
5582
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
23,547✔
5583
  }
5584
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
23,559✔
5585
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5586
  QUERY_CHECK_CODE(code, lino, _end);
23,560!
5587

5588
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
23,560!
5589
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
16✔
5590
    QUERY_CHECK_CODE(code, lino, _end);
16!
5591
  }
5592

5593
  void*   pIte = NULL;
23,560✔
5594
  int32_t iter = 0;
23,560✔
5595
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
8,899,651✔
5596
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
8,876,091✔
5597
    if (!tmp) {
8,876,091!
5598
      code = terrno;
×
5599
      QUERY_CHECK_CODE(code, lino, _end);
×
5600
    }
5601
  }
5602
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
23,563✔
5603

5604
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
23,564✔
5605
  pInfo->pUpdated = NULL;
23,565✔
5606
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
23,565✔
5607
  QUERY_CHECK_CODE(code, lino, _end);
23,566!
5608

5609
  tSimpleHashCleanup(pInfo->pUpdatedMap);
23,566✔
5610
  pInfo->pUpdatedMap = NULL;
23,566✔
5611

5612
  code = buildIntervalResult(pOperator, ppRes);
23,566✔
5613
  QUERY_CHECK_CODE(code, lino, _end);
23,561!
5614

5615
  return code;
23,561✔
5616

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

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

5633
  int32_t code = TSDB_CODE_SUCCESS;
2,973✔
5634
  int32_t lino = 0;
2,973✔
5635
  int32_t numOfCols = 0;
2,973✔
5636

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

5644
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
2,973✔
5645

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

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

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

5668
  pOperator->pTaskInfo = pTaskInfo;
2,973✔
5669
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
2,973✔
5670

5671
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2,973✔
5672
  pInfo->ignoreExpiredDataSaved = false;
2,973✔
5673

5674
  SExprSupp* pSup = &pOperator->exprSupp;
2,973✔
5675
  pSup->hasWindowOrGroup = true;
2,973✔
5676

5677
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2,973✔
5678
  QUERY_CHECK_CODE(code, lino, _error);
2,973!
5679

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

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

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

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

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

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

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

5712
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
2,973✔
5713
  QUERY_CHECK_CODE(code, lino, _error);
2,973!
5714

5715
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2,973✔
5716

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

5731
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
2,972✔
5732
  pInfo->pState->pFileState = NULL;
2,972✔
5733

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

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

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

5753
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
2,972✔
5754
  QUERY_CHECK_CODE(code, lino, _error);
2,973!
5755

5756
  pInfo->recvGetAll = false;
2,973✔
5757

5758
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
2,973✔
5759
  QUERY_CHECK_CODE(code, lino, _error);
2,973!
5760

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

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

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

5780
  code = appendDownstream(pOperator, &downstream, 1);
2,973✔
5781
  QUERY_CHECK_CODE(code, lino, _error);
2,973!
5782

5783
  *pOptrInfo = pOperator;
2,973✔
5784
  return TSDB_CODE_SUCCESS;
2,973✔
5785

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

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

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

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

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

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

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

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

5861
    pResult = (SResultRow*)pResPos->pRowBuff;
1,304✔
5862

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

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

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

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

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

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

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

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

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

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

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

5953
  return NULL;
89✔
5954
}
5955

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

5965
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
106!
5966

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

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

5994
    resBlock = buildMidIntervalResult(pOperator);
70✔
5995
    if (resBlock != NULL) {
70✔
5996
      (*ppRes) = resBlock;
2✔
5997
      return code;
2✔
5998
    }
5999

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6136
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
65✔
6137
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
65✔
6138

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

6149
  tSimpleHashCleanup(pInfo->pUpdatedMap);
65✔
6150
  pInfo->pUpdatedMap = NULL;
65✔
6151
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
65✔
6152

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

6158
  SSDataBlock* resBlock = NULL;
65✔
6159
  code = buildIntervalResult(pOperator, &resBlock);
65✔
6160
  QUERY_CHECK_CODE(code, lino, _end);
65!
6161
  if (resBlock != NULL) {
65✔
6162
    (*ppRes) = resBlock;
28✔
6163
    return code;
28✔
6164
  }
6165

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

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

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

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

6194
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
34,866✔
6195
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
34,866✔
6196
         getStreamOpName(pOperator->operatorType), pOperator->status);
6197
  setOperatorCompleted(pOperator);
34,866✔
6198
}
34,862✔
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