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

taosdata / TDengine / #3661

17 Mar 2025 05:39AM UTC coverage: 62.007% (-0.03%) from 62.039%
#3661

push

travis-ci

web-flow
tests: add tdb ut (#30093)

* fix: compile warnings

* tests: add tdb ut

* test(tdb): fix return code

* test: recover ut

* fix: minor changes

* fix: enable test

* fix: ut errors

---------

Co-authored-by: Minglei Jin <mljin@taosdata.com>

153829 of 317582 branches covered (48.44%)

Branch coverage included in aggregate %.

240310 of 318051 relevant lines covered (75.56%)

19602636.8 hits per line

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

71.22
/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 "streaminterval.h"
23
#include "streamsession.h"
24
#include "tchecksum.h"
25
#include "tcommon.h"
26
#include "tcompare.h"
27
#include "tdatablock.h"
28
#include "tfill.h"
29
#include "tglobal.h"
30
#include "tlog.h"
31
#include "ttime.h"
32

33
#define IS_FINAL_INTERVAL_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL)
34
#define IS_MID_INTERVAL_OP(op)   ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL)
35

36
#define IS_FINAL_SESSION_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION)
37

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

46
#define MAX_STREAM_HISTORY_RESULT 20000000
47

48
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes);
49

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

54
  if (num <= 0) return -1;
1,607✔
55
  if (order == TSDB_ORDER_DESC) {
1,399!
56
    // find the first position which is smaller or equal than the key
57
    while (1) {
58
      if (comparefn(pKey, keyList, lastPos) >= 0) return lastPos;
1,499✔
59
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
359✔
60
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
206✔
61

62
      numOfRows = lastPos - firstPos + 1;
147✔
63
      midPos = (numOfRows >> 1) + firstPos;
147✔
64

65
      if (comparefn(pKey, keyList, midPos) < 0) {
147✔
66
        lastPos = midPos - 1;
64✔
67
      } else if (comparefn(pKey, keyList, midPos) > 0) {
83✔
68
        firstPos = midPos + 1;
36✔
69
      } else {
70
        break;
47✔
71
      }
72
    }
73

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

80
      if (comparefn(pKey, keyList, lastPos) > 0) {
×
81
        lastPos = lastPos + 1;
×
82
        if (lastPos >= num)
×
83
          return -1;
×
84
        else
85
          return lastPos;
×
86
      }
87

88
      numOfRows = lastPos - firstPos + 1;
×
89
      midPos = (numOfRows >> 1) + firstPos;
×
90

91
      if (comparefn(pKey, keyList, midPos) < 0) {
×
92
        lastPos = midPos - 1;
×
93
      } else if (comparefn(pKey, keyList, midPos) > 0) {
×
94
        firstPos = midPos + 1;
×
95
      } else {
96
        break;
×
97
      }
98
    }
99
  }
100

101
  return midPos;
47✔
102
}
103

104
static int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
178✔
105
  SArray*          res = (SArray*)data;
178✔
106
  SPullWindowInfo* pos = taosArrayGet(res, index);
178✔
107
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
178✔
108
  if (pData->groupId > pos->groupId) {
178✔
109
    return 1;
64✔
110
  } else if (pData->groupId < pos->groupId) {
114✔
111
    return -1;
59✔
112
  }
113

114
  if (pData->window.skey > pos->window.ekey) {
55✔
115
    return 1;
42✔
116
  } else if (pData->window.ekey < pos->window.skey) {
13✔
117
    return -1;
7✔
118
  }
119
  return 0;
6✔
120
}
121

122
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
221✔
123
  int32_t size = taosArrayGetSize(pPullWins);
221✔
124
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
221✔
125
  if (index == -1) {
221✔
126
    index = 0;
174✔
127
  } else {
128
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
47✔
129
    if (code == 0) {
47✔
130
      SPullWindowInfo* pos = taosArrayGet(pPullWins, index);
3✔
131
      pos->window.skey = TMIN(pos->window.skey, pPullInfo->window.skey);
3✔
132
      pos->window.ekey = TMAX(pos->window.ekey, pPullInfo->window.ekey);
3✔
133
      pos->calWin.skey = TMIN(pos->calWin.skey, pPullInfo->calWin.skey);
3✔
134
      pos->calWin.ekey = TMAX(pos->calWin.ekey, pPullInfo->calWin.ekey);
3✔
135
      return TSDB_CODE_SUCCESS;
3✔
136
    } else if (code > 0) {
44!
137
      index++;
44✔
138
    }
139
  }
140
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
218!
141
    return terrno;
×
142
  }
143
  return TSDB_CODE_SUCCESS;
218✔
144
}
145

146
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
10,469✔
147
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
10,469!
148
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
149
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
150
  }
151
  winInfo.sessionWin.win.ekey = winInfo.sessionWin.win.skey;
10,470✔
152
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
10,470✔
153
}
154

155
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
9,715,313✔
156
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
9,715,313!
157
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
158
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
159
  }
160
  return tSimpleHashPut(pUpdatedMap, pKey, sizeof(SWinKey), &pPos, POINTER_BYTES);
9,715,238✔
161
}
162

163
static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
309✔
164
  SWinKey key = {.ts = ts, .groupId = groupId};
309✔
165
  return saveWinResult(&key, pPos, pUpdatedMap);
309✔
166
}
167

168
static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) {
207✔
169
  int32_t size = taosArrayGetSize(pWins);
207✔
170
  for (int32_t i = 0; i < size; i++) {
456✔
171
    SWinKey* pW = taosArrayGet(pWins, i);
249✔
172
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
249✔
173
    if (tmp) {
249!
174
      void* value = *(void**)tmp;
×
175
      taosMemoryFree(value);
×
176
      int32_t tmpRes = tSimpleHashRemove(pUpdatedMap, pW, sizeof(SWinKey));
×
177
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
×
178
    }
179
  }
180
}
207✔
181

182
int32_t compareWinKey(void* pKey, void* data, int32_t index) {
3,460✔
183
  void* pDataPos = taosArrayGet((SArray*)data, index);
3,460✔
184
  return winKeyCmprImpl(pKey, pDataPos);
3,460✔
185
}
186

187
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
27,830✔
188
  taosArraySort(pDelWins, winKeyCmprImpl);
27,830✔
189
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
27,828✔
190
  int32_t delSize = taosArrayGetSize(pDelWins);
27,827✔
191
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
27,828✔
192
    return;
27,251✔
193
  }
194
  void*   pIte = NULL;
577✔
195
  int32_t iter = 0;
577✔
196
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,668✔
197
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
1,091✔
198
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
1,091✔
199
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
1,091✔
200
      taosArrayRemove(pDelWins, index);
881✔
201
      delSize = taosArrayGetSize(pDelWins);
881✔
202
    }
203
  }
204
}
205

206
bool isOverdue(TSKEY ekey, STimeWindowAggSupp* pTwSup) {
90,973,490✔
207
  return pTwSup->maxTs != INT64_MIN && ekey < pTwSup->maxTs - pTwSup->waterMark;
90,973,490✔
208
}
209

210
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
40,327,425✔
211

212
static void doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) {
3,527✔
213
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,527✔
214

215
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
3,527✔
216
  SWinKey                      key = {.ts = ts, .groupId = groupId};
3,527✔
217
  int32_t                      tmpRes = tSimpleHashRemove(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey));
3,527✔
218
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,527✔
219
  pAPI->stateStore.streamStateDel(pInfo->pState, &key);
3,527✔
220
}
3,526✔
221

222
int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,436✔
223

224
static void doDeleteWindowByGroupId(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
55✔
225
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
55✔
226
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
55✔
227

228
  SColumnInfoData* pGpIdCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
55✔
229
  uint64_t* pGroupIdData = (uint64_t*)pGpIdCol->pData;
55✔
230
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
110✔
231
    uint64_t groupId = pGroupIdData[i];
55✔
232
    void*   pIte = NULL;
55✔
233
    int32_t iter = 0;
55✔
234
    while ((pIte = tSimpleHashIterate(pInfo->aggSup.pResultRowHashTable, pIte, &iter)) != NULL) {
71✔
235
      size_t keyLen = 0;
16✔
236
      SWinKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
16!
237
      if (pKey->groupId == groupId) {
16!
238
        int32_t tmpRes = tSimpleHashIterateRemove(pInfo->aggSup.pResultRowHashTable, pKey, keyLen, &pIte, &iter);
16✔
239
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
16!
240
      }
241
    }
242

243
    pAPI->stateStore.streamStateDelByGroupId(pInfo->pState, groupId);
55✔
244
  }
245
}
55✔
246

247
static int32_t doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins,
2,389✔
248
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
249
  int32_t                      code = TSDB_CODE_SUCCESS;
2,389✔
250
  int32_t                      lino = 0;
2,389✔
251
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,389✔
252
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2,389✔
253
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,389✔
254
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
2,389✔
255
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,389✔
256
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
2,389✔
257
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
2,389✔
258
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
2,389✔
259
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
2,389✔
260
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
2,389✔
261
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,389✔
262
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
2,389✔
263
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5,074✔
264
    SResultRowInfo dumyInfo = {0};
2,685✔
265
    dumyInfo.cur.pageId = -1;
2,685✔
266

267
    STimeWindow win = {0};
2,685✔
268
    if (IS_FINAL_INTERVAL_OP(pOperator) || IS_MID_INTERVAL_OP(pOperator)) {
2,685✔
269
      win.skey = startTsCols[i];
261✔
270
      win.ekey = endTsCols[i];
261✔
271
    } else {
272
      win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC);
2,424✔
273
    }
274

275
    do {
276
      if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i], pBlock->info.type)) {
3,581✔
277
        getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
26✔
278
        continue;
79✔
279
      }
280
      uint64_t winGpId = pGpDatas[i];
3,555✔
281
      SWinKey  winRes = {.ts = win.skey, .groupId = winGpId};
3,555✔
282
      void*    chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
3,555✔
283
      if (chIds) {
3,555✔
284
        int32_t childId = getChildIndex(pBlock);
56✔
285
        if (pInvalidWins) {
56✔
286
          qDebug("===stream===save invalid delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d", winRes.ts,
50!
287
                 winRes.groupId, childId);
288
          code = taosHashPut(pInvalidWins, &winRes, sizeof(SWinKey), NULL, 0);
50✔
289
          QUERY_CHECK_CODE(code, lino, _end);
50!
290
        }
291

292
        SArray* chArray = *(void**)chIds;
56✔
293
        int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
56✔
294
        if (index != -1) {
56✔
295
          qDebug("===stream===try push delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d ,continue", win.skey,
53!
296
                 winGpId, childId);
297
          getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
53✔
298
          continue;
53✔
299
        }
300
      }
301
      doDeleteWindow(pOperator, win.skey, winGpId);
3,502✔
302
      if (pUpWins) {
3,502✔
303
        void* tmp = taosArrayPush(pUpWins, &winRes);
2,739✔
304
        if (!tmp) {
2,739!
305
          code = terrno;
×
306
          QUERY_CHECK_CODE(code, lino, _end);
×
307
        }
308
      }
309
      if (pUpdatedMap) {
3,501!
310
        int32_t tmpRes = tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey));
3,501✔
311
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,502✔
312
      }
313
      getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
3,502✔
314
    } while (win.ekey <= endTsCols[i]);
3,581✔
315
  }
316
_end:
2,389✔
317
  if (code != TSDB_CODE_SUCCESS) {
2,389!
318
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
319
  }
320
  return code;
2,389✔
321
}
322

323
static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) {
1,101✔
324
  void*   pIte = NULL;
1,101✔
325
  int32_t iter = 0;
1,101✔
326
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1,420✔
327
    SWinKey*     pKey = tSimpleHashGetKey(pIte, NULL);
319✔
328
    uint64_t     groupId = pKey->groupId;
319✔
329
    TSKEY        ts = pKey->ts;
319✔
330
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
319✔
331
    if (!pPos->beUpdated) {
319✔
332
      continue;
10✔
333
    }
334
    pPos->beUpdated = false;
309✔
335
    int32_t code = saveWinResultInfo(ts, groupId, pPos, resWins);
309✔
336
    if (code != TSDB_CODE_SUCCESS) {
309!
337
      return code;
×
338
    }
339
  }
340
  return TSDB_CODE_SUCCESS;
1,101✔
341
}
342

343
static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval,
26,194✔
344
                                         SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins,
345
                                         SOperatorInfo* pOperator) {
346
  qDebug("===stream===close interval window");
26,194✔
347
  int32_t                      code = TSDB_CODE_SUCCESS;
26,194✔
348
  int32_t                      lino = 0;
26,194✔
349
  void*                        pIte = NULL;
26,194✔
350
  int32_t                      iter = 0;
26,194✔
351
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
26,194✔
352
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
26,194✔
353
  int32_t                      delSize = taosArrayGetSize(pDelWins);
26,194✔
354
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
31,242✔
355
    void*    key = tSimpleHashGetKey(pIte, NULL);
5,046!
356
    SWinKey* pWinKey = (SWinKey*)key;
5,046✔
357
    if (delSize > 0) {
5,046✔
358
      int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey);
295✔
359
      if (index >= 0 && 0 == compareWinKey(pWinKey, pDelWins, index)) {
295✔
360
        taosArrayRemove(pDelWins, index);
118✔
361
        delSize = taosArrayGetSize(pDelWins);
118✔
362
      }
363
    }
364

365
    void*       chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey));
5,046✔
366
    STimeWindow win = {
10,092✔
367
        .skey = pWinKey->ts,
5,046✔
368
        .ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1,
5,046✔
369
    };
370
    if (isCloseWindow(&win, pTwSup)) {
5,046✔
371
      if (chIds && pPullDataMap) {
2,078!
372
        SArray* chAy = *(SArray**)chIds;
×
373
        int32_t size = taosArrayGetSize(chAy);
×
374
        qDebug("===stream===window %" PRId64 " wait child size:%d", pWinKey->ts, size);
×
375
        for (int32_t i = 0; i < size; i++) {
×
376
          qDebug("===stream===window %" PRId64 " wait child id:%d", pWinKey->ts, *(int32_t*)taosArrayGet(chAy, i));
×
377
        }
378
        continue;
×
379
      } else if (pPullDataMap) {
2,078✔
380
        qDebug("===stream===close window %" PRId64, pWinKey->ts);
572✔
381
      }
382

383
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
2,078!
384
        code = saveWinResult(pWinKey, *(SRowBuffPos**)pIte, closeWins);
2,078✔
385
        QUERY_CHECK_CODE(code, lino, _end);
2,078!
386
      }
387
      int32_t tmpRes = tSimpleHashIterateRemove(pHashMap, pWinKey, sizeof(SWinKey), &pIte, &iter);
2,078✔
388
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
2,078✔
389
    }
390
  }
391

392
_end:
26,193✔
393
  if (code != TSDB_CODE_SUCCESS) {
26,193!
394
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
395
  }
396
  return code;
26,195✔
397
}
398

399
STimeWindow getFinalTimeWindow(int64_t ts, SInterval* pInterval) {
242,217✔
400
  STimeWindow w = {.skey = ts, .ekey = INT64_MAX};
242,217✔
401
  w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1;
242,217✔
402
  return w;
242,217✔
403
}
404

405
static void doBuildDeleteResult(SExecTaskInfo* pTaskInfo, SArray* pWins, int32_t* index,
144,918✔
406
                                SSDataBlock* pBlock) {
407
  doBuildDeleteResultImpl(&pTaskInfo->storageAPI.stateStore, pTaskInfo->streamInfo.pState, pWins, index, pBlock);
144,918✔
408
}
144,918✔
409

410
void doBuildDeleteResultImpl(SStateStore* pAPI, SStreamState* pState, SArray* pWins, int32_t* index,
146,794✔
411
                             SSDataBlock* pBlock) {
412
  int32_t code = TSDB_CODE_SUCCESS;
146,794✔
413
  int32_t lino = 0;
146,794✔
414
  blockDataCleanup(pBlock);
146,794✔
415
  int32_t size = taosArrayGetSize(pWins);
146,795✔
416
  if (*index == size) {
146,796✔
417
    *index = 0;
146,072✔
418
    taosArrayClear(pWins);
146,072✔
419
    goto _end;
146,070✔
420
  }
421
  code = blockDataEnsureCapacity(pBlock, size - *index);
724✔
422
  QUERY_CHECK_CODE(code, lino, _end);
724!
423

424
  uint64_t uid = 0;
724✔
425
  for (int32_t i = *index; i < size; i++) {
2,299✔
426
    SWinKey* pWin = taosArrayGet(pWins, i);
1,575✔
427
    void*    tbname = NULL;
1,575✔
428
    int32_t  winCode = TSDB_CODE_SUCCESS;
1,575✔
429
    code = pAPI->streamStateGetParName(pState, pWin->groupId, &tbname, false, &winCode);
1,575✔
430
    QUERY_CHECK_CODE(code, lino, _end);
1,575!
431

432
    if (winCode != TSDB_CODE_SUCCESS) {
1,575✔
433
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, NULL);
1,085✔
434
      QUERY_CHECK_CODE(code, lino, _end);
1,085!
435
    } else {
436
      QUERY_CHECK_CONDITION((tbname), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
490!
437
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
438
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
490✔
439
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, parTbName);
490✔
440
      QUERY_CHECK_CODE(code, lino, _end);
489!
441
    }
442
    pAPI->streamStateFreeVal(tbname);
1,574✔
443
    (*index)++;
1,575✔
444
  }
445

446
_end:
724✔
447
  if (code != TSDB_CODE_SUCCESS) {
146,794!
448
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
449
  }
450
}
146,794✔
451

452
void destroyFlusedPos(void* pRes) {
940,635✔
453
  SRowBuffPos* pPos = (SRowBuffPos*)pRes;
940,635✔
454
  if (pPos->needFree && !pPos->pRowBuff) {
940,635!
455
    taosMemoryFreeClear(pPos->pKey);
×
456
    taosMemoryFree(pPos);
×
457
  }
458
}
940,635✔
459

460
void destroyFlusedppPos(void* ppRes) {
2✔
461
  void* pRes = *(void**)ppRes;
2✔
462
  destroyFlusedPos(pRes);
2✔
463
}
2✔
464

465
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
6,534✔
466
  int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
6,534✔
467
  if (pGroupResInfo->index >= 0 && pGroupResInfo->index < size) {
6,534!
468
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
940,635✔
469
      void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
940,633✔
470
      destroyFlusedPos(pPos);
940,633✔
471
    }
472
  }
473
  pGroupResInfo->freeItem = false;
6,534✔
474
  taosArrayDestroy(pGroupResInfo->pRows);
6,534✔
475
  pGroupResInfo->pRows = NULL;
6,533✔
476
  pGroupResInfo->index = 0;
6,533✔
477
  pGroupResInfo->delIndex = 0;
6,533✔
478
}
6,533✔
479

480
void destroyStreamFinalIntervalOperatorInfo(void* param) {
3,938✔
481
  if (param == NULL) {
3,938!
482
    return;
×
483
  }
484
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)param;
3,938✔
485
  cleanupBasicInfo(&pInfo->binfo);
3,938✔
486
  if (pInfo->pOperator) {
3,938!
487
    cleanupResultInfo(pInfo->pOperator->pTaskInfo, &pInfo->pOperator->exprSupp, &pInfo->groupResInfo, &pInfo->aggSup,
3,938✔
488
                      false);
489
    pInfo->pOperator = NULL;
3,938✔
490
  }
491

492
  destroyStreamBasicInfo(&pInfo->basic);
3,938✔
493
  cleanupAggSup(&pInfo->aggSup);
3,937✔
494
  clearGroupResInfo(&pInfo->groupResInfo);
3,938✔
495
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
3,938✔
496
  pInfo->pUpdated = NULL;
3,938✔
497

498
  // it should be empty.
499
  void* pIte = NULL;
3,938✔
500
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
3,939✔
501
    taosArrayDestroy(*(void**)pIte);
1✔
502
  }
503
  taosHashCleanup(pInfo->pPullDataMap);
3,938✔
504
  taosHashCleanup(pInfo->pFinalPullDataMap);
3,938✔
505
  taosArrayDestroy(pInfo->pPullWins);
3,938✔
506
  blockDataDestroy(pInfo->pPullDataRes);
3,938✔
507
  taosArrayDestroy(pInfo->pDelWins);
3,938✔
508
  blockDataDestroy(pInfo->pDelRes);
3,938✔
509
  blockDataDestroy(pInfo->pMidRetriveRes);
3,938✔
510
  blockDataDestroy(pInfo->pMidPulloverRes);
3,938✔
511
  if (pInfo->pUpdatedMap != NULL) {
3,938✔
512
    // free flushed pos
513
    tSimpleHashSetFreeFp(pInfo->pUpdatedMap, destroyFlusedppPos);
2✔
514
    tSimpleHashCleanup(pInfo->pUpdatedMap);
2✔
515
    pInfo->pUpdatedMap = NULL;
2✔
516
  }
517

518
  if (pInfo->stateStore.streamFileStateDestroy != NULL) {
3,938!
519
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
3,938✔
520
  }
521
  taosArrayDestroy(pInfo->pMidPullDatas);
3,938✔
522

523
  if (pInfo->pState != NULL && pInfo->pState->dump == 1) {
3,938!
524
    taosMemoryFreeClear(pInfo->pState->pTdbState->pOwner);
874!
525
    taosMemoryFreeClear(pInfo->pState->pTdbState);
874!
526
  }
527
  taosMemoryFreeClear(pInfo->pState);
3,938!
528

529
  nodesDestroyNode((SNode*)pInfo->pPhyNode);
3,938✔
530
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
3,938✔
531
  cleanupExprSupp(&pInfo->scalarSupp);
3,938✔
532
  tSimpleHashCleanup(pInfo->pDeletedMap);
3,938✔
533

534
  blockDataDestroy(pInfo->pCheckpointRes);
3,937✔
535

536
  taosMemoryFreeClear(param);
3,938!
537
}
538

539
#ifdef BUILD_NO_CALL
540
static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
541
  for (int32_t i = 0; i < numOfCols; i++) {
542
    if (fmIsUserDefinedFunc(pFCtx[i].functionId) || !fmIsInvertible(pFCtx[i].functionId)) {
543
      return false;
544
    }
545
  }
546
  return true;
547
}
548
#endif
549

550
void reloadFromDownStream(SOperatorInfo* downstream, SStreamIntervalOperatorInfo* pInfo) {
1,347✔
551
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
1,347✔
552

553
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
1,347✔
554
    reloadFromDownStream(downstream->pDownstream[0], pInfo);
64✔
555
    return;
64✔
556
  }
557

558
  SStreamScanInfo* pScanInfo = downstream->info;
1,283✔
559
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
1,283✔
560
}
561

562
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
10,863,223✔
563

564
int32_t initIntervalDownStream(SOperatorInfo* downstream, uint16_t type, SStreamIntervalOperatorInfo* pInfo,
3,989✔
565
                               struct SSteamOpBasicInfo* pBasic) {
566
  int32_t        code = TSDB_CODE_SUCCESS;
3,989✔
567
  int32_t        lino = 0;
3,989✔
568
  SStateStore*   pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
3,989✔
569
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
3,989✔
570

571
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
3,989✔
572
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
264✔
573
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
264✔
574
  }
575

576
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
3,989✔
577
    return initIntervalDownStream(downstream->pDownstream[0], type, pInfo, pBasic);
264✔
578
  }
579

580
  SStreamScanInfo* pScanInfo = downstream->info;
3,725✔
581
  pScanInfo->windowSup.parentType = type;
3,725✔
582
  pScanInfo->windowSup.pIntervalAggSup = &pInfo->aggSup;
3,725✔
583
  if (!pScanInfo->pUpdateInfo) {
3,725✔
584
    code = pAPI->updateInfoInitP(&pInfo->interval, pInfo->twAggSup.waterMark, pScanInfo->igCheckUpdate,
3,443✔
585
                                 pScanInfo->pkColType, pScanInfo->pkColLen, &pScanInfo->pUpdateInfo);
3,443✔
586
    QUERY_CHECK_CODE(code, lino, _end);
3,443!
587
  }
588

589
  pScanInfo->interval = pInfo->interval;
3,725✔
590
  pScanInfo->twAggSup = pInfo->twAggSup;
3,725✔
591
  pScanInfo->pState = pInfo->pState;
3,725✔
592
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
3,725✔
593
  if (!hasSrcPrimaryKeyCol(pBasic)) {
3,725✔
594
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
3,720✔
595
  }
596

597
_end:
4✔
598
  if (code != TSDB_CODE_SUCCESS) {
3,724!
599
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
600
  }
601
  return code;
3,724✔
602
}
603

604
int32_t compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t numOfOutput,
45✔
605
                         SExecTaskInfo* pTaskInfo, SColumnInfoData* pTimeWindowData) {
606
  int32_t code = TSDB_CODE_SUCCESS;
45✔
607
  int32_t lino = 0;
45✔
608
  for (int32_t k = 0; k < numOfOutput; ++k) {
256✔
609
    if (fmIsWindowPseudoColumnFunc(pDestCtx[k].functionId)) {
213✔
610
      if (!pTimeWindowData) {
49!
611
        continue;
×
612
      }
613

614
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pDestCtx[k]);
49✔
615
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
49✔
616
      SColumnInfoData      idata = {0};
49✔
617
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
49✔
618
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
49✔
619
      idata.pData = p;
49✔
620

621
      SScalarParam out = {.columnData = &idata};
49✔
622
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
49✔
623
      code = pDestCtx[k].sfp.process(&tw, 1, &out);
49✔
624
      QUERY_CHECK_CODE(code, lino, _end);
49!
625

626
      pEntryInfo->numOfRes = 1;
49✔
627
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
164!
628
      code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
162✔
629
      QUERY_CHECK_CODE(code, lino, _end);
162!
630
    } else if (pDestCtx[k].fpSet.combine == NULL) {
2!
631
      char* funName = fmGetFuncName(pDestCtx[k].functionId);
2✔
632
      qError("%s error, combine funcion for %s is not implemented", GET_TASKID(pTaskInfo), funName);
2!
633
      taosMemoryFreeClear(funName);
2!
634
      code = TSDB_CODE_FAILED;
2✔
635
      QUERY_CHECK_CODE(code, lino, _end);
2!
636
    }
637
  }
638

639
_end:
43✔
640
  if (code != TSDB_CODE_SUCCESS) {
45✔
641
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
642
  }
643
  return code;
45✔
644
}
645

646
bool hasIntervalWindow(void* pState, SWinKey* pKey, SStateStore* pStore) {
23✔
647
  return pStore->streamStateCheck(pState, pKey, false, NULL);
23✔
648
}
649

650
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
9,720,301✔
651
                             SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset,
652
                             SAggSupporter* pAggSup, SStateStore* pStore, int32_t* pWinCode) {
653
  int32_t code = TSDB_CODE_SUCCESS;
9,720,301✔
654
  int32_t lino = 0;
9,720,301✔
655
  SWinKey key = {.ts = win->skey, .groupId = groupId};
9,720,301✔
656
  char*   value = NULL;
9,720,301✔
657
  int32_t size = pAggSup->resultRowSize;
9,720,301✔
658

659
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
9,720,301✔
660
  QUERY_CHECK_CODE(code, lino, _end);
9,720,761!
661

662
  *pResult = (SRowBuffPos*)value;
9,720,761✔
663
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
9,720,761✔
664

665
  // set time window for current result
666
  res->win = (*win);
9,720,761✔
667
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
9,720,761✔
668
  QUERY_CHECK_CODE(code, lino, _end);
9,719,529!
669

670
_end:
9,719,529✔
671
  if (code != TSDB_CODE_SUCCESS) {
9,719,529!
672
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
673
  }
674
  return code;
9,719,498✔
675
}
676

677
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
30,667,581✔
678
                           SStateStore* pStore) {
679
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
30,667,581✔
680
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
23✔
681
    if (!hasIntervalWindow(pState, &key, pStore)) {
23✔
682
      return true;
12✔
683
    }
684
    return false;
11✔
685
  }
686
  return false;
30,667,558✔
687
}
688

689
int32_t getNexWindowPos(SInterval* pInterval, SDataBlockInfo* pBlockInfo, TSKEY* tsCols, int32_t startPos, TSKEY eKey,
42✔
690
                        STimeWindow* pNextWin) {
691
  int32_t forwardRows =
692
      getNumOfRowsInTimeWindow(pBlockInfo, tsCols, startPos, eKey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
42✔
693
  int32_t prevEndPos = forwardRows - 1 + startPos;
42✔
694
  return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
42✔
695
}
696

697
int32_t addPullWindow(SHashObj* pMap, SWinKey* pWinRes, int32_t size) {
227✔
698
  int32_t code = TSDB_CODE_SUCCESS;
227✔
699
  int32_t lino = 0;
227✔
700
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
227✔
701
  QUERY_CHECK_NULL(childIds, code, lino, _end, terrno);
227!
702
  for (int32_t i = 0; i < size; i++) {
979✔
703
    void* tmp = taosArrayPush(childIds, &i);
752✔
704
    if (!tmp) {
752!
705
      code = terrno;
×
706
      QUERY_CHECK_CODE(code, lino, _end);
×
707
    }
708
  }
709
  code = taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
227✔
710
  QUERY_CHECK_CODE(code, lino, _end);
227!
711
_end:
227✔
712
  if (code != TSDB_CODE_SUCCESS) {
227!
713
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
714
  }
715
  return code;
227✔
716
}
717

718
static void clearStreamIntervalOperator(SStreamIntervalOperatorInfo* pInfo) {
1,759✔
719
  tSimpleHashClear(pInfo->aggSup.pResultRowHashTable);
1,759✔
720
  clearDiskbasedBuf(pInfo->aggSup.pResultBuf);
1,759✔
721
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
1,759✔
722
  pInfo->aggSup.currentPageId = -1;
1,759✔
723
  pInfo->stateStore.streamStateClear(pInfo->pState);
1,759✔
724
}
1,759✔
725

726
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
4,236✔
727
  if (pBlock->info.rows <= 0) {
4,236✔
728
    return;
4,078✔
729
  }
730
  blockDataCleanup(pBlock);
158✔
731
}
732

733
void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
4,236✔
734
  int32_t code = TSDB_CODE_SUCCESS;
4,236✔
735
  int32_t lino = 0;
4,236✔
736
  clearSpecialDataBlock(pBlock);
4,236✔
737
  int32_t size = taosArrayGetSize(array);
4,236✔
738
  if (size - (*pIndex) == 0) {
4,236✔
739
    goto _end;
4,078✔
740
  }
741
  code = blockDataEnsureCapacity(pBlock, size - (*pIndex));
158✔
742
  QUERY_CHECK_CODE(code, lino, _end);
158!
743

744
  SColumnInfoData* pStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
158✔
745
  SColumnInfoData* pEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
158✔
746
  SColumnInfoData* pGroupId = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
158✔
747
  SColumnInfoData* pCalStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
158✔
748
  SColumnInfoData* pCalEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
158✔
749
  SColumnInfoData* pTbName = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
158✔
750
  SColumnInfoData* pPrimaryKey = NULL;
158✔
751
  if (taosArrayGetSize(pBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
158!
752
    pPrimaryKey = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
753
  }
754
  for (; (*pIndex) < size; (*pIndex)++) {
376✔
755
    SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
218✔
756
    code = colDataSetVal(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false);
218✔
757
    QUERY_CHECK_CODE(code, lino, _end);
218!
758

759
    code = colDataSetVal(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false);
218✔
760
    QUERY_CHECK_CODE(code, lino, _end);
218!
761

762
    code = colDataSetVal(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false);
218✔
763
    QUERY_CHECK_CODE(code, lino, _end);
218!
764

765
    code = colDataSetVal(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false);
218✔
766
    QUERY_CHECK_CODE(code, lino, _end);
218!
767

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

771
    colDataSetNULL(pTbName, pBlock->info.rows);
218!
772
    if (pPrimaryKey != NULL) {
218!
773
      colDataSetNULL(pPrimaryKey, pBlock->info.rows);
×
774
    }
775

776
    pBlock->info.rows++;
218✔
777
  }
778
  if ((*pIndex) == size) {
158!
779
    *pIndex = 0;
158✔
780
    taosArrayClear(array);
158✔
781
  }
782
  code = blockDataUpdateTsWindow(pBlock, 0);
158✔
783
  QUERY_CHECK_CODE(code, lino, _end);
158!
784

785
_end:
158✔
786
  if (code != TSDB_CODE_SUCCESS) {
4,236!
787
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
788
  }
789
}
4,236✔
790

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

823
            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
226✔
824
            if (pFinalCh) {
226✔
825
              int32_t tmpRes = taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
25✔
826
              qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
25!
827
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
25✔
828
              STimeWindow     nextWin = getFinalTimeWindow(winRes.ts, pInterval);
25✔
829
              SPullWindowInfo pull = {.window = nextWin,
25✔
830
                                      .groupId = winRes.groupId,
25✔
831
                                      .calWin.skey = nextWin.skey,
25✔
832
                                      .calWin.ekey = nextWin.skey};
25✔
833
              // add pull data request
834
              qDebug("===stream===prepare final retrive for delete window:%" PRId64 ",groupId:%" PRId64 ", size:%d",
25!
835
                     winRes.ts, winRes.groupId, numOfCh);
836
              if (IS_MID_INTERVAL_OP(pOperator)) {
25!
837
                SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
×
838

839
                void* tmp = taosArrayPush(pInfo->pMidPullDatas, &winRes);
×
840
                if (!tmp) {
×
841
                  code = terrno;
×
842
                  QUERY_CHECK_CODE(code, lino, _end);
×
843
                }
844
              } else if (savePullWindow(&pull, pPullWins) == TSDB_CODE_SUCCESS) {
25!
845
                void* tmp = taosArrayPush(pInfo->pDelWins, &winRes);
25✔
846
                if (!tmp) {
25!
847
                  code = terrno;
×
848
                  QUERY_CHECK_CODE(code, lino, _end);
×
849
                }
850

851
                code = addPullWindow(pMap, &winRes, numOfCh);
25✔
852
                QUERY_CHECK_CODE(code, lino, _end);
25!
853

854
                if (pInfo->destHasPrimaryKey) {
25!
855
                  code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
856
                  QUERY_CHECK_CODE(code, lino, _end);
×
857
                }
858
                qDebug("===stream===prepare final retrive for delete %" PRId64 ", size:%d", winRes.ts, numOfCh);
25!
859
              }
860
            }
861
          }
862
        }
863
      }
864
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision, NULL);
750✔
865
    }
866
  }
867
  if (pBeOver) {
530✔
868
    *pBeOver = res;
12✔
869
  }
870

871
_end:
518✔
872
  if (code != TSDB_CODE_SUCCESS) {
530!
873
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
874
  }
875
  return code;
530✔
876
}
877

878
static int32_t addRetriveWindow(SArray* wins, SStreamIntervalOperatorInfo* pInfo, int32_t childId) {
204✔
879
  int32_t code = TSDB_CODE_SUCCESS;
204✔
880
  int32_t lino = 0;
204✔
881
  int32_t size = taosArrayGetSize(wins);
204✔
882
  for (int32_t i = 0; i < size; i++) {
403✔
883
    SWinKey*    winKey = taosArrayGet(wins, i);
199✔
884
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
199✔
885
    void*       chIds = taosHashGet(pInfo->pPullDataMap, winKey, sizeof(SWinKey));
199✔
886
    if (!chIds) {
199✔
887
      SPullWindowInfo pull = {
196✔
888
          .window = nextWin, .groupId = winKey->groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
196✔
889
      // add pull data request
890
      if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
196!
891
        code = addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
196✔
892
        QUERY_CHECK_CODE(code, lino, _end);
196!
893

894
        if (pInfo->destHasPrimaryKey) {
196!
895
          code = tSimpleHashPut(pInfo->pDeletedMap, winKey, sizeof(SWinKey), NULL, 0);
×
896
          QUERY_CHECK_CODE(code, lino, _end);
×
897
        }
898
        qDebug("===stream===prepare retrive for delete %" PRId64 ", size:%d", winKey->ts, pInfo->numOfChild);
196✔
899
      }
900
    } else {
901
      SArray* chArray = *(void**)chIds;
3✔
902
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
3✔
903
      qDebug("===stream===check final retrive %" PRId64 ",chid:%d", winKey->ts, index);
3!
904
      if (index == -1) {
3!
905
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
3!
906
        code = taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
3✔
907
        QUERY_CHECK_CODE(code, lino, _end);
3!
908
      }
909
    }
910
  }
911

912
_end:
204✔
913
  if (code != TSDB_CODE_SUCCESS) {
204!
914
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
915
  }
916
  return code;
204✔
917
}
918

919
static void clearFunctionContext(SExprSupp* pSup) {
2,294✔
920
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
24,856✔
921
    pSup->pCtx[i].saveHandle.currentPage = -1;
22,562✔
922
  }
923
}
2,294✔
924

925
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
8,432,128✔
926
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
8,432,128✔
927
}
928

929
void buildDataBlockFromGroupRes(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
107,382✔
930
                                SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
931
  int32_t         code = TSDB_CODE_SUCCESS;
107,382✔
932
  int32_t         lino = 0;
107,382✔
933
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
107,382✔
934
  SStorageAPI*    pAPI = &pOperator->pTaskInfo->storageAPI;
107,382✔
935
  SExprInfo*      pExprInfo = pSup->pExprInfo;
107,382✔
936
  int32_t         numOfExprs = pSup->numOfExprs;
107,382✔
937
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
107,382✔
938
  SqlFunctionCtx* pCtx = pSup->pCtx;
107,382✔
939

940
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
107,382✔
941

942
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
8,449,255✔
943
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
8,432,153✔
944
    SResultRow*  pRow = NULL;
8,432,141✔
945
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
8,432,141✔
946
    QUERY_CHECK_CODE(code, lino, _end);
8,432,124!
947
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
8,432,124✔
948
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
8,432,124✔
949
    // no results, continue to check the next one
950
    if (pRow->numOfRows == 0) {
8,432,066!
951
      pGroupResInfo->index += 1;
×
952
      continue;
×
953
    }
954
    if (pBlock->info.id.groupId == 0) {
8,432,066✔
955
      pBlock->info.id.groupId = groupId;
580,008✔
956
      void*   tbname = NULL;
580,008✔
957
      int32_t winCode = TSDB_CODE_SUCCESS;
580,008✔
958
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
580,008✔
959
                                                    false, &winCode);
960
      QUERY_CHECK_CODE(code, lino, _end);
580,199!
961
      if (winCode != TSDB_CODE_SUCCESS) {
580,199✔
962
        pBlock->info.parTbName[0] = 0;
574,060✔
963
      } else {
964
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
6,139✔
965
      }
966
      pAPI->stateStore.streamStateFreeVal(tbname);
580,199✔
967
    } else {
968
      // current value belongs to different group, it can't be packed into one datablock
969
      if (pBlock->info.id.groupId != groupId) {
7,852,058✔
970
        break;
89,953✔
971
      }
972
    }
973

974
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
8,343,501✔
975
      break;
1,194✔
976
    }
977
    pGroupResInfo->index += 1;
8,342,307✔
978

979
    for (int32_t j = 0; j < numOfExprs; ++j) {
67,889,525✔
980
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
59,547,652✔
981

982
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
59,547,652✔
983

984
      if (pCtx[j].fpSet.finalize) {
59,547,470✔
985
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
39,528,594✔
986
        if (TAOS_FAILED(tmpRes)) {
39,528,569!
987
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
988
          QUERY_CHECK_CODE(code, lino, _end);
×
989
        }
990
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
20,018,876✔
991
        // do nothing, todo refactor
992
      } else {
993
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
994
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
995
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
19,949,922✔
996
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
19,949,913✔
997
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
39,899,812✔
998
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
19,949,900✔
999
          QUERY_CHECK_CODE(code, lino, _end);
19,949,899!
1000
        }
1001
      }
1002
    }
1003

1004
    if (pSessionKeys) {
8,341,873!
1005
      SSessionKey key = {.groupId = groupId, .win = pRow->win};
×
1006
      for (int32_t j = 0; j < pRow->numOfRows; ++j) {
×
1007
        const void* px = taosArrayPush(pSessionKeys, &key);
×
1008
        QUERY_CHECK_NULL(px, code, lino, _end, terrno);
×
1009
      }
1010
    }
1011

1012
    pBlock->info.rows += pRow->numOfRows;
8,341,873✔
1013
  }
1014

1015
  pBlock->info.dataLoad = 1;
107,055✔
1016
  code = blockDataUpdateTsWindow(pBlock, 0);
107,055✔
1017
  QUERY_CHECK_CODE(code, lino, _end);
107,381!
1018

1019
_end:
107,381✔
1020
  if (code != TSDB_CODE_SUCCESS) {
107,381!
1021
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1022
  }
1023
}
107,381✔
1024

1025
void doBuildStreamIntervalResult(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock,
146,100✔
1026
                                 SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
1027
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
146,100✔
1028
  // set output datablock version
1029
  pBlock->info.version = pTaskInfo->version;
146,100✔
1030

1031
  blockDataCleanup(pBlock);
146,100✔
1032
  taosArrayClear(pSessionKeys);
146,098✔
1033
  if (!hasRemainResults(pGroupResInfo)) {
146,098✔
1034
    return;
38,716✔
1035
  }
1036

1037
  // clear the existed group id
1038
  pBlock->info.id.groupId = 0;
107,382✔
1039
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
107,382✔
1040
}
1041

1042
int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
241,993✔
1043
                                    TSKEY* primaryKeys, int32_t prevPosition) {
1044
  int32_t startPos = prevPosition + 1;
241,993✔
1045
  if (startPos == pDataBlockInfo->rows) {
241,993✔
1046
    startPos = -1;
2,546✔
1047
  } else {
1048
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
239,447✔
1049
  }
1050
  return startPos;
241,993✔
1051
}
1052

1053
static int32_t doStreamIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, uint64_t groupId,
1,127,984✔
1054
                                       SSHashObj* pUpdatedMap, SSHashObj* pDeletedMap) {
1055
  int32_t                      code = TSDB_CODE_SUCCESS;
1,127,984✔
1056
  int32_t                      lino = 0;
1,127,984✔
1057
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
1,127,984✔
1058
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
1,127,984✔
1059

1060
  SResultRowInfo* pResultRowInfo = &(pInfo->binfo.resultRowInfo);
1,127,984✔
1061
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
1,127,984✔
1062
  SExprSupp*      pSup = &pOperator->exprSupp;
1,127,984✔
1063
  int32_t         numOfOutput = pSup->numOfExprs;
1,127,984✔
1064
  int32_t         step = 1;
1,127,984✔
1065
  TSKEY*          tsCols = NULL;
1,127,984✔
1066
  SRowBuffPos*    pResPos = NULL;
1,127,984✔
1067
  SResultRow*     pResult = NULL;
1,127,984✔
1068
  int32_t         forwardRows = 0;
1,127,984✔
1069
  int32_t         endRowId = pSDataBlock->info.rows - 1;
1,127,984✔
1070

1071
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,127,984✔
1072
  tsCols = (int64_t*)pColDataInfo->pData;
1,127,985✔
1073

1074
  void*            pPkVal = NULL;
1,127,985✔
1075
  int32_t          pkLen = 0;
1,127,985✔
1076
  SColumnInfoData* pPkColDataInfo = NULL;
1,127,985✔
1077
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
1,127,985✔
1078
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
363,380✔
1079
  }
1080

1081
  if (pSDataBlock->info.window.skey != tsCols[0] || pSDataBlock->info.window.ekey != tsCols[endRowId]) {
1,127,985!
1082
    qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64 ",maxKey %" PRId64,
×
1083
           pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
1084
    code = blockDataUpdateTsWindow(pSDataBlock, pInfo->primaryTsIndex);
×
1085
    QUERY_CHECK_CODE(code, lino, _end);
×
1086

1087
    // timestamp of the data is incorrect
1088
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
1089
      qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
1090
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
1091
    }
1092
  }
1093

1094
  int32_t     startPos = 0;
1,127,986✔
1095
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
1,127,986✔
1096
  STimeWindow nextWin = {0};
1,127,986✔
1097
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,127,986✔
1098
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,496✔
1099
  } else {
1100
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
1,125,490✔
1101
  }
1102
  while (1) {
8,592,329✔
1103
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
9,720,306✔
1104
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
9,720,261!
1105
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1106
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1107
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1108
    }
1109

1110
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
9,721,376!
1111
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
1,134✔
1112
                          nextWin.ekey, pPkVal, pkLen)) ||
9,720,034✔
1113
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
9,720,219✔
1114
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
37✔
1115
      if (startPos < 0) {
42✔
1116
        break;
1,127,988✔
1117
      }
1118
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
19!
1119
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1120
      continue;
56✔
1121
    }
1122

1123
    if (IS_FINAL_INTERVAL_OP(pOperator) && pInfo->numOfChild > 0) {
9,720,020!
1124
      bool    ignore = true;
240,683✔
1125
      SWinKey winRes = {
240,683✔
1126
          .ts = nextWin.skey,
240,683✔
1127
          .groupId = groupId,
1128
      };
1129
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
240,683✔
1130
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore) && isClosed &&
240,683!
1131
          !chIds) {
×
1132
        SPullWindowInfo pull = {
×
1133
            .window = nextWin, .groupId = groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
×
1134
        // add pull data request
1135
        if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
×
1136
          code = addPullWindow(pInfo->pPullDataMap, &winRes, pInfo->numOfChild);
×
1137
          QUERY_CHECK_CODE(code, lino, _end);
×
1138

1139
          if (pInfo->destHasPrimaryKey) {
×
1140
            code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
1141
            QUERY_CHECK_CODE(code, lino, _end);
×
1142
          }
1143
        }
1144
      } else {
1145
        int32_t index = -1;
240,683✔
1146
        SArray* chArray = NULL;
240,683✔
1147
        int32_t chId = 0;
240,683✔
1148
        if (chIds) {
240,683✔
1149
          chArray = *(void**)chIds;
343✔
1150
          chId = getChildIndex(pSDataBlock);
343✔
1151
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
343✔
1152
        }
1153
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
240,683✔
1154
          ignore = false;
240,553✔
1155
        }
1156
      }
1157

1158
      if (ignore) {
240,683✔
1159
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
130✔
1160
        if (startPos < 0) {
130✔
1161
          break;
93✔
1162
        }
1163
        continue;
37✔
1164
      }
1165
    }
1166

1167
    int32_t winCode = TSDB_CODE_SUCCESS;
9,719,890✔
1168
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
9,719,890✔
1169
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1170
    QUERY_CHECK_CODE(code, lino, _end);
9,718,187!
1171

1172
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator) &&
9,718,187✔
1173
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
8,836,622!
1174
      SSessionKey key = {.win = nextWin, .groupId = groupId};
×
1175
      code = addIntervalAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &key, &pInfo->basic.notifyEventSup,
×
1176
                                       pTaskInfo->streamInfo.pNotifyEventStat);
1177
      QUERY_CHECK_CODE(code, lino, _end);
×
1178
    }
1179

1180
    pResult = (SResultRow*)pResPos->pRowBuff;
9,718,187✔
1181

1182
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,718,187✔
1183
      forwardRows = 1;
240,553✔
1184
    } else {
1185
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
9,477,634✔
1186
                                             NULL, TSDB_ORDER_ASC);
1187
    }
1188

1189
    SWinKey key = {
9,721,245✔
1190
        .ts = pResult->win.skey,
9,721,245✔
1191
        .groupId = groupId,
1192
    };
1193

1194
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
9,721,245!
1195
      code = tSimpleHashPut(pDeletedMap, &key, sizeof(SWinKey), NULL, 0);
6✔
1196
      QUERY_CHECK_CODE(code, lino, _end);
6!
1197
    }
1198

1199
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
9,721,245!
1200
      code = saveWinResult(&key, pResPos, pUpdatedMap);
9,711,440✔
1201
      QUERY_CHECK_CODE(code, lino, _end);
9,711,253!
1202
    }
1203

1204
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
9,721,058✔
1205
      pResPos->beUpdated = true;
8,529✔
1206
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
8,529✔
1207
      QUERY_CHECK_CODE(code, lino, _end);
8,529!
1208
    }
1209

1210
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
9,721,058✔
1211
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
9,719,403✔
1212
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
9,719,403✔
1213
    QUERY_CHECK_CODE(code, lino, _end);
9,721,273!
1214
    key.ts = nextWin.skey;
9,721,273✔
1215

1216
    if (pInfo->delKey.ts > key.ts) {
9,721,273✔
1217
      pInfo->delKey = key;
2,066✔
1218
    }
1219
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
9,721,273✔
1220
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,721,273✔
1221
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
240,553✔
1222
    } else {
1223
      startPos =
1224
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
9,480,720✔
1225
    }
1226
    if (startPos < 0) {
9,720,145✔
1227
      break;
1,127,872✔
1228
    }
1229
  }
1230
_end:
1,127,988✔
1231
  if (code != TSDB_CODE_SUCCESS) {
1,127,988!
1232
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1233
  }
1234
  return code;
1,127,986✔
1235
}
1236

1237
int winPosCmprImpl(const void* pKey1, const void* pKey2) {
130,769,038✔
1238
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
130,769,038✔
1239
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
130,769,038✔
1240
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
130,769,038✔
1241
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
130,769,038✔
1242

1243
  if (pWin1->groupId > pWin2->groupId) {
130,769,038✔
1244
    return 1;
22,637,590✔
1245
  } else if (pWin1->groupId < pWin2->groupId) {
108,131,448✔
1246
    return -1;
21,281,150✔
1247
  }
1248

1249
  if (pWin1->ts > pWin2->ts) {
86,850,298✔
1250
    return 1;
43,733,288✔
1251
  } else if (pWin1->ts < pWin2->ts) {
43,117,010✔
1252
    return -1;
43,117,006✔
1253
  }
1254

1255
  return 0;
4✔
1256
}
1257

1258
static void resetUnCloseWinInfo(SSHashObj* winMap) {
261✔
1259
  void*   pIte = NULL;
261✔
1260
  int32_t iter = 0;
261✔
1261
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
583✔
1262
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
322✔
1263
    pPos->beUsed = true;
322✔
1264
  }
1265
}
261✔
1266

1267
int32_t encodeSWinKey(void** buf, SWinKey* key) {
34✔
1268
  int32_t tlen = 0;
34✔
1269
  tlen += taosEncodeFixedI64(buf, key->ts);
34✔
1270
  tlen += taosEncodeFixedU64(buf, key->groupId);
34✔
1271
  return tlen;
34✔
1272
}
1273

1274
void* decodeSWinKey(void* buf, SWinKey* key) {
2✔
1275
  buf = taosDecodeFixedI64(buf, &key->ts);
2!
1276
  buf = taosDecodeFixedU64(buf, &key->groupId);
2!
1277
  return buf;
2✔
1278
}
1279

1280
int32_t encodeSTimeWindowAggSupp(void** buf, STimeWindowAggSupp* pTwAggSup) {
216✔
1281
  int32_t tlen = 0;
216✔
1282
  tlen += taosEncodeFixedI64(buf, pTwAggSup->minTs);
216✔
1283
  tlen += taosEncodeFixedI64(buf, pTwAggSup->maxTs);
216✔
1284
  return tlen;
216✔
1285
}
1286

1287
void* decodeSTimeWindowAggSupp(void* buf, STimeWindowAggSupp* pTwAggSup) {
46✔
1288
  buf = taosDecodeFixedI64(buf, &pTwAggSup->minTs);
46!
1289
  buf = taosDecodeFixedI64(buf, &pTwAggSup->maxTs);
46!
1290
  return buf;
46✔
1291
}
1292

1293
int32_t encodeSTimeWindow(void** buf, STimeWindow* pWin) {
16✔
1294
  int32_t tlen = 0;
16✔
1295
  tlen += taosEncodeFixedI64(buf, pWin->skey);
16✔
1296
  tlen += taosEncodeFixedI64(buf, pWin->ekey);
16✔
1297
  return tlen;
16✔
1298
}
1299

1300
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
2✔
1301
  buf = taosDecodeFixedI64(buf, &pWin->skey);
2!
1302
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
2!
1303
  return buf;
2✔
1304
}
1305

1306
int32_t encodeSPullWindowInfo(void** buf, SPullWindowInfo* pPullInfo) {
×
1307
  int32_t tlen = 0;
×
1308
  tlen += encodeSTimeWindow(buf, &pPullInfo->calWin);
×
1309
  tlen += taosEncodeFixedU64(buf, pPullInfo->groupId);
×
1310
  tlen += encodeSTimeWindow(buf, &pPullInfo->window);
×
1311
  return tlen;
×
1312
}
1313

1314
void* decodeSPullWindowInfo(void* buf, SPullWindowInfo* pPullInfo) {
×
1315
  buf = decodeSTimeWindow(buf, &pPullInfo->calWin);
×
1316
  buf = taosDecodeFixedU64(buf, &pPullInfo->groupId);
×
1317
  buf = decodeSTimeWindow(buf, &pPullInfo->window);
×
1318
  return buf;
×
1319
}
1320

1321
int32_t encodeSPullWindowInfoArray(void** buf, SArray* pPullInfos) {
84✔
1322
  int32_t tlen = 0;
84✔
1323
  int32_t size = taosArrayGetSize(pPullInfos);
84✔
1324
  tlen += taosEncodeFixedI32(buf, size);
84✔
1325
  for (int32_t i = 0; i < size; i++) {
84!
1326
    void* pItem = taosArrayGet(pPullInfos, i);
×
1327
    tlen += encodeSPullWindowInfo(buf, pItem);
×
1328
  }
1329
  return tlen;
84✔
1330
}
1331

1332
int32_t decodeSPullWindowInfoArray(void* buf, SArray* pPullInfos, void** ppBuf) {
20✔
1333
  int32_t code = TSDB_CODE_SUCCESS;
20✔
1334
  int32_t lino = 0;
20✔
1335
  int32_t size = 0;
20!
1336
  buf = taosDecodeFixedI32(buf, &size);
20✔
1337
  for (int32_t i = 0; i < size; i++) {
20!
1338
    SPullWindowInfo item = {0};
×
1339
    buf = decodeSPullWindowInfo(buf, &item);
×
1340
    void* tmp = taosArrayPush(pPullInfos, &item);
×
1341
    if (!tmp) {
×
1342
      code = terrno;
×
1343
      QUERY_CHECK_CODE(code, lino, _end);
×
1344
    }
1345
  }
1346
  (*ppBuf) = buf;
20✔
1347

1348
_end:
20✔
1349
  if (code != TSDB_CODE_SUCCESS) {
20!
1350
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1351
  }
1352
  return code;
20✔
1353
}
1354

1355
int32_t doStreamIntervalEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator) {
84✔
1356
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
84✔
1357
  if (!pInfo) {
84!
1358
    return 0;
×
1359
  }
1360

1361
  void* pData = (buf == NULL) ? NULL : *buf;
84✔
1362

1363
  // 1.pResultRowHashTable
1364
  int32_t tlen = 0;
84✔
1365
  int32_t mapSize = tSimpleHashGetSize(pInfo->aggSup.pResultRowHashTable);
84✔
1366
  tlen += taosEncodeFixedI32(buf, mapSize);
84✔
1367
  void*   pIte = NULL;
84✔
1368
  size_t  keyLen = 0;
84✔
1369
  int32_t iter = 0;
84✔
1370
  while ((pIte = tSimpleHashIterate(pInfo->aggSup.pResultRowHashTable, pIte, &iter)) != NULL) {
118✔
1371
    void* key = tSimpleHashGetKey(pIte, &keyLen);
34✔
1372
    tlen += encodeSWinKey(buf, key);
34✔
1373
  }
1374

1375
  // 2.twAggSup
1376
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
84✔
1377

1378
  // 3.pPullDataMap
1379
  int32_t size = taosHashGetSize(pInfo->pPullDataMap);
84✔
1380
  tlen += taosEncodeFixedI32(buf, size);
84✔
1381
  pIte = NULL;
84✔
1382
  keyLen = 0;
84✔
1383
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
84!
1384
    void* key = taosHashGetKey(pIte, &keyLen);
×
1385
    tlen += encodeSWinKey(buf, key);
×
1386
    SArray* pArray = *(SArray**)pIte;
×
1387
    int32_t chSize = taosArrayGetSize(pArray);
×
1388
    tlen += taosEncodeFixedI32(buf, chSize);
×
1389
    for (int32_t i = 0; i < chSize; i++) {
×
1390
      void* pChItem = taosArrayGet(pArray, i);
×
1391
      tlen += taosEncodeFixedI32(buf, *(int32_t*)pChItem);
×
1392
    }
1393
  }
1394

1395
  // 4.pPullWins
1396
  tlen += encodeSPullWindowInfoArray(buf, pInfo->pPullWins);
84✔
1397

1398
  // 5.dataVersion
1399
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
84✔
1400

1401
  // 6.basicInfo
1402
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
84✔
1403

1404
  // 7.checksum
1405
  if (buf) {
84✔
1406
    uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
84!
1407
    tlen += taosEncodeFixedU32(buf, cksum);
42✔
1408
  } else {
1409
    tlen += sizeof(uint32_t);
42✔
1410
  }
1411

1412
  return tlen;
84✔
1413
}
1414

1415
void doStreamIntervalDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator) {
20✔
1416
  int32_t                      code = TSDB_CODE_SUCCESS;
20✔
1417
  int32_t                      lino = 0;
20✔
1418
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
20✔
1419
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
20✔
1420
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
20✔
1421
  if (!pInfo) {
20!
1422
    code = TSDB_CODE_FAILED;
×
1423
    QUERY_CHECK_CODE(code, lino, _end);
×
1424
  }
1425

1426
  // 7.checksum
1427
  int32_t dataLen = len - sizeof(uint32_t);
20✔
1428
  void*   pCksum = POINTER_SHIFT(buf, dataLen);
20✔
1429
  if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
40!
1430
    code = TSDB_CODE_FAILED;
×
1431
    QUERY_CHECK_CODE(code, lino, _end);
×
1432
  }
1433
  pDataEnd = pCksum;
20✔
1434

1435
  // 1.pResultRowHashTable
1436
  int32_t mapSize = 0;
20✔
1437
  buf = taosDecodeFixedI32(buf, &mapSize);
20!
1438
  for (int32_t i = 0; i < mapSize; i++) {
22✔
1439
    SWinKey key = {0};
2✔
1440
    buf = decodeSWinKey(buf, &key);
2✔
1441
    SRowBuffPos* pPos = NULL;
2✔
1442
    int32_t      resSize = pInfo->aggSup.resultRowSize;
2✔
1443
    int32_t      winCode = TSDB_CODE_SUCCESS;
2✔
1444
    code = pInfo->stateStore.streamStateAddIfNotExist(pInfo->pState, &key, (void**)&pPos, &resSize, &winCode);
2✔
1445
    QUERY_CHECK_CODE(code, lino, _end);
2!
1446
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
2!
1447

1448
    code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pPos, POINTER_BYTES);
2✔
1449
    QUERY_CHECK_CODE(code, lino, _end);
2!
1450
  }
1451

1452
  // 2.twAggSup
1453
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
20✔
1454

1455
  // 3.pPullDataMap
1456
  int32_t size = 0;
20✔
1457
  buf = taosDecodeFixedI32(buf, &size);
20!
1458
  for (int32_t i = 0; i < size; i++) {
20!
1459
    SWinKey key = {0};
×
1460
    SArray* pArray = taosArrayInit(0, sizeof(int32_t));
×
1461
    if (!pArray) {
×
1462
      code = terrno;
×
1463
      QUERY_CHECK_CODE(code, lino, _end);
×
1464
    }
1465

1466
    buf = decodeSWinKey(buf, &key);
×
1467
    int32_t chSize = 0;
×
1468
    buf = taosDecodeFixedI32(buf, &chSize);
×
1469
    for (int32_t i = 0; i < chSize; i++) {
×
1470
      int32_t chId = 0;
×
1471
      buf = taosDecodeFixedI32(buf, &chId);
×
1472
      void* tmp = taosArrayPush(pArray, &chId);
×
1473
      if (!tmp) {
×
1474
        code = terrno;
×
1475
        QUERY_CHECK_CODE(code, lino, _end);
×
1476
      }
1477
    }
1478
    code = taosHashPut(pInfo->pPullDataMap, &key, sizeof(SWinKey), &pArray, POINTER_BYTES);
×
1479
    QUERY_CHECK_CODE(code, lino, _end);
×
1480
  }
1481

1482
  // 4.pPullWins
1483
  code = decodeSPullWindowInfoArray(buf, pInfo->pPullWins, &buf);
20✔
1484
  QUERY_CHECK_CODE(code, lino, _end);
20!
1485

1486
  // 5.dataVersion
1487
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
20!
1488

1489
  // 6.basicInfo
1490
  if (buf < pDataEnd) {
20!
1491
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
20✔
1492
    QUERY_CHECK_CODE(code, lino, _end);
20!
1493
  }
1494

1495
_end:
20✔
1496
  if (code != TSDB_CODE_SUCCESS) {
20!
1497
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1498
  }
1499
}
20✔
1500

1501
void doStreamIntervalSaveCheckpoint(SOperatorInfo* pOperator) {
2,095✔
1502
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,095✔
1503
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
2,095✔
1504
    int32_t len = doStreamIntervalEncodeOpState(NULL, 0, pOperator);
42✔
1505
    void*   buf = taosMemoryCalloc(1, len);
42!
1506
    if (!buf) {
42!
1507
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1508
      return;
×
1509
    }
1510
    void* pBuf = buf;
42✔
1511
    len = doStreamIntervalEncodeOpState(&pBuf, len, pOperator);
42✔
1512
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
42✔
1513
                                          strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), buf, len);
1514
    taosMemoryFree(buf);
42!
1515
    saveStreamOperatorStateComplete(&pInfo->basic);
42✔
1516
  }
1517
}
1518

1519
int32_t copyIntervalDeleteKey(SSHashObj* pMap, SArray* pWins) {
62✔
1520
  int32_t code = TSDB_CODE_SUCCESS;
62✔
1521
  int32_t lino = 0;
62✔
1522
  void*   pIte = NULL;
62✔
1523
  int32_t iter = 0;
62✔
1524
  while ((pIte = tSimpleHashIterate(pMap, pIte, &iter)) != NULL) {
83✔
1525
    void* pKey = tSimpleHashGetKey(pIte, NULL);
21✔
1526
    void* tmp = taosArrayPush(pWins, pKey);
21✔
1527
    if (!tmp) {
21!
1528
      code = terrno;
×
1529
      QUERY_CHECK_CODE(code, lino, _end);
×
1530
    }
1531
  }
1532
  tSimpleHashClear(pMap);
62✔
1533

1534
_end:
62✔
1535
  if (code != TSDB_CODE_SUCCESS) {
62!
1536
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1537
  }
1538
  return code;
62✔
1539
}
1540

1541
static int32_t buildIntervalResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
144,774✔
1542
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
144,774✔
1543
  int32_t                      code = TSDB_CODE_SUCCESS;
144,774✔
1544
  int32_t                      lino = 0;
144,774✔
1545
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
144,774✔
1546
  uint16_t                     opType = pOperator->operatorType;
144,774✔
1547
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
144,774✔
1548
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
144,774✔
1549
  bool                         addNotifyEvent = false;
144,774✔
1550

1551
  // check if query task is closed or not
1552
  if (isTaskKilled(pTaskInfo)) {
144,774✔
1553
    (*ppRes) = NULL;
2✔
1554
    return code;
2✔
1555
  }
1556

1557
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
276,343✔
1558
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
131,572!
1559
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
144,771✔
1560
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
4,177✔
1561
    if (pInfo->pPullDataRes->info.rows != 0) {
4,177✔
1562
      // process the rest of the data
1563
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
158✔
1564
      (*ppRes) = pInfo->pPullDataRes;
158✔
1565
      return code;
158✔
1566
    }
1567
  }
1568

1569
  doBuildDeleteResult(pTaskInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
144,613✔
1570
  if (pInfo->pDelRes->info.rows != 0) {
144,612✔
1571
    // process the rest of the data
1572
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
516✔
1573
    if (addNotifyEvent) {
516!
1574
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
1575
      QUERY_CHECK_CODE(code, lino, _end);
×
1576
    }
1577
    (*ppRes) = pInfo->pDelRes;
516✔
1578
    return code;
516✔
1579
  }
1580

1581
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo,
144,096!
1582
                              addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
1583
  if (pInfo->binfo.pRes->info.rows != 0) {
144,095✔
1584
    printDataBlock(pInfo->binfo.pRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
107,141✔
1585
    if (addNotifyEvent) {
107,141!
1586
      code = addAggResultNotifyEvent(pInfo->binfo.pRes, pNotifySup->pSessionKeys,
×
1587
                                     pTaskInfo->streamInfo.notifyResultSchema, pNotifySup, pNotifyEventStat);
×
1588
      QUERY_CHECK_CODE(code, lino, _end);
×
1589
    }
1590
    (*ppRes) = pInfo->binfo.pRes;
107,141✔
1591
    return code;
107,141✔
1592
  }
1593

1594
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
36,954✔
1595
  QUERY_CHECK_CODE(code, lino, _end);
36,958!
1596
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
36,958!
1597
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1598
    (*ppRes) = pNotifySup->pEventBlock;
×
1599
    return code;
×
1600
  }
1601

1602
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
36,958✔
1603
  QUERY_CHECK_CODE(code, lino, _end);
36,958!
1604

1605
_end:
36,958✔
1606
  if (code != TSDB_CODE_SUCCESS) {
36,958!
1607
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1608
  }
1609
  (*ppRes) = NULL;
36,958✔
1610
  return code;
36,958✔
1611
}
1612

1613
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
19,051✔
1614
  int32_t code = TSDB_CODE_SUCCESS;
19,051✔
1615
  int32_t lino = 0;
19,051✔
1616
  void*   pIte = NULL;
19,051✔
1617
  int32_t iter = 0;
19,051✔
1618
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
507,155✔
1619
    void* tmp = taosArrayPush(pUpdated, pIte);
488,104✔
1620
    if (!tmp) {
488,104!
1621
      code = terrno;
×
1622
      QUERY_CHECK_CODE(code, lino, _end);
×
1623
    }
1624
  }
1625
  taosArraySort(pUpdated, compar);
19,056✔
1626
  tSimpleHashCleanup(*ppWinUpdated);
19,051✔
1627
  *ppWinUpdated = NULL;
19,054✔
1628

1629
_end:
19,054✔
1630
  if (code != TSDB_CODE_SUCCESS) {
19,054!
1631
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1632
  }
1633
  return code;
19,056✔
1634
}
1635

1636
static int32_t doStreamFinalIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
14,183✔
1637
  int32_t                      code = TSDB_CODE_SUCCESS;
14,183✔
1638
  int32_t                      lino = 0;
14,183✔
1639
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
14,183✔
1640
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
14,183✔
1641
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
14,183✔
1642

1643
  SOperatorInfo* downstream = pOperator->pDownstream[0];
14,183✔
1644
  SExprSupp*     pSup = &pOperator->exprSupp;
14,183✔
1645

1646
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
14,183✔
1647

1648
  if (pOperator->status == OP_EXEC_DONE) {
14,183!
1649
    (*ppRes) = NULL;
×
1650
    return code;
×
1651
  } else if (pOperator->status == OP_RES_TO_RETURN) {
14,183✔
1652
    SSDataBlock* resBlock = NULL;
4,923✔
1653
    code = buildIntervalResult(pOperator, &resBlock);
4,923✔
1654
    QUERY_CHECK_CODE(code, lino, _end);
4,921!
1655
    if (resBlock != NULL) {
4,921✔
1656
      (*ppRes) = resBlock;
1,771✔
1657
      return code;
4,922✔
1658
    }
1659

1660
    if (pInfo->recvGetAll) {
3,150✔
1661
      pInfo->recvGetAll = false;
83✔
1662
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
83✔
1663
    }
1664

1665
    if (pInfo->reCkBlock) {
3,151!
1666
      pInfo->reCkBlock = false;
×
1667
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1668
      (*ppRes) = pInfo->pCheckpointRes;
×
1669
      return code;
×
1670
    }
1671

1672
    setStreamOperatorCompleted(pOperator);
3,151✔
1673
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
3,151✔
1674
      clearFunctionContext(&pOperator->exprSupp);
1,717✔
1675
      // semi interval operator clear disk buffer
1676
      clearStreamIntervalOperator(pInfo);
1,717✔
1677
      qDebug("===stream===clear semi operator");
1,717✔
1678
    }
1679
    (*ppRes) = NULL;
3,151✔
1680
    return code;
3,151✔
1681
  } else {
1682
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
9,260✔
1683
      SSDataBlock* resBlock = NULL;
6,045✔
1684
      code = buildIntervalResult(pOperator, &resBlock);
6,045✔
1685
      QUERY_CHECK_CODE(code, lino, _end);
6,049!
1686
      if (resBlock != NULL) {
6,049!
1687
        (*ppRes) = resBlock;
×
1688
        return code;
×
1689
      }
1690

1691
      if (pInfo->recvRetrive) {
6,049!
1692
        pInfo->recvRetrive = false;
×
1693
        printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1694
        (*ppRes) = pInfo->pMidRetriveRes;
×
1695
        return code;
×
1696
      }
1697
    }
1698
  }
1699

1700
  if (!pInfo->pUpdated) {
9,264✔
1701
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
6,247✔
1702
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
6,248!
1703
  }
1704
  if (!pInfo->pUpdatedMap) {
9,265✔
1705
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
6,248✔
1706
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
6,248✔
1707
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
6,247!
1708
  }
1709

1710
  while (1) {
20,732✔
1711
    if (isTaskKilled(pTaskInfo)) {
29,996✔
1712
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
2!
1713
      (*ppRes) = NULL;
2✔
1714
      return code;
3,016✔
1715
    }
1716

1717
    SSDataBlock* pBlock = NULL;
29,994✔
1718
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
29,994✔
1719
    QUERY_CHECK_CODE(code, lino, _end);
29,988!
1720

1721
    if (pBlock == NULL) {
29,988✔
1722
      pOperator->status = OP_RES_TO_RETURN;
5,722✔
1723
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
5,722✔
1724
             pInfo->numOfDatapack);
1725
      pInfo->numOfDatapack = 0;
5,722✔
1726
      break;
5,722✔
1727
    }
1728

1729
    pInfo->numOfDatapack++;
24,266✔
1730
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
24,266✔
1731
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
24,266✔
1732

1733
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
24,269✔
1734
      pInfo->binfo.pRes->info.type = pBlock->info.type;
17,933✔
1735
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
6,336✔
1736
               pBlock->info.type == STREAM_CLEAR) {
6,104✔
1737
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
408✔
1738
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
408!
1739
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
408✔
1740
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
408✔
1741
      QUERY_CHECK_CODE(code, lino, _end);
408!
1742

1743
      if (IS_FINAL_INTERVAL_OP(pOperator)) {
408✔
1744
        int32_t chId = getChildIndex(pBlock);
204✔
1745
        code = addRetriveWindow(delWins, pInfo, chId);
204✔
1746
        QUERY_CHECK_CODE(code, lino, _end);
204!
1747

1748
        if (pBlock->info.type != STREAM_CLEAR) {
204✔
1749
          void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
116✔
1750
          if (!tmp && taosArrayGetSize(delWins) > 0) {
116!
1751
            code = TSDB_CODE_OUT_OF_MEMORY;
×
1752
            QUERY_CHECK_CODE(code, lino, _end);
×
1753
          }
1754
        }
1755
        taosArrayDestroy(delWins);
204✔
1756
        continue;
2,056✔
1757
      }
1758
      removeResults(delWins, pInfo->pUpdatedMap);
204✔
1759
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
204✔
1760
      if (!tmp && taosArrayGetSize(delWins) > 0) {
203!
1761
        code = TSDB_CODE_OUT_OF_MEMORY;
×
1762
        QUERY_CHECK_CODE(code, lino, _end);
×
1763
      }
1764
      taosArrayDestroy(delWins);
203✔
1765

1766
      doBuildDeleteResult(pTaskInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
204✔
1767
      if (pInfo->pDelRes->info.rows != 0) {
204!
1768
        // process the rest of the data
1769
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
204✔
1770
        if (pBlock->info.type == STREAM_CLEAR) {
204✔
1771
          pInfo->pDelRes->info.type = STREAM_CLEAR;
88✔
1772
        } else {
1773
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
116✔
1774
        }
1775
        (*ppRes) = pInfo->pDelRes;
204✔
1776
        return code;
204✔
1777
      }
1778

1779
      break;
×
1780
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
5,928!
1781
      pInfo->recvGetAll = true;
83✔
1782
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
83✔
1783
      QUERY_CHECK_CODE(code, lino, _end);
83!
1784
      continue;
83✔
1785
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
5,845✔
1786
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
523!
1787
        pInfo->recvRetrive = true;
523✔
1788
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
523✔
1789
        QUERY_CHECK_CODE(code, lino, _end);
524!
1790

1791
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
524✔
1792
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
524✔
1793
        QUERY_CHECK_CODE(code, lino, _end);
524!
1794
        break;
524✔
1795
      }
1796
      continue;
×
1797
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
5,322!
1798
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
518✔
1799
                             pInfo->numOfChild, pOperator, NULL);
1800
      QUERY_CHECK_CODE(code, lino, _end);
518!
1801
      continue;
518✔
1802
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
4,804✔
1803
      (*ppRes) = pBlock;
2,810✔
1804
      return code;
2,810✔
1805
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,994✔
1806
      pAPI->stateStore.streamStateCommit(pInfo->pState);
727✔
1807
      doStreamIntervalSaveCheckpoint(pOperator);
727✔
1808
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
727✔
1809
      QUERY_CHECK_CODE(code, lino, _end);
727!
1810

1811
      continue;
727✔
1812
    } else if (IS_FINAL_INTERVAL_OP(pOperator) && pBlock->info.type == STREAM_MID_RETRIEVE) {
1,267✔
1813
      continue;
524✔
1814
    } else {
1815
      if (pBlock->info.type != STREAM_INVALID) {
743!
1816
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1817
        QUERY_CHECK_CODE(code, lino, _end);
×
1818
      }
1819
    }
1820

1821
    if (pInfo->scalarSupp.pExprInfo != NULL) {
18,676!
1822
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
1823
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
1824
      QUERY_CHECK_CODE(code, lino, _end);
×
1825
    }
1826
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
18,676✔
1827
    QUERY_CHECK_CODE(code, lino, _end);
18,678!
1828

1829
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
18,678✔
1830
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
18,676!
1831
      code = TSDB_CODE_SUCCESS;
×
1832
      pOperator->status = OP_RES_TO_RETURN;
×
1833
      break;
×
1834
    }
1835
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
18,676✔
1836
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
18,676✔
1837
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
18,676✔
1838
  }
1839

1840
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
6,246✔
1841
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,807✔
1842
  }
1843
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
6,246✔
1844
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,809✔
1845
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1846
    QUERY_CHECK_CODE(code, lino, _end);
1,809!
1847

1848
    if (pInfo->destHasPrimaryKey) {
1,809✔
1849
      code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
2✔
1850
      QUERY_CHECK_CODE(code, lino, _end);
2!
1851
    }
1852
  }
1853
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
6,246✔
1854

1855
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
6,246✔
1856
  QUERY_CHECK_CODE(code, lino, _end);
6,246!
1857

1858
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
6,246✔
1859
  pInfo->pUpdated = NULL;
6,246✔
1860
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
6,246✔
1861
  QUERY_CHECK_CODE(code, lino, _end);
6,246!
1862

1863
  SSDataBlock* resBlock = NULL;
6,246✔
1864
  code = buildIntervalResult(pOperator, &resBlock);
6,246✔
1865
  QUERY_CHECK_CODE(code, lino, _end);
6,246!
1866
  if (resBlock != NULL) {
6,246✔
1867
    (*ppRes) = resBlock;
3,151✔
1868
    return code;
3,151✔
1869
  }
1870

1871
  if (pInfo->recvRetrive) {
3,095✔
1872
    pInfo->recvRetrive = false;
524✔
1873
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
524✔
1874
    (*ppRes) = pInfo->pMidRetriveRes;
524✔
1875
    return code;
524✔
1876
  }
1877

1878
_end:
2,571✔
1879
  if (code != TSDB_CODE_SUCCESS) {
2,571!
1880
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1881
    pTaskInfo->code = code;
×
1882
    T_LONG_JMP(pTaskInfo->env, code);
×
1883
  }
1884
  setStreamOperatorCompleted(pOperator);
2,571✔
1885
  (*ppRes) = NULL;
2,571✔
1886
  return code;
2,571✔
1887
}
1888

1889
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
5,860✔
1890
  if (pWinPhyNode->deleteMark <= 0) {
5,860✔
1891
    return DEAULT_DELETE_MARK;
3,919✔
1892
  }
1893
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
1,941✔
1894
  deleteMark = TMAX(deleteMark, interval);
1,941✔
1895
  return deleteMark;
1,941✔
1896
}
1897

1898
int64_t getDeleteMarkFromOption(SStreamNodeOption* pOption) {
220✔
1899
  if (pOption->deleteMark <= 0) {
220!
1900
    return DEAULT_DELETE_MARK;
221✔
1901
  }
1902
  int64_t deleteMark = TMAX(pOption->deleteMark, pOption->watermark);
×
1903
  return deleteMark;
×
1904
}
1905

1906
TSKEY compareTs(void* pKey) {
31,711,187✔
1907
  SWinKey* pWinKey = (SWinKey*)pKey;
31,711,187✔
1908
  return pWinKey->ts;
31,711,187✔
1909
}
1910

1911
static int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
226,865✔
1912
  if (pCtx->subsidiaries.rowLen == 0) {
226,865!
1913
    int32_t rowLen = 0;
226,868✔
1914
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
227,267✔
1915
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
399✔
1916
      rowLen += pc->pExpr->base.resSchema.bytes;
399✔
1917
    }
1918

1919
    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
226,868✔
1920
  } else {
1921
    return pCtx->subsidiaries.rowLen;
×
1922
  }
1923
}
1924

1925
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
6,083✔
1926
  int32_t size = 0;
6,083✔
1927
  for (int32_t i = 0; i < numOfCols; ++i) {
232,949✔
1928
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
226,864✔
1929
    size = TMAX(size, resSize);
226,866✔
1930
  }
1931
  return size;
6,085✔
1932
}
1933

1934
static void streamIntervalReleaseState(SOperatorInfo* pOperator) {
1,283✔
1935
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,283✔
1936
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,152✔
1937
    SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,142✔
1938
    int32_t                      resSize = sizeof(TSKEY);
1,142✔
1939
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,142✔
1940
                                          strlen(STREAM_INTERVAL_OP_STATE_NAME), &pInfo->twAggSup.maxTs, resSize);
1,142✔
1941
  }
1942
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,283✔
1943
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
1,283✔
1944
  pAPI->stateStore.streamStateCommit(pInfo->pState);
1,283✔
1945
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,283✔
1946
  if (downstream->fpSet.releaseStreamStateFn) {
1,283!
1947
    downstream->fpSet.releaseStreamStateFn(downstream);
1,283✔
1948
  }
1949
}
1,283✔
1950

1951
void streamIntervalReloadState(SOperatorInfo* pOperator) {
1,283✔
1952
  int32_t                      code = TSDB_CODE_SUCCESS;
1,283✔
1953
  int32_t                      lino = 0;
1,283✔
1954
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,283✔
1955
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1,283✔
1956
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,283✔
1957
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,152✔
1958
    int32_t size = 0;
1,142✔
1959
    void*   pBuf = NULL;
1,142✔
1960
    code = pInfo->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,142✔
1961
                                                strlen(STREAM_INTERVAL_OP_STATE_NAME), &pBuf, &size);
1962
    QUERY_CHECK_CODE(code, lino, _end);
1,142!
1963

1964
    TSKEY ts = *(TSKEY*)pBuf;
1,142✔
1965
    taosMemoryFree(pBuf);
1,142!
1966
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
1,142✔
1967
    pInfo->stateStore.streamStateReloadInfo(pInfo->pState, ts);
1,142✔
1968
  }
1969
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,283✔
1970
  if (downstream->fpSet.reloadStreamStateFn) {
1,283!
1971
    downstream->fpSet.reloadStreamStateFn(downstream);
1,283✔
1972
  }
1973
  reloadFromDownStream(downstream, pInfo);
1,283✔
1974

1975
_end:
1,283✔
1976
  if (code != TSDB_CODE_SUCCESS) {
1,283!
1977
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1978
  }
1979
}
1,283✔
1980

1981
int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
873✔
1982
                                              int32_t numOfChild, SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
1983
  QRY_PARAM_CHECK(pOptrInfo);
873!
1984

1985
  int32_t                      code = TSDB_CODE_SUCCESS;
873✔
1986
  int32_t                      lino = 0;
873✔
1987
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
873✔
1988
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
873!
1989
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
873!
1990
  if (pInfo == NULL || pOperator == NULL) {
873!
1991
    code = terrno;
×
1992
    QUERY_CHECK_CODE(code, lino, _error);
×
1993
  }
1994

1995
  pOperator->exprSupp.hasWindowOrGroup = true;
873✔
1996
  pOperator->pTaskInfo = pTaskInfo;
873✔
1997
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
873✔
1998

1999
  pInfo->interval = (SInterval){.interval = pIntervalPhyNode->interval,
873✔
2000
                                .sliding = pIntervalPhyNode->sliding,
873✔
2001
                                .intervalUnit = pIntervalPhyNode->intervalUnit,
873✔
2002
                                .slidingUnit = pIntervalPhyNode->slidingUnit,
873✔
2003
                                .offset = pIntervalPhyNode->offset,
873✔
2004
                                .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
873✔
2005
                                .timeRange = pIntervalPhyNode->timeRange};
873✔
2006
  calcIntervalAutoOffset(&pInfo->interval);
873✔
2007
  pInfo->twAggSup = (STimeWindowAggSupp){
873✔
2008
      .waterMark = pIntervalPhyNode->window.watermark,
873✔
2009
      .calTrigger = pIntervalPhyNode->window.triggerType,
874✔
2010
      .maxTs = INT64_MIN,
2011
      .minTs = INT64_MAX,
2012
      .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval),
874✔
2013
      .deleteMarkSaved = 0,
2014
      .calTriggerSaved = 0,
2015
  };
2016
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
873✔
2017
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
873✔
2018
  initResultSizeInfo(&pOperator->resultInfo, 4096);
873✔
2019
  if (pIntervalPhyNode->window.pExprs != NULL) {
872!
2020
    int32_t    numOfScalar = 0;
×
2021
    SExprInfo* pScalarExprInfo = NULL;
×
2022

2023
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
×
2024
    QUERY_CHECK_CODE(code, lino, _error);
×
2025

2026
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
×
2027
    QUERY_CHECK_CODE(code, lino, _error);
×
2028
  }
2029

2030
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
872✔
2031
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
874!
2032
  initBasicInfo(&pInfo->binfo, pResBlock);
874✔
2033

2034
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
874!
2035
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
874!
2036
  qInfo("open state %p", pInfo->pState);
874!
2037
  pAPI->stateStore.streamStateCopyBackend(pTaskInfo->streamInfo.pState, pInfo->pState);
874✔
2038
  //*(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2039

2040
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
874!
2041

2042
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
874✔
2043

2044
  int32_t    numOfCols = 0;
874✔
2045
  SExprInfo* pExprInfo = NULL;
874✔
2046
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
874✔
2047
  QUERY_CHECK_CODE(code, lino, _error);
874!
2048

2049
  code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
874✔
2050
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
874✔
2051
  QUERY_CHECK_CODE(code, lino, _error);
874!
2052

2053
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
874✔
2054
  QUERY_CHECK_CODE(code, lino, _error);
874!
2055
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
874✔
2056

2057
  pInfo->numOfChild = numOfChild;
874✔
2058
  pInfo->pPhyNode = NULL;
874✔
2059
  code = nodesCloneNode((SNode*)pPhyNode, (SNode**)&pInfo->pPhyNode);
874✔
2060
  if (TSDB_CODE_SUCCESS != code) {
874!
2061
    goto _error;
×
2062
  }
2063

2064
  pInfo->pPullWins = taosArrayInit(8, sizeof(SPullWindowInfo));
874✔
2065
  QUERY_CHECK_NULL(pInfo->pPullWins, code, lino, _error, terrno);
874!
2066
  pInfo->pullIndex = 0;
874✔
2067
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
874✔
2068
  pInfo->pPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
874✔
2069
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
874✔
2070

2071
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
874✔
2072
  QUERY_CHECK_CODE(code, lino, _error);
874!
2073

2074
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
874✔
2075
  pInfo->ignoreExpiredDataSaved = false;
874✔
2076
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
874✔
2077
  QUERY_CHECK_CODE(code, lino, _error);
874!
2078

2079
  pInfo->delIndex = 0;
874✔
2080
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
874✔
2081
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
874!
2082
  pInfo->delKey.ts = INT64_MAX;
874✔
2083
  pInfo->delKey.groupId = 0;
874✔
2084
  pInfo->numOfDatapack = 0;
874✔
2085
  pInfo->pUpdated = NULL;
874✔
2086
  pInfo->pUpdatedMap = NULL;
874✔
2087
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
874✔
2088
  int32_t funResSize = getMaxFunResSize(&pOperator->exprSupp, numOfCols);
874✔
2089
  pInfo->pState->pFileState = NULL;
874✔
2090

2091
  // used for backward compatibility of function's result info
2092
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
874✔
2093
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
874✔
2094
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
874✔
2095

2096
  code =
2097
      pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
874✔
2098
                                           compareTs, pInfo->pState, pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo),
874✔
2099
                                           pHandle->checkpointId, STREAM_STATE_BUFF_HASH, &pInfo->pState->pFileState);
874✔
2100
  QUERY_CHECK_CODE(code, lino, _error);
874!
2101

2102
  pInfo->dataVersion = 0;
874✔
2103
  pInfo->recvGetAll = false;
874✔
2104
  pInfo->recvPullover = false;
874✔
2105
  pInfo->recvRetrive = false;
874✔
2106

2107
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
874✔
2108
  QUERY_CHECK_CODE(code, lino, _error);
874!
2109
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidRetriveRes);
874✔
2110
  QUERY_CHECK_CODE(code, lino, _error);
874!
2111
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidPulloverRes);
874✔
2112
  QUERY_CHECK_CODE(code, lino, _error);
874!
2113

2114
  pInfo->clearState = false;
874✔
2115
  pInfo->pMidPullDatas = taosArrayInit(4, sizeof(SWinKey));
874✔
2116
  QUERY_CHECK_NULL(pInfo->pMidPullDatas, code, lino, _error, terrno);
874!
2117
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
874✔
2118
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
874!
2119
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
874✔
2120
  pInfo->pOperator = pOperator;
874✔
2121

2122
  pOperator->operatorType = pPhyNode->type;
874✔
2123
  if (!IS_FINAL_INTERVAL_OP(pOperator) || numOfChild == 0) {
874!
2124
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
661✔
2125
  }
2126
  pOperator->name = getStreamOpName(pOperator->operatorType);
874✔
2127
  pOperator->blocking = true;
874✔
2128
  pOperator->status = OP_NOT_OPENED;
874✔
2129
  pOperator->info = pInfo;
874✔
2130

2131
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
874✔
2132
    pOperator->fpSet =
2133
        createOperatorFpSet(NULL, doStreamMidIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
22✔
2134
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2135
  } else {
2136
    pOperator->fpSet =
2137
        createOperatorFpSet(NULL, doStreamFinalIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
852✔
2138
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2139
  }
2140
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
874✔
2141

2142
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
874✔
2143
  QUERY_CHECK_CODE(code, lino, _error);
874!
2144

2145
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL ||
874✔
2146
      pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
235✔
2147
    pInfo->basic.primaryPkIndex = -1;
661✔
2148
    code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
661✔
2149
    QUERY_CHECK_CODE(code, lino, _error);
661!
2150
  }
2151
  code = appendDownstream(pOperator, &downstream, 1);
874✔
2152
  QUERY_CHECK_CODE(code, lino, _error);
874!
2153

2154
  // for stream
2155
  void*   buff = NULL;
874✔
2156
  int32_t len = 0;
874✔
2157
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
874✔
2158
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
2159
  if (res == TSDB_CODE_SUCCESS) {
874✔
2160
    doStreamIntervalDecodeOpState(buff, len, pOperator);
5✔
2161
    taosMemoryFree(buff);
5!
2162
  }
2163

2164
  *pOptrInfo = pOperator;
874✔
2165
  return TSDB_CODE_SUCCESS;
874✔
2166

2167
_error:
×
2168
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
2169
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
2170
  pTaskInfo->code = code;
×
2171
  return code;
×
2172
}
2173

2174
void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
2,145✔
2175
  tSimpleHashCleanup(pSup->pResultRows);
2,145✔
2176
  destroyDiskbasedBuf(pSup->pResultBuf);
2,145✔
2177
  blockDataDestroy(pSup->pScanBlock);
2,145✔
2178
  if (pSup->stateStore.streamFileStateDestroy != NULL) {
2,145!
2179
    pSup->stateStore.streamFileStateDestroy(pSup->pState->pFileState);
2,145✔
2180
  }
2181
  taosMemoryFreeClear(pSup->pState);
2,145!
2182
  taosMemoryFreeClear(pSup->pDummyCtx);
2,145!
2183
}
2,145✔
2184

2185
void destroyStreamSessionAggOperatorInfo(void* param) {
904✔
2186
  if (param == NULL) {
904!
2187
    return;
×
2188
  }
2189
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
904✔
2190
  cleanupBasicInfo(&pInfo->binfo);
904✔
2191
  if (pInfo->pOperator) {
904!
2192
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
904✔
2193
                              &pInfo->groupResInfo);
2194
    pInfo->pOperator = NULL;
904✔
2195
  }
2196

2197
  destroyStreamBasicInfo(&pInfo->basic);
904✔
2198
  cleanupExprSupp(&pInfo->scalarSupp);
904✔
2199
  clearGroupResInfo(&pInfo->groupResInfo);
904✔
2200
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
904✔
2201
  pInfo->pUpdated = NULL;
904✔
2202
  destroyStreamAggSupporter(&pInfo->streamAggSup);
904✔
2203

2204
  if (pInfo->pChildren != NULL) {
904✔
2205
    int32_t size = taosArrayGetSize(pInfo->pChildren);
38✔
2206
    for (int32_t i = 0; i < size; i++) {
163✔
2207
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
125✔
2208
      destroyOperator(pChild);
125✔
2209
    }
2210
    taosArrayDestroy(pInfo->pChildren);
38✔
2211
  }
2212

2213
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
904✔
2214
  blockDataDestroy(pInfo->pDelRes);
904✔
2215
  blockDataDestroy(pInfo->pWinBlock);
904✔
2216
  tSimpleHashCleanup(pInfo->pStUpdated);
904✔
2217
  tSimpleHashCleanup(pInfo->pStDeleted);
904✔
2218
  cleanupGroupResInfo(&pInfo->groupResInfo);
904✔
2219

2220
  taosArrayDestroy(pInfo->historyWins);
904✔
2221
  blockDataDestroy(pInfo->pCheckpointRes);
904✔
2222
  tSimpleHashCleanup(pInfo->pPkDeleted);
904✔
2223
  destroyNonBlockAggSupptor(&pInfo->nbSup);
904✔
2224

2225
  taosMemoryFreeClear(param);
904!
2226
}
2227

2228
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
1,797✔
2229
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
2230
  initBasicInfo(pBasicInfo, pResultBlock);
1,797✔
2231
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
1,797✔
2232
  if (code != TSDB_CODE_SUCCESS) {
1,795!
2233
    return code;
×
2234
  }
2235

2236
  for (int32_t i = 0; i < numOfCols; ++i) {
28,614✔
2237
    pSup->pCtx[i].saveHandle.pBuf = NULL;
26,819✔
2238
  }
2239

2240
  return TSDB_CODE_SUCCESS;
1,795✔
2241
}
2242

2243
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
2,145✔
2244
  for (int i = 0; i < nums; i++) {
30,444✔
2245
    pDummy[i].functionId = pCtx[i].functionId;
28,299✔
2246
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
28,299✔
2247
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
28,299✔
2248
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
28,299✔
2249
  }
2250
}
2,145✔
2251

2252
int32_t initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
2,314✔
2253
                       STimeWindowAggSupp* pTwSup, struct SSteamOpBasicInfo* pBasic, int64_t recalculateInterval) {
2254
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
2,314✔
2255
  int32_t        code = TSDB_CODE_SUCCESS;
2,314✔
2256
  int32_t        lino = 0;
2,314✔
2257
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
2,314✔
2258
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
642✔
2259
    pScanInfo->tsColIndex = tsColIndex;
642✔
2260
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
642✔
2261
  }
2262

2263
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
2,314✔
2264
    code = initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup, pBasic, recalculateInterval);
642✔
2265
    return code;
642✔
2266
  }
2267
  SStreamScanInfo* pScanInfo = downstream->info;
1,672✔
2268
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
1,672✔
2269
  pScanInfo->pState = pAggSup->pState;
1,672✔
2270
  if (!pScanInfo->pUpdateInfo) {
1,672✔
2271
    code = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark,
1,030✔
2272
                                              pScanInfo->igCheckUpdate, pScanInfo->pkColType, pScanInfo->pkColLen,
1,030✔
2273
                                              &pScanInfo->pUpdateInfo);
1,030✔
2274
    QUERY_CHECK_CODE(code, lino, _end);
1,030!
2275
  }
2276
  pScanInfo->twAggSup = *pTwSup;
1,672✔
2277
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
1,672✔
2278
  if (!hasSrcPrimaryKeyCol(pBasic)) {
1,672✔
2279
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
1,668✔
2280
  }
2281

2282
  pBasic->pTsDataState = pScanInfo->basic.pTsDataState;
1,672✔
2283

2284
  if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_CONTINUE_SEMI_SESSION) {
1,672!
2285
    pScanInfo->scanAllTables = true;
×
2286
  }
2287
  pScanInfo->recalculateInterval = recalculateInterval;
1,672✔
2288
  pScanInfo->windowSup.parentType = type;
1,672✔
2289
  pScanInfo->recParam.gap = pAggSup->gap;
1,672✔
2290

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

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

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

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

2318
  pSup->stateStore = *pStore;
2,145✔
2319
  pSup->pSessionAPI = pApi;
2,145✔
2320

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

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

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

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

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

2356
  pSup->pCur = NULL;
2,145✔
2357

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

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

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

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

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

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

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

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

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

2415
  if (*pWinCode == TSDB_CODE_SUCCESS) {
3,280✔
2416
    pCurWin->isOutput = true;
945✔
2417
    if (pCurWin->pStatePos->needFree) {
945✔
2418
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
136✔
2419
    }
2420
  } else {
2421
    pCurWin->sessionWin.win.skey = startTs;
2,335✔
2422
    pCurWin->sessionWin.win.ekey = endTs;
2,335✔
2423
  }
2424
  qDebug("===stream===set session window buff .start:%" PRId64 ",end:%" PRId64 ",groupid:%" PRIu64,
3,280✔
2425
         pCurWin->sessionWin.win.skey, pCurWin->sessionWin.win.ekey, pCurWin->sessionWin.groupId);
2426
_end:
1,778✔
2427
  if (code != TSDB_CODE_SUCCESS) {
3,280!
2428
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2429
  }
2430
  return code;
3,280✔
2431
}
2432

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

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

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

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

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

2466
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
13,118✔
2467
  pAPI->streamStateReleaseBuf(pState, pPos, false);
13,118✔
2468
}
13,119✔
2469

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

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

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

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

2524
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
3,256✔
2525
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2526
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2527
                                int32_t* pWinRos) {
2528
  int32_t code = TSDB_CODE_SUCCESS;
3,256✔
2529
  int32_t lino = 0;
3,256✔
2530
  for (int32_t i = start; i < rows; ++i) {
7,383✔
2531
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
4,222!
2532
      (*pWinRos) = i - start;
94✔
2533
      goto _end;
94✔
2534
    }
2535
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
4,127✔
2536
      if (pStDeleted && pWinInfo->isOutput) {
28!
2537
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
21✔
2538
        QUERY_CHECK_CODE(code, lino, _end);
21!
2539
      }
2540

2541
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
28✔
2542
      pWinInfo->sessionWin.win.skey = pStartTs[i];
28✔
2543
    }
2544
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
4,127✔
2545
    if (pEndTs) {
4,127!
2546
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
4,127✔
2547
    }
2548
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
4,127✔
2549
  }
2550
  (*pWinRos) = rows - start;
3,161✔
2551

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

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

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

2577
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
12,486✔
2578
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
12,485✔
2579

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

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

2595
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
16,152✔
2596
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
16,152✔
2597
  if (pVal) {
16,152✔
2598
    SResultWindowInfo* pWin = pVal;
789✔
2599
    pWinInfo->isOutput = pWin->isOutput;
789✔
2600
  }
2601
}
16,152✔
2602

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

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

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

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

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

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

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

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

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

2676
  if (pIsEnd != NULL) {
3,440!
2677
    (*pIsEnd) = false;
×
2678
  }
2679
  // Just look for the window behind StartIndex
2680
  while (1) {
18✔
2681
    SResultWindowInfo winInfo = {0};
3,458✔
2682
    getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
3,458✔
2683
    if (!IS_VALID_SESSION_WIN(winInfo)) {
3,457✔
2684
      if (pIsEnd != NULL) {
3,005!
2685
        (*pIsEnd) = true;
×
2686
      }
2687
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
3,005✔
2688
      break;
3,006✔
2689
    }
2690
    if (!isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
452✔
2691
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
20!
2692
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
432✔
2693
      break;
431✔
2694
    }
2695
    code =
2696
        compactTimeWindow(pSup, pAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, &winInfo, pStUpdated, pStDeleted, true);
20✔
2697
    QUERY_CHECK_CODE(code, lino, _end);
20✔
2698
    winNum++;
18✔
2699
  }
2700
  if (pWinNum) {
3,437✔
2701
    (*pWinNum) = winNum;
161✔
2702
  }
2703

2704
_end:
3,276✔
2705
  if (code != TSDB_CODE_SUCCESS) {
3,439✔
2706
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2707
  }
2708
  return code;
3,438✔
2709
}
2710

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

2735
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
12,847✔
2736
  qDebug("===stream===try save session result skey:%" PRId64 ", ekey:%" PRId64 ".pos%d", pWinInfo->sessionWin.win.skey,
12,847✔
2737
         pWinInfo->sessionWin.win.ekey, pWinInfo->pStatePos->needFree);
2738
  return pAggSup->stateStore.streamStateSessionPut(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pStatePos,
12,847✔
2739
                                                   pAggSup->resultRowSize);
2740
}
2741

2742
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3,184✔
2743
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
2744
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,184✔
2745
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,184✔
2746
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,184✔
2747
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
3,184✔
2748
  int32_t                        code = TSDB_CODE_SUCCESS;
3,184✔
2749
  int32_t                        lino = 0;
3,184✔
2750
  SResultRow*                    pResult = NULL;
3,184✔
2751
  int32_t                        rows = pSDataBlock->info.rows;
3,184✔
2752
  int32_t                        winRows = 0;
3,184✔
2753
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,184✔
2754

2755
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,184✔
2756
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,184✔
2757
  if (pAggSup->winRange.ekey <= 0) {
3,184!
2758
    pAggSup->winRange.ekey = INT64_MAX;
×
2759
  }
2760

2761
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,184✔
2762
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,184✔
2763
  SColumnInfoData* pEndTsCol = NULL;
3,184✔
2764
  if (hasEndTs) {
3,184✔
2765
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
486✔
2766
  } else {
2767
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,698✔
2768
  }
2769

2770
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
3,184✔
2771

2772
  void*            pPkVal = NULL;
3,184✔
2773
  int32_t          pkLen = 0;
3,184✔
2774
  SColumnInfoData* pPkColDataInfo = NULL;
3,184✔
2775
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
3,184✔
2776
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
14✔
2777
  }
2778

2779
  for (int32_t i = 0; i < rows;) {
6,458✔
2780
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
3,278!
2781
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2782
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2783
    }
2784
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
3,469✔
2785
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
191✔
2786
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
191✔
2787
      i++;
19✔
2788
      continue;
19✔
2789
    }
2790
    SResultWindowInfo winInfo = {0};
3,259✔
2791
    int32_t           winCode = TSDB_CODE_SUCCESS;
3,259✔
2792
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo, &winCode);
3,259✔
2793
    QUERY_CHECK_CODE(code, lino, _end);
3,261!
2794

2795
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_SESSION_OP(pOperator) &&
3,259✔
2796
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
2,046!
2797
      code = addSessionAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &winInfo.sessionWin, &pInfo->basic.notifyEventSup,
×
2798
                                      pTaskInfo->streamInfo.pNotifyEventStat);
2799
      QUERY_CHECK_CODE(code, lino, _end);
×
2800
    }
2801

2802
    // coverity scan error
2803
    if (!winInfo.pStatePos) {
3,259!
2804
      continue;
×
2805
    }
2806
    setSessionWinOutputInfo(pStUpdated, &winInfo);
3,259✔
2807
    code = updateSessionWindowInfo(pAggSup, &winInfo, startTsCols, endTsCols, groupId, rows, i, pAggSup->gap,
3,257✔
2808
                                   pAggSup->pResultRows, pStUpdated, pStDeleted, &winRows);
2809
    QUERY_CHECK_CODE(code, lino, _end);
3,255!
2810

2811
    int64_t winDelta = 0;
3,255✔
2812
    if (addGap) {
3,255✔
2813
      winDelta = pAggSup->gap;
2,616✔
2814
    }
2815
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
3,255✔
2816
                              pOperator, winDelta);
2817
    QUERY_CHECK_CODE(code, lino, _end);
3,258!
2818

2819
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL, NULL);
3,258✔
2820
    QUERY_CHECK_CODE(code, lino, _end);
3,257✔
2821

2822
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,255✔
2823
    QUERY_CHECK_CODE(code, lino, _end);
3,254!
2824

2825
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
3,254!
2826
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
4✔
2827
      QUERY_CHECK_CODE(code, lino, _end);
6!
2828
    }
2829
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
3,256✔
2830
      code = saveResult(winInfo, pStUpdated);
2,356✔
2831
      QUERY_CHECK_CODE(code, lino, _end);
2,356!
2832
    }
2833
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,256✔
2834
      winInfo.pStatePos->beUpdated = true;
620✔
2835
      SSessionKey key = {0};
620✔
2836
      getSessionHashKey(&winInfo.sessionWin, &key);
620✔
2837
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
620✔
2838
      QUERY_CHECK_CODE(code, lino, _end);
619!
2839
    }
2840

2841
    i += winRows;
3,255✔
2842
  }
2843

2844
_end:
3,180✔
2845
  if (code != TSDB_CODE_SUCCESS) {
3,182✔
2846
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2847
  }
2848
}
3,182✔
2849

2850
int32_t doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
1,196✔
2851
  int32_t          code = TSDB_CODE_SUCCESS;
1,196✔
2852
  int32_t          lino = 0;
1,196✔
2853
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,196✔
2854
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
1,196✔
2855
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,196✔
2856
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
1,196✔
2857
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,196✔
2858
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
1,195✔
2859
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
2,453✔
2860
    while (1) {
1,283✔
2861
      SSessionKey curWin = {0};
2,540✔
2862
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
2,540✔
2863
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
2,543✔
2864
        break;
1,258✔
2865
      }
2866
      doDeleteSessionWindow(pAggSup, &curWin);
1,285✔
2867
      if (result) {
1,285✔
2868
        code = saveDeleteInfo(result, curWin);
1,241✔
2869
        QUERY_CHECK_CODE(code, lino, _end);
1,239!
2870
      }
2871
    }
2872
  }
2873

2874
_end:
1,196✔
2875
  if (code != TSDB_CODE_SUCCESS) {
1,196!
2876
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2877
  }
2878
  return code;
1,196✔
2879
}
2880

2881
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
6,419✔
2882
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
6,419✔
2883
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
6,419✔
2884
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
6,419✔
2885
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
6,419✔
2886

2887
  if (pWin1->groupId > pWin2->groupId) {
6,419✔
2888
    return 1;
2,053✔
2889
  } else if (pWin1->groupId < pWin2->groupId) {
4,366✔
2890
    return -1;
1,896✔
2891
  }
2892

2893
  if (pWin1->win.skey > pWin2->win.skey) {
2,470✔
2894
    return 1;
1,361✔
2895
  } else if (pWin1->win.skey < pWin2->win.skey) {
1,109!
2896
    return -1;
1,109✔
2897
  }
2898

2899
  return 0;
×
2900
}
2901

2902
static int32_t appendToDeleteDataBlock(SOperatorInfo* pOp, SSDataBlock *pBlock, SSessionKey *pKey) {
700✔
2903
  int32_t        code = TSDB_CODE_SUCCESS;
700✔
2904
  int32_t        lino = 0;
700✔
2905
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
700✔
2906

2907
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
700!
2908
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
700!
2909

2910
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
700✔
2911
  code = colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
700✔
2912
  QUERY_CHECK_CODE(code, lino, _end);
700!
2913

2914
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
700✔
2915
  code = colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
700✔
2916
  QUERY_CHECK_CODE(code, lino, _end);
700!
2917

2918
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
700✔
2919
  colDataSetNULL(pUidCol, pBlock->info.rows);
700!
2920

2921
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
700✔
2922
  code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&pKey->groupId, false);
700✔
2923
  QUERY_CHECK_CODE(code, lino, _end);
700!
2924

2925
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
700✔
2926
  colDataSetNULL(pCalStCol, pBlock->info.rows);
700!
2927

2928
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
700✔
2929
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
700!
2930

2931
  SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
700✔
2932
  if (!pTableCol) {
700!
2933
    QUERY_CHECK_CODE(code, lino, _end);
×
2934
  }
2935

2936
  void*        tbname = NULL;
700✔
2937
  int32_t      winCode = TSDB_CODE_SUCCESS;
700✔
2938
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;
700✔
2939
  code =
2940
      pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, pKey->groupId, &tbname, false, &winCode);
700✔
2941
  QUERY_CHECK_CODE(code, lino, _end);
700!
2942

2943
  if (winCode != TSDB_CODE_SUCCESS) {
700✔
2944
    colDataSetNULL(pTableCol, pBlock->info.rows);
229!
2945
  } else {
2946
    char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
2947
    STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
471✔
2948
    code = colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
471✔
2949
    QUERY_CHECK_CODE(code, lino, _end);
471!
2950
    pAPI->stateStore.streamStateFreeVal(tbname);
471✔
2951
  }
2952
  pBlock->info.rows += 1;
700✔
2953

2954
_end:
700✔
2955
  if (code != TSDB_CODE_SUCCESS) {
700!
2956
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2957
  }
2958
  return code;
700✔
2959
}
2960

2961
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite,
18,056✔
2962
                            SGroupResInfo* pGroupResInfo) {
2963
  int32_t        code = TSDB_CODE_SUCCESS;
18,056✔
2964
  int32_t        lino = 0;
18,056✔
2965
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
18,056✔
2966
  int64_t        minWindowSize = getMinWindowSize(pOp);
18,056✔
2967
  int32_t        numOfRows = getNumOfTotalRes(pGroupResInfo);
18,054✔
2968

2969
  blockDataCleanup(pBlock);
18,051✔
2970
  int32_t size = tSimpleHashGetSize(pStDeleted);
18,048✔
2971
  if (minWindowSize > 0) {
18,047✔
2972
    // Add the number of windows that are below the minimum width limit.
2973
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
252✔
2974
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
2975
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
2976
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
2977
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
2978
        size++;
60✔
2979
      }
2980
    }
2981
  }
2982
  if (size == 0) {
18,047✔
2983
    return;
17,493✔
2984
  }
2985
  code = blockDataEnsureCapacity(pBlock, size);
554✔
2986
  QUERY_CHECK_CODE(code, lino, _end);
554!
2987

2988
  int32_t iter = 0;
554✔
2989
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
1,194✔
2990
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
640!
2991
      break;
×
2992
    }
2993
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
640!
2994
    code = appendToDeleteDataBlock(pOp, pBlock, res);
640✔
2995
    QUERY_CHECK_CODE(code, lino, _end);
640!
2996
  }
2997

2998
  if (minWindowSize > 0) {
554✔
2999
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
138✔
3000
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
3001
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
3002
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
3003
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
3004
        code = appendToDeleteDataBlock(pOp, pBlock, pKey);
60✔
3005
        QUERY_CHECK_CODE(code, lino, _end);
60!
3006
      }
3007
    }
3008
    pGroupResInfo->delIndex = numOfRows;
18✔
3009
  }
3010

3011
_end:
536✔
3012
  if ((*Ite) == NULL) {
554!
3013
    tSimpleHashClear(pStDeleted);
554✔
3014
  }
3015

3016
  if (code != TSDB_CODE_SUCCESS) {
554!
3017
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3018
  }
3019
}
3020

3021
static int32_t rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
56✔
3022
  int32_t        winCode = TSDB_CODE_SUCCESS;
56✔
3023
  int32_t        code = TSDB_CODE_SUCCESS;
56✔
3024
  int32_t        lino = 0;
56✔
3025
  SExprSupp*     pSup = &pOperator->exprSupp;
56✔
3026
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
56✔
3027
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
56✔
3028

3029
  int32_t                        size = taosArrayGetSize(pWinArray);
56✔
3030
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
56✔
3031
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
56✔
3032
  int32_t                        numOfOutput = pSup->numOfExprs;
56✔
3033
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
56✔
3034

3035
  for (int32_t i = 0; i < size; i++) {
111✔
3036
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
55✔
3037
    int32_t           num = 0;
55✔
3038
    SResultWindowInfo parentWin = {0};
55✔
3039
    for (int32_t j = 0; j < numOfChild; j++) {
249✔
3040
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
194✔
3041
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
194✔
3042
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
194✔
3043
      SSessionKey                    chWinKey = {0};
194✔
3044
      getSessionHashKey(pWinKey, &chWinKey);
194✔
3045
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
194✔
3046
      SResultRow*      pResult = NULL;
194✔
3047
      SResultRow*      pChResult = NULL;
194✔
3048
      while (1) {
21✔
3049
        SResultWindowInfo childWin = {0};
215✔
3050
        childWin.sessionWin = *pWinKey;
215✔
3051
        getSessionWinBuf(pChAggSup, pCur, &childWin, &winCode);
215✔
3052

3053
        if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
215!
3054
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
×
3055
          continue;
×
3056
        }
3057

3058
        if (winCode == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
215✔
3059
          if (num == 0) {
21!
3060
            code = setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin,
21✔
3061
                                       &winCode);
3062
            QUERY_CHECK_CODE(code, lino, _end);
21!
3063

3064
            parentWin.sessionWin = childWin.sessionWin;
21✔
3065
            memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3066
            code = initSessionOutputBuf(&parentWin, &pResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
21✔
3067
            QUERY_CHECK_CODE(code, lino, _end);
21!
3068
          }
3069
          num++;
21✔
3070
          parentWin.sessionWin.win.skey = TMIN(parentWin.sessionWin.win.skey, childWin.sessionWin.win.skey);
21✔
3071
          parentWin.sessionWin.win.ekey = TMAX(parentWin.sessionWin.win.ekey, childWin.sessionWin.win.ekey);
21✔
3072
          memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3073

3074
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap);
21✔
3075
          code = initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
21✔
3076
                                      pChild->exprSupp.rowEntryInfoOffset);
3077
          QUERY_CHECK_CODE(code, lino, _end);
21!
3078

3079
          code = compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo,
21✔
3080
                                  &pInfo->twAggSup.timeWindowData);
3081
          QUERY_CHECK_CODE(code, lino, _end);
21!
3082

3083
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL, NULL);
21✔
3084
          QUERY_CHECK_CODE(code, lino, _end);
21!
3085

3086
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
21✔
3087
        } else {
3088
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
194✔
3089
          break;
194✔
3090
        }
3091
      }
3092
      pAPI->stateStore.streamStateFreeCur(pCur);
194✔
3093
    }
3094
    if (num > 0) {
55✔
3095
      code = saveResult(parentWin, pStUpdated);
21✔
3096
      QUERY_CHECK_CODE(code, lino, _end);
21!
3097

3098
      code = saveSessionOutputBuf(pAggSup, &parentWin);
21✔
3099
      QUERY_CHECK_CODE(code, lino, _end);
21!
3100
    }
3101
  }
3102

3103
_end:
56✔
3104
  if (code != TSDB_CODE_SUCCESS) {
56!
3105
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3106
  }
3107
  return code;
56✔
3108
}
3109

3110
int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) {
11,176✔
3111
  int32_t code = TSDB_CODE_SUCCESS;
11,176✔
3112
  int32_t lino = 0;
11,176✔
3113
  void*   pIte = NULL;
11,176✔
3114
  int32_t iter = 0;
11,176✔
3115
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
13,095✔
3116
    SResultWindowInfo* pWinInfo = pIte;
1,919✔
3117
    if (isCloseWindow(&pWinInfo->sessionWin.win, pTwSup)) {
1,919✔
3118
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
612!
3119
        code = saveResult(*pWinInfo, pClosed);
612✔
3120
        QUERY_CHECK_CODE(code, lino, _end);
612!
3121
      }
3122
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
612!
3123
      code = tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
612✔
3124
      QUERY_CHECK_CODE(code, lino, _end);
612!
3125
    }
3126
  }
3127
_end:
11,183✔
3128
  if (code != TSDB_CODE_SUCCESS) {
11,183!
3129
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3130
  }
3131
  return code;
11,184✔
3132
}
3133

3134
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
3,772✔
3135
  int32_t code = TSDB_CODE_SUCCESS;
3,772✔
3136
  int32_t lino = 0;
3,772✔
3137

3138
  int32_t size = taosArrayGetSize(pChildren);
3,772✔
3139
  for (int32_t i = 0; i < size; i++) {
4,341✔
3140
    SOperatorInfo*                 pChildOp = taosArrayGetP(pChildren, i);
569✔
3141
    SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
569✔
3142
    pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
569✔
3143
    code = closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
569✔
3144
    QUERY_CHECK_CODE(code, lino, _end);
569!
3145
  }
3146
_end:
3,772✔
3147
  if (code != TSDB_CODE_SUCCESS) {
3,772!
3148
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3149
  }
3150
  return code;
3,771✔
3151
}
3152

3153
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
243✔
3154
  int32_t code = TSDB_CODE_SUCCESS;
243✔
3155
  int32_t lino = 0;
243✔
3156
  void*   pIte = NULL;
243✔
3157
  int32_t iter = 0;
243✔
3158
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
364✔
3159
    SResultWindowInfo* pWinInfo = pIte;
121✔
3160
    if (!pWinInfo->pStatePos->beUpdated) {
121✔
3161
      continue;
4✔
3162
    }
3163
    pWinInfo->pStatePos->beUpdated = false;
117✔
3164
    code = saveResult(*pWinInfo, pStUpdated);
117✔
3165
    QUERY_CHECK_CODE(code, lino, _end);
117!
3166
  }
3167

3168
_end:
243✔
3169
  if (code != TSDB_CODE_SUCCESS) {
243!
3170
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3171
  }
3172
  return code;
243✔
3173
}
3174

3175
int32_t copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
1,147✔
3176
  int32_t code = TSDB_CODE_SUCCESS;
1,147✔
3177
  int32_t lino = 0;
1,147✔
3178
  int32_t size = taosArrayGetSize(pResWins);
1,147✔
3179
  for (int32_t i = 0; i < size; i++) {
2,409✔
3180
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
1,262✔
3181
    if (!pWinKey) continue;
1,262!
3182
    SSessionKey winInfo = {0};
1,262✔
3183
    getSessionHashKey(pWinKey, &winInfo);
1,262✔
3184
    code = tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
1,262✔
3185
    QUERY_CHECK_CODE(code, lino, _end);
1,262!
3186
  }
3187

3188
_end:
1,147✔
3189
  if (code != TSDB_CODE_SUCCESS) {
1,147!
3190
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3191
  }
3192
  return code;
1,147✔
3193
}
3194

3195
// the allocated memory comes from outer function.
3196
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
11,145✔
3197
  pGroupResInfo->pRows = pArrayList;
11,145✔
3198
  pGroupResInfo->index = 0;
11,145✔
3199
  pGroupResInfo->pBuf = NULL;
11,145✔
3200
  pGroupResInfo->freeItem = false;
11,145✔
3201
  pGroupResInfo->delIndex = 0;
11,145✔
3202
}
11,145✔
3203

3204
int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
5,663✔
3205
                                    SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
3206
  int32_t         code = TSDB_CODE_SUCCESS;
5,663✔
3207
  int32_t         lino = 0;
5,663✔
3208
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
5,663✔
3209
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
5,663✔
3210
  SExprInfo*      pExprInfo = pSup->pExprInfo;
5,663✔
3211
  int32_t         numOfExprs = pSup->numOfExprs;
5,663✔
3212
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
5,663✔
3213
  SqlFunctionCtx* pCtx = pSup->pCtx;
5,663✔
3214
  int64_t         minWindowSize = getMinWindowSize(pOperator);
5,663✔
3215

3216
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
5,663✔
3217

3218
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
12,528✔
3219
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
8,741✔
3220
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
8,741✔
3221
    SResultRow*        pRow = NULL;
8,741✔
3222
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
8,741✔
3223

3224
    if (pBlock->info.id.groupId == 0) {
8,741✔
3225
      pBlock->info.id.groupId = pKey->groupId;
6,252✔
3226

3227
      void*   tbname = NULL;
6,252✔
3228
      int32_t winCode = TSDB_CODE_SUCCESS;
6,252✔
3229
      code = pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
6,252✔
3230
                                                    &tbname, false, &winCode);
3231
      QUERY_CHECK_CODE(code, lino, _end);
6,252!
3232

3233
      if (winCode != TSDB_CODE_SUCCESS) {
6,252✔
3234
        pBlock->info.parTbName[0] = 0;
1,780✔
3235
      } else {
3236
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,472✔
3237
      }
3238
      pAPI->stateStore.streamStateFreeVal(tbname);
6,252✔
3239
    } else {
3240
      // current value belongs to different group, it can't be packed into one datablock
3241
      if (pBlock->info.id.groupId != pKey->groupId) {
2,489✔
3242
        break;
1,791✔
3243
      }
3244
    }
3245

3246
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
6,950✔
3247
    QUERY_CHECK_CODE(code, lino, _end);
6,947!
3248

3249
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
6,947✔
3250
    // no results, continue to check the next one
3251
    if (pRow->numOfRows == 0) {
6,947!
3252
      pGroupResInfo->index += 1;
×
3253
      continue;
60✔
3254
    }
3255
    // skip the window which is less than the windowMinSize
3256
    if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
6,947✔
3257
      qDebug("skip small window, groupId: %" PRId64 ", windowSize: %" PRId64 ", minWindowSize: %" PRId64, pKey->groupId,
60!
3258
             pKey->win.ekey - pKey->win.skey, minWindowSize);
3259
      pGroupResInfo->index += 1;
60✔
3260
      continue;
60✔
3261
    }
3262

3263
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,887!
3264
      break;
×
3265
    }
3266

3267
    pGroupResInfo->index += 1;
6,887✔
3268

3269
    for (int32_t j = 0; j < numOfExprs; ++j) {
114,819✔
3270
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
108,014✔
3271

3272
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
108,014✔
3273
      if (pCtx[j].fpSet.finalize) {
108,002✔
3274
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
98,680✔
3275
        if (TAOS_FAILED(tmpRes)) {
98,687!
3276
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
3277
          QUERY_CHECK_CODE(code, lino, _end);
×
3278
        }
3279
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
9,322✔
3280
        // do nothing, todo refactor
3281
      } else {
3282
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
3283
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
3284
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
9,280✔
3285
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
9,279✔
3286
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
18,558✔
3287
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
9,280✔
3288
          QUERY_CHECK_CODE(code, lino, _end);
9,279!
3289
        }
3290
      }
3291
    }
3292

3293
    if (pSessionKeys) {
6,805!
3294
      for (int32_t j = 0; j < pRow->numOfRows; ++j) {
×
3295
        const void* px = taosArrayPush(pSessionKeys, pKey);
×
3296
        QUERY_CHECK_NULL(px, code, lino, _end, terrno);
×
3297
      }
3298
    }
3299

3300
    pBlock->info.dataLoad = 1;
6,805✔
3301
    pBlock->info.rows += pRow->numOfRows;
6,805✔
3302
  }
3303
  code = blockDataUpdateTsWindow(pBlock, 0);
5,578✔
3304
  QUERY_CHECK_CODE(code, lino, _end);
5,663!
3305

3306
_end:
5,663✔
3307
  if (code != TSDB_CODE_SUCCESS) {
5,663!
3308
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3309
  }
3310
  return code;
5,663✔
3311
}
3312

3313
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo, SSDataBlock* pBlock,
17,492✔
3314
                          SArray* pSessionKeys) {
3315
  int32_t        code = TSDB_CODE_SUCCESS;
17,492✔
3316
  int32_t        lino = 0;
17,492✔
3317
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
17,492✔
3318
  // set output datablock version
3319
  pBlock->info.version = pTaskInfo->version;
17,492✔
3320

3321
  blockDataCleanup(pBlock);
17,492✔
3322
  taosArrayClear(pSessionKeys);
17,497✔
3323
  if (!hasRemainResults(pGroupResInfo)) {
17,499✔
3324
    cleanupGroupResInfo(pGroupResInfo);
11,840✔
3325
    goto _end;
11,848✔
3326
  }
3327

3328
  // clear the existed group id
3329
  pBlock->info.id.groupId = 0;
5,663✔
3330
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
5,663✔
3331
  QUERY_CHECK_CODE(code, lino, _end);
5,663!
3332

3333
  if (pBlock->info.rows == 0) {
5,663!
3334
    cleanupGroupResInfo(pGroupResInfo);
×
3335
  }
3336

3337
_end:
5,663✔
3338
  if (code != TSDB_CODE_SUCCESS) {
17,511!
3339
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3340
  }
3341
}
17,511✔
3342

3343
static int32_t buildSessionResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,167✔
3344
  int32_t                        code = TSDB_CODE_SUCCESS;
7,167✔
3345
  int32_t                        lino = 0;
7,167✔
3346
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
7,167✔
3347
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
7,167✔
3348
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
7,167✔
3349
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
7,167✔
3350
  SStreamNotifyEventSupp*        pNotifySup = &pInfo->basic.notifyEventSup;
7,167✔
3351
  STaskNotifyEventStat*          pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
7,167✔
3352
  bool                           addNotifyEvent = false;
7,167✔
3353
  addNotifyEvent = IS_NORMAL_SESSION_OP(pOperator) &&
12,816✔
3354
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
5,649!
3355
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
7,167✔
3356
  if (pInfo->pDelRes->info.rows > 0) {
7,169✔
3357
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
266✔
3358
    if (addNotifyEvent) {
263!
3359
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
3360
      QUERY_CHECK_CODE(code, lino, _end);
×
3361
    }
3362
    (*ppRes) = pInfo->pDelRes;
263✔
3363
    return code;
263✔
3364
  }
3365

3366
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes,
6,903!
3367
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
3368
  if (pBInfo->pRes->info.rows > 0) {
6,915✔
3369
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,924✔
3370
    if (addNotifyEvent) {
1,924!
3371
      // Adjust the window end time based on the Session Window gap
3372
      for (int32_t i = 0; i < taosArrayGetSize(pNotifySup->pSessionKeys); ++i) {
×
3373
        SSessionKey* pKey = taosArrayGet(pNotifySup->pSessionKeys, i);
×
3374
        pKey->win.ekey += pAggSup->gap;
×
3375
      }
3376
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
3377
                                     pNotifySup, pNotifyEventStat);
3378
      QUERY_CHECK_CODE(code, lino, _end);
×
3379
    }
3380
    (*ppRes) = pBInfo->pRes;
1,924✔
3381
    return code;
1,924✔
3382
  }
3383

3384
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
4,991✔
3385
  QUERY_CHECK_CODE(code, lino, _end);
4,989!
3386
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
4,989!
3387
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3388
    (*ppRes) = pNotifySup->pEventBlock;
×
3389
    return code;
×
3390
  }
3391

3392
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
4,989✔
3393
  QUERY_CHECK_CODE(code, lino, _end);
4,989!
3394

3395
_end:
4,989✔
3396
  if (code != TSDB_CODE_SUCCESS) {
4,989!
3397
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3398
  }
3399
  (*ppRes) = NULL;
4,989✔
3400
  return code;
4,989✔
3401
}
3402

3403
int32_t getMaxTsWins(const SArray* pAllWins, SArray* pMaxWins) {
392✔
3404
  int32_t code = TSDB_CODE_SUCCESS;
392✔
3405
  int32_t lino = 0;
392✔
3406
  int32_t size = taosArrayGetSize(pAllWins);
392✔
3407
  if (size == 0) {
392✔
3408
    goto _end;
259✔
3409
  }
3410
  SResultWindowInfo* pWinInfo = taosArrayGet(pAllWins, size - 1);
133✔
3411
  SSessionKey*       pSeKey = &pWinInfo->sessionWin;
133✔
3412
  void*              tmp = taosArrayPush(pMaxWins, pSeKey);
133✔
3413
  if (!tmp) {
133!
3414
    code = terrno;
×
3415
    QUERY_CHECK_CODE(code, lino, _end);
×
3416
  }
3417

3418
  if (pSeKey->groupId == 0) {
133✔
3419
    goto _end;
17✔
3420
  }
3421
  uint64_t preGpId = pSeKey->groupId;
116✔
3422
  for (int32_t i = size - 2; i >= 0; i--) {
439✔
3423
    pWinInfo = taosArrayGet(pAllWins, i);
323✔
3424
    pSeKey = &pWinInfo->sessionWin;
323✔
3425
    if (preGpId != pSeKey->groupId) {
323✔
3426
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
209✔
3427
      if (!tmp) {
209!
3428
        code = terrno;
×
3429
        QUERY_CHECK_CODE(code, lino, _end);
×
3430
      }
3431
      preGpId = pSeKey->groupId;
209✔
3432
    }
3433
  }
3434

3435
_end:
116✔
3436
  if (code != TSDB_CODE_SUCCESS) {
392!
3437
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3438
  }
3439
  return code;
392✔
3440
}
3441

3442
int32_t encodeSSessionKey(void** buf, SSessionKey* key) {
16✔
3443
  int32_t tlen = 0;
16✔
3444
  tlen += encodeSTimeWindow(buf, &key->win);
16✔
3445
  tlen += taosEncodeFixedU64(buf, key->groupId);
16✔
3446
  return tlen;
16✔
3447
}
3448

3449
void* decodeSSessionKey(void* buf, SSessionKey* key) {
2✔
3450
  buf = decodeSTimeWindow(buf, &key->win);
2✔
3451
  buf = taosDecodeFixedU64(buf, &key->groupId);
2!
3452
  return buf;
2✔
3453
}
3454

3455
int32_t encodeSResultWindowInfo(void** buf, SResultWindowInfo* key, int32_t outLen) {
8✔
3456
  int32_t tlen = 0;
8✔
3457
  tlen += taosEncodeFixedBool(buf, key->isOutput);
8✔
3458
  tlen += encodeSSessionKey(buf, &key->sessionWin);
8✔
3459
  return tlen;
8✔
3460
}
3461

3462
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
1✔
3463
  buf = taosDecodeFixedBool(buf, &key->isOutput);
1✔
3464
  buf = decodeSSessionKey(buf, &key->sessionWin);
1✔
3465
  return buf;
1✔
3466
}
3467

3468
int32_t doStreamSessionEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
×
3469
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3470
  if (!pInfo) {
×
3471
    return 0;
×
3472
  }
3473

3474
  void* pData = (buf == NULL) ? NULL : *buf;
×
3475

3476
  // 1.streamAggSup.pResultRows
3477
  int32_t tlen = 0;
×
3478
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
×
3479
  tlen += taosEncodeFixedI32(buf, mapSize);
×
3480
  void*   pIte = NULL;
×
3481
  size_t  keyLen = 0;
×
3482
  int32_t iter = 0;
×
3483
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
×
3484
    void* key = tSimpleHashGetKey(pIte, &keyLen);
×
3485
    tlen += encodeSSessionKey(buf, key);
×
3486
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
×
3487
  }
3488

3489
  // 2.twAggSup
3490
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3491

3492
  // 3.pChildren
3493
  int32_t size = taosArrayGetSize(pInfo->pChildren);
×
3494
  tlen += taosEncodeFixedI32(buf, size);
×
3495
  for (int32_t i = 0; i < size; i++) {
×
3496
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3497
    tlen += doStreamSessionEncodeOpState(buf, 0, pChOp, false);
×
3498
  }
3499

3500
  // 4.dataVersion
3501
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
3502

3503
  // 5.basicInfo
3504
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
×
3505

3506
  // 6.checksum
3507
  if (isParent) {
×
3508
    if (buf) {
×
3509
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
×
3510
      tlen += taosEncodeFixedU32(buf, cksum);
×
3511
    } else {
3512
      tlen += sizeof(uint32_t);
×
3513
    }
3514
  }
3515

3516
  return tlen;
×
3517
}
3518

3519
int32_t doStreamSessionDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
3520
  int32_t                        code = TSDB_CODE_SUCCESS;
×
3521
  int32_t                        lino = 0;
×
3522
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3523
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
×
3524
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
×
3525
  if (!pInfo) {
×
3526
    code = TSDB_CODE_FAILED;
×
3527
    QUERY_CHECK_CODE(code, lino, _end);
×
3528
  }
3529
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
×
3530

3531
  // 6.checksum
3532
  if (isParent) {
×
3533
    int32_t dataLen = len - sizeof(uint32_t);
×
3534
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
3535
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
3536
      qError("stream session state is invalid");
×
3537
      code = TSDB_CODE_FAILED;
×
3538
      QUERY_CHECK_CODE(code, lino, _end);
×
3539
    }
3540
    pDataEnd = pCksum;
×
3541
  }
3542

3543
  // 1.streamAggSup.pResultRows
3544
  int32_t mapSize = 0;
×
3545
  buf = taosDecodeFixedI32(buf, &mapSize);
×
3546
  for (int32_t i = 0; i < mapSize; i++) {
×
3547
    SResultWindowInfo winfo = {0};
×
3548
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
3549
    int32_t winCode = TSDB_CODE_SUCCESS;
×
3550
    code = pAggSup->stateStore.streamStateSessionAddIfNotExist(
×
3551
        pAggSup->pState, &winfo.sessionWin, pAggSup->gap, (void**)&winfo.pStatePos, &pAggSup->resultRowSize, &winCode);
3552
    QUERY_CHECK_CODE(code, lino, _end);
×
3553
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
3554

3555
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
3556
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
3557
                          sizeof(SResultWindowInfo));
3558
    QUERY_CHECK_CODE(code, lino, _end);
×
3559
  }
3560

3561
  // 2.twAggSup
3562
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3563

3564
  // 3.pChildren
3565
  int32_t size = 0;
×
3566
  buf = taosDecodeFixedI32(buf, &size);
×
3567
  for (int32_t i = 0; i < size; i++) {
×
3568
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3569
    code = doStreamSessionDecodeOpState(buf, 0, pChOp, false, &buf);
×
3570
    QUERY_CHECK_CODE(code, lino, _end);
×
3571
  }
3572

3573
  // 4.dataVersion
3574
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
3575
  if (ppBuf) {
×
3576
    (*ppBuf) = buf;
×
3577
  }
3578

3579
  // 5.basicInfo
3580
  if (buf < pDataEnd) {
×
3581
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
×
3582
    QUERY_CHECK_CODE(code, lino, _end);
×
3583
  }
3584

3585
_end:
×
3586
  if (code != TSDB_CODE_SUCCESS) {
×
3587
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3588
  }
3589
  return code;
×
3590
}
3591

3592
void doStreamSessionSaveCheckpoint(SOperatorInfo* pOperator) {
191✔
3593
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3594
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
191!
3595
    int32_t len = doStreamSessionEncodeOpState(NULL, 0, pOperator, true);
×
3596
    void*   buf = taosMemoryCalloc(1, len);
×
3597
    if (!buf) {
×
3598
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
3599
      return;
×
3600
    }
3601
    void* pBuf = buf;
×
3602
    len = doStreamSessionEncodeOpState(&pBuf, len, pOperator, true);
×
3603
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
×
3604
                                                       strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), buf, len);
3605
    taosMemoryFree(buf);
×
3606
    saveStreamOperatorStateComplete(&pInfo->basic);
×
3607
  }
3608
}
3609

3610
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
102✔
3611
  void*   pIte = NULL;
102✔
3612
  int32_t iter = 0;
102✔
3613
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
219✔
3614
    SResultWindowInfo* pResInfo = pIte;
117✔
3615
    pResInfo->pStatePos->beUsed = true;
117✔
3616
  }
3617
}
102✔
3618

3619
int32_t copyDeleteSessionKey(SSHashObj* source, SSHashObj* dest) {
32✔
3620
  int32_t code = TSDB_CODE_SUCCESS;
32✔
3621
  int32_t lino = 0;
32✔
3622
  if (tSimpleHashGetSize(source) == 0) {
32✔
3623
    goto _end;
23✔
3624
  }
3625
  void*   pIte = NULL;
9✔
3626
  int32_t iter = 0;
9✔
3627
  size_t  keyLen = 0;
9✔
3628
  while ((pIte = tSimpleHashIterate(source, pIte, &iter)) != NULL) {
21✔
3629
    SSessionKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
12✔
3630
    code = saveDeleteRes(dest, *pKey);
12✔
3631
    QUERY_CHECK_CODE(code, lino, _end);
12!
3632
  }
3633
  tSimpleHashClear(source);
9✔
3634

3635
_end:
32✔
3636
  if (code != TSDB_CODE_SUCCESS) {
32!
3637
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3638
  }
3639
  return code;
32✔
3640
}
3641

3642
static int32_t doStreamSessionAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
6,505✔
3643
  int32_t                        code = TSDB_CODE_SUCCESS;
6,505✔
3644
  int32_t                        lino = 0;
6,505✔
3645
  SExprSupp*                     pSup = &pOperator->exprSupp;
6,505✔
3646
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
6,505✔
3647
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
6,505✔
3648
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
6,505✔
3649
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
6,505✔
3650
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
6,505✔
3651
  if (pOperator->status == OP_EXEC_DONE) {
6,505!
3652
    (*ppRes) = NULL;
×
3653
    return code;
×
3654
  } else if (pOperator->status == OP_RES_TO_RETURN) {
6,505✔
3655
    SSDataBlock* opRes = NULL;
1,886✔
3656
    code = buildSessionResult(pOperator, &opRes);
1,886✔
3657
    QUERY_CHECK_CODE(code, lino, _end);
1,888!
3658
    if (opRes) {
1,888✔
3659
      (*ppRes) = opRes;
457✔
3660
      return code;
1,888✔
3661
    }
3662

3663
    if (pInfo->recvGetAll) {
1,431✔
3664
      pInfo->recvGetAll = false;
83✔
3665
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
83✔
3666
    }
3667

3668
    if (pInfo->reCkBlock) {
1,431!
3669
      pInfo->reCkBlock = false;
×
3670
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3671
      (*ppRes) = pInfo->pCheckpointRes;
×
3672
      return code;
×
3673
    }
3674

3675
    setStreamOperatorCompleted(pOperator);
1,431✔
3676
    (*ppRes) = NULL;
1,431✔
3677
    return code;
1,431✔
3678
  }
3679

3680
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,619✔
3681
  if (!pInfo->pUpdated) {
4,619✔
3682
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
3,771✔
3683
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
3,771!
3684
  }
3685
  if (!pInfo->pStUpdated) {
4,619✔
3686
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,701✔
3687
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
3,700✔
3688
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
3,700!
3689
  }
3690
  while (1) {
3,359✔
3691
    SSDataBlock* pBlock = NULL;
7,977✔
3692
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,977✔
3693
    QUERY_CHECK_CODE(code, lino, _end);
7,973!
3694

3695
    if (pBlock == NULL) {
7,973✔
3696
      break;
3,769✔
3697
    }
3698
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,204✔
3699
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,206✔
3700

3701
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,204✔
3702
        pBlock->info.type == STREAM_CLEAR) {
3,958✔
3703
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
416✔
3704
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
416!
3705
      // gap must be 0
3706
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
416✔
3707
      QUERY_CHECK_CODE(code, lino, _end);
416!
3708

3709
      removeSessionResults(pAggSup, pInfo->pStUpdated, pWins);
416✔
3710
      if (IS_FINAL_SESSION_OP(pOperator)) {
416✔
3711
        int32_t                        childIndex = getChildIndex(pBlock);
56✔
3712
        SOperatorInfo*                 pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
56✔
3713
        SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
56✔
3714
        // gap must be 0
3715
        code = doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
56✔
3716
        QUERY_CHECK_CODE(code, lino, _end);
56!
3717

3718
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
56✔
3719
        QUERY_CHECK_CODE(code, lino, _end);
56!
3720
      }
3721
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
416✔
3722
      QUERY_CHECK_CODE(code, lino, _end);
416!
3723

3724
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
416!
3725
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
2✔
3726
        QUERY_CHECK_CODE(code, lino, _end);
2!
3727
      }
3728
      taosArrayDestroy(pWins);
416✔
3729
      continue;
778✔
3730
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,788✔
3731
      pInfo->recvGetAll = true;
186✔
3732
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
186✔
3733
      QUERY_CHECK_CODE(code, lino, _end);
186!
3734
      continue;
186✔
3735
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,602✔
3736
      (*ppRes) = pBlock;
847✔
3737
      return code;
847✔
3738
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,755✔
3739
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
176✔
3740
      doStreamSessionSaveCheckpoint(pOperator);
176✔
3741
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
176✔
3742
      QUERY_CHECK_CODE(code, lino, _end);
176!
3743

3744
      continue;
176✔
3745
    } else {
3746
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
2,579!
3747
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3748
        QUERY_CHECK_CODE(code, lino, _end);
×
3749
      }
3750
    }
3751

3752
    if (pInfo->scalarSupp.pExprInfo != NULL) {
2,579✔
3753
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
3754
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
3755
      QUERY_CHECK_CODE(code, lino, _end);
13!
3756
    }
3757
    // the pDataBlock are always the same one, no need to call this again
3758
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
2,579✔
3759
    QUERY_CHECK_CODE(code, lino, _end);
2,583!
3760

3761
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_SESSION_OP(pOperator),
2,583✔
3762
                           true);
3763
    if (IS_FINAL_SESSION_OP(pOperator)) {
2,581✔
3764
      int32_t chIndex = getChildIndex(pBlock);
243✔
3765
      int32_t size = taosArrayGetSize(pInfo->pChildren);
243✔
3766
      // if chIndex + 1 - size > 0, add new child
3767
      for (int32_t i = 0; i < chIndex + 1 - size; i++) {
243!
3768
        SOperatorInfo* pChildOp = NULL;
×
3769
        code = createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0, NULL, &pChildOp);
×
3770
        if (pChildOp == NULL || code != 0) {
×
3771
          qError("%s create stream child of final session error", GET_TASKID(pTaskInfo));
×
3772
          code = TSDB_CODE_FAILED;
×
3773
          QUERY_CHECK_CODE(code, lino, _end);
×
3774
        }
3775

3776
        void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
×
3777
        if (!tmp) {
×
3778
          code = terrno;
×
3779
          QUERY_CHECK_CODE(code, lino, _end);
×
3780
        }
3781
      }
3782

3783
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
243✔
3784
      code = setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
243✔
3785
      QUERY_CHECK_CODE(code, lino, _end);
243!
3786
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
243✔
3787
    }
3788
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
2,581✔
3789
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
2,581✔
3790
  }
3791
  // restore the value
3792
  pOperator->status = OP_RES_TO_RETURN;
3,769✔
3793

3794
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
3,769✔
3795
  QUERY_CHECK_CODE(code, lino, _end);
3,772!
3796

3797
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
3,772✔
3798
  QUERY_CHECK_CODE(code, lino, _end);
3,770!
3799

3800
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
3,770✔
3801
  QUERY_CHECK_CODE(code, lino, _end);
3,770!
3802

3803
  if (!pInfo->destHasPrimaryKey) {
3,770✔
3804
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
3,752✔
3805
  }
3806
  if (pInfo->isHistoryOp) {
3,769✔
3807
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
199✔
3808
    QUERY_CHECK_CODE(code, lino, _end);
199!
3809
  }
3810
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
3,769!
3811
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
22✔
3812
    QUERY_CHECK_CODE(code, lino, _end);
22!
3813
  }
3814
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
3,769✔
3815
  pInfo->pUpdated = NULL;
3,761✔
3816
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3,761✔
3817
  QUERY_CHECK_CODE(code, lino, _end);
3,765!
3818

3819
  SSDataBlock* opRes = NULL;
3,765✔
3820
  code = buildSessionResult(pOperator, &opRes);
3,765✔
3821
  QUERY_CHECK_CODE(code, lino, _end);
3,773!
3822
  if (opRes) {
3,773✔
3823
    (*ppRes) = opRes;
1,431✔
3824
    return code;
1,431✔
3825
  }
3826

3827
_end:
2,342✔
3828
  if (code != TSDB_CODE_SUCCESS) {
2,342!
3829
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3830
    pTaskInfo->code = code;
×
3831
    T_LONG_JMP(pTaskInfo->env, code);
×
3832
  }
3833
  setStreamOperatorCompleted(pOperator);
2,342✔
3834
  (*ppRes) = NULL;
2,340✔
3835
  return code;
2,340✔
3836
}
3837

3838
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
×
3839
  SSDataBlock* pRes = NULL;
×
3840
  int32_t      code = doStreamSessionAggNext(pOperator, &pRes);
×
3841
  return pRes;
×
3842
}
3843

3844
void streamSessionReleaseState(SOperatorInfo* pOperator) {
191✔
3845
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3846
  int32_t                        winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
191✔
3847
  int32_t                        resSize = winSize + sizeof(TSKEY);
191✔
3848
  char*                          pBuff = taosMemoryCalloc(1, resSize);
191!
3849
  if (!pBuff) {
191!
3850
    return;
×
3851
  }
3852
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
191✔
3853
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
191✔
3854
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_STATE_NAME,
191✔
3855
                                                     strlen(STREAM_SESSION_OP_STATE_NAME), pBuff, resSize);
3856
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
191✔
3857
  taosMemoryFreeClear(pBuff);
191!
3858
  SOperatorInfo* downstream = pOperator->pDownstream[0];
191✔
3859
  if (downstream->fpSet.releaseStreamStateFn) {
191!
3860
    downstream->fpSet.releaseStreamStateFn(downstream);
191✔
3861
  }
3862
}
3863

3864
void resetWinRange(STimeWindow* winRange) {
359✔
3865
  winRange->skey = INT64_MIN;
359✔
3866
  winRange->ekey = INT64_MAX;
359✔
3867
}
359✔
3868

3869
int32_t getSessionWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SResultWindowInfo* pWinInfo) {
342✔
3870
  int32_t code = TSDB_CODE_SUCCESS;
342✔
3871
  int32_t lino = 0;
342✔
3872
  int32_t rowSize = pAggSup->resultRowSize;
342✔
3873
  int32_t winCode = TSDB_CODE_SUCCESS;
342✔
3874
  code = pAggSup->stateStore.streamStateSessionGet(pAggSup->pState, pKey, (void**)&pWinInfo->pStatePos, &rowSize,
342✔
3875
                                                   &winCode);
3876
  QUERY_CHECK_CODE(code, lino, _end);
342!
3877

3878
  if (winCode == TSDB_CODE_SUCCESS) {
342!
3879
    pWinInfo->sessionWin = *pKey;
342✔
3880
    pWinInfo->isOutput = true;
342✔
3881
    if (pWinInfo->pStatePos->needFree) {
342!
3882
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pWinInfo->sessionWin);
342✔
3883
    }
3884
  } else {
3885
    SET_SESSION_WIN_INVALID((*pWinInfo));
×
3886
  }
3887

3888
_end:
342✔
3889
  if (code != TSDB_CODE_SUCCESS) {
342!
3890
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3891
  }
3892
  return code;
342✔
3893
}
3894

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

3898
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
643✔
3899
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
205✔
3900
    return;
205✔
3901
  }
3902

3903
  SStreamScanInfo* pScanInfo = downstream->info;
438✔
3904
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
438✔
3905
}
3906

3907
void streamSessionSemiReloadState(SOperatorInfo* pOperator) {
15✔
3908
  int32_t                        code = TSDB_CODE_SUCCESS;
15✔
3909
  int32_t                        lino = 0;
15✔
3910
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
15✔
3911
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
15✔
3912
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
15✔
3913
  resetWinRange(&pAggSup->winRange);
15✔
3914

3915
  SResultWindowInfo winInfo = {0};
15✔
3916
  int32_t           size = 0;
15✔
3917
  void*             pBuf = NULL;
15✔
3918
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
15✔
3919
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3920
  QUERY_CHECK_CODE(code, lino, _end);
15!
3921

3922
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
15✔
3923
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
15✔
3924
  for (int32_t i = 0; i < num; i++) {
40✔
3925
    SResultWindowInfo winInfo = {0};
25✔
3926
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
25✔
3927
    QUERY_CHECK_CODE(code, lino, _end);
25!
3928
    if (!IS_VALID_SESSION_WIN(winInfo)) {
25!
3929
      continue;
×
3930
    }
3931
    compactSessionSemiWindow(pOperator, &winInfo);
25✔
3932
    code = saveSessionOutputBuf(pAggSup, &winInfo);
25✔
3933
    QUERY_CHECK_CODE(code, lino, _end);
25!
3934
  }
3935
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
15✔
3936
  taosMemoryFree(pBuf);
15!
3937
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
15✔
3938
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
15✔
3939

3940
  SOperatorInfo* downstream = pOperator->pDownstream[0];
15✔
3941
  if (downstream->fpSet.reloadStreamStateFn) {
15!
3942
    downstream->fpSet.reloadStreamStateFn(downstream);
15✔
3943
  }
3944
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
15✔
3945

3946
_end:
15✔
3947
  if (code != TSDB_CODE_SUCCESS) {
15!
3948
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3949
  }
3950
}
15✔
3951

3952
void streamSessionReloadState(SOperatorInfo* pOperator) {
176✔
3953
  int32_t                        code = TSDB_CODE_SUCCESS;
176✔
3954
  int32_t                        lino = 0;
176✔
3955
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
176✔
3956
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
176✔
3957
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
176✔
3958
  resetWinRange(&pAggSup->winRange);
176✔
3959

3960
  int32_t size = 0;
176✔
3961
  void*   pBuf = NULL;
176✔
3962
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
176✔
3963
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3964

3965
  QUERY_CHECK_CODE(code, lino, _end);
176!
3966

3967
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
176✔
3968
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
176✔
3969

3970
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
176✔
3971
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
176✔
3972
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
176✔
3973

3974
  if (!pInfo->pStUpdated && num > 0) {
176!
3975
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
70✔
3976
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
70✔
3977
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
70!
3978
  }
3979
  for (int32_t i = 0; i < num; i++) {
337✔
3980
    SResultWindowInfo winInfo = {0};
161✔
3981
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
161✔
3982
    QUERY_CHECK_CODE(code, lino, _end);
161!
3983
    if (!IS_VALID_SESSION_WIN(winInfo)) {
161!
3984
      continue;
×
3985
    }
3986

3987
    int32_t winNum = 0;
161✔
3988
    code = compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted, true, &winNum, NULL);
161✔
3989
    QUERY_CHECK_CODE(code, lino, _end);
161!
3990

3991
    if (winNum > 0) {
161!
3992
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, winInfo.sessionWin.win.skey,
×
3993
             winInfo.sessionWin.groupId);
3994
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
3995
        code = saveResult(winInfo, pInfo->pStUpdated);
×
3996
        QUERY_CHECK_CODE(code, lino, _end);
×
3997
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
3998
        if (!isCloseWindow(&winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
3999
          code = saveDeleteRes(pInfo->pStDeleted, winInfo.sessionWin);
×
4000
          QUERY_CHECK_CODE(code, lino, _end);
×
4001
        }
4002
        SSessionKey key = {0};
×
4003
        getSessionHashKey(&winInfo.sessionWin, &key);
×
4004
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
×
4005
        QUERY_CHECK_CODE(code, lino, _end);
×
4006
      }
4007
    }
4008
    code = saveSessionOutputBuf(pAggSup, &winInfo);
161✔
4009
    QUERY_CHECK_CODE(code, lino, _end);
161!
4010
  }
4011
  taosMemoryFree(pBuf);
176!
4012

4013
  SOperatorInfo* downstream = pOperator->pDownstream[0];
176✔
4014
  if (downstream->fpSet.reloadStreamStateFn) {
176!
4015
    downstream->fpSet.reloadStreamStateFn(downstream);
176✔
4016
  }
4017
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
176✔
4018

4019
_end:
176✔
4020
  if (code != TSDB_CODE_SUCCESS) {
176!
4021
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4022
  }
4023
}
176✔
4024

4025
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
904✔
4026
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4027
  QRY_PARAM_CHECK(pOptrInfo);
904!
4028

4029
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
904✔
4030
  int32_t                        numOfCols = 0;
904✔
4031
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
904✔
4032
  int32_t                        lino = 0;
904✔
4033
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
904!
4034
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
904!
4035
  if (pInfo == NULL || pOperator == NULL) {
904!
4036
    code = terrno;
×
4037
    goto _error;
×
4038
  }
4039

4040
  pOperator->pTaskInfo = pTaskInfo;
904✔
4041

4042
  initResultSizeInfo(&pOperator->resultInfo, 4096);
904✔
4043
  if (pSessionNode->window.pExprs != NULL) {
904✔
4044
    int32_t    numOfScalar = 0;
1✔
4045
    SExprInfo* pScalarExprInfo = NULL;
1✔
4046
    code = createExprInfo(pSessionNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
4047
    QUERY_CHECK_CODE(code, lino, _error);
1!
4048

4049
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
4050
    if (code != TSDB_CODE_SUCCESS) {
1!
4051
      goto _error;
×
4052
    }
4053
  }
4054
  SExprSupp* pExpSup = &pOperator->exprSupp;
904✔
4055

4056
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
904✔
4057
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
904!
4058
  pInfo->binfo.pRes = pResBlock;
904✔
4059

4060
  SExprInfo* pExprInfo = NULL;
904✔
4061
  code = createExprInfo(pSessionNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
904✔
4062
  QUERY_CHECK_CODE(code, lino, _error);
904!
4063

4064
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
904✔
4065
  QUERY_CHECK_CODE(code, lino, _error);
903!
4066

4067
  pInfo->twAggSup = (STimeWindowAggSupp){
904✔
4068
      .waterMark = pSessionNode->window.watermark,
904✔
4069
      .calTrigger = pSessionNode->window.triggerType,
903✔
4070
      .maxTs = INT64_MIN,
4071
      .minTs = INT64_MAX,
4072
      .deleteMark = getDeleteMark(&pSessionNode->window, 0),
903✔
4073
  };
4074

4075
  pInfo->primaryTsIndex = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
904✔
4076
  code =
4077
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, pSessionNode->gap, pTaskInfo->streamInfo.pState,
904✔
4078
                             0, 0, &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
904✔
4079
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
4080
  if (code != TSDB_CODE_SUCCESS) {
904!
4081
    goto _error;
×
4082
  }
4083

4084
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
904✔
4085
  QUERY_CHECK_CODE(code, lino, _error);
903!
4086

4087
  if (pSessionNode->window.pTsEnd) {
903!
4088
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
904✔
4089
  }
4090

4091
  pInfo->order = TSDB_ORDER_ASC;
903✔
4092
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
903✔
4093
  pInfo->pStDeleted = tSimpleHashInit(64, hashFn);
904✔
4094
  QUERY_CHECK_NULL(pInfo->pStDeleted, code, lino, _error, terrno);
904!
4095
  pInfo->pDelIterator = NULL;
904✔
4096
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
904✔
4097
  QUERY_CHECK_CODE(code, lino, _error);
904!
4098

4099
  pInfo->pChildren = NULL;
904✔
4100
  pInfo->pPhyNode = pPhyNode;
904✔
4101
  pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
904✔
4102
  pInfo->ignoreExpiredDataSaved = false;
904✔
4103
  pInfo->pUpdated = NULL;
904✔
4104
  pInfo->pStUpdated = NULL;
904✔
4105
  pInfo->dataVersion = 0;
904✔
4106
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
904✔
4107
  if (!pInfo->historyWins) {
904!
4108
    goto _error;
×
4109
  }
4110
  if (pHandle) {
904!
4111
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
904✔
4112
  }
4113

4114
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
904✔
4115
  QUERY_CHECK_CODE(code, lino, _error);
904!
4116

4117
  pInfo->clearState = false;
904✔
4118
  pInfo->recvGetAll = false;
904✔
4119
  pInfo->destHasPrimaryKey = pSessionNode->window.destHasPrimaryKey;
904✔
4120
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
904✔
4121
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
904!
4122
  pInfo->pOperator = pOperator;
904✔
4123
  initNonBlockAggSupptor(&pInfo->nbSup, NULL, NULL);
904✔
4124

4125
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), nodeType(pSessionNode), true,
903✔
4126
                  OP_NOT_OPENED, pInfo, pTaskInfo);
4127
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
904✔
4128
    // for stream
4129
    void*   buff = NULL;
741✔
4130
    int32_t len = 0;
741✔
4131
    int32_t res =
4132
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
741✔
4133
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4134
    if (res == TSDB_CODE_SUCCESS) {
741!
4135
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4136
      taosMemoryFree(buff);
×
4137
      QUERY_CHECK_CODE(code, lino, _error);
×
4138
    }
4139
  }
4140

4141
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
904✔
4142
  QUERY_CHECK_CODE(code, lino, _error);
904!
4143

4144
  if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
904!
4145
    if (pHandle->fillHistory == STREAM_HISTORY_OPERATOR) {
×
4146
      setFillHistoryOperatorFlag(&pInfo->basic);
×
4147
    } else if (pHandle->fillHistory == STREAM_RECALCUL_OPERATOR) {
×
4148
      setRecalculateOperatorFlag(&pInfo->basic);
×
4149
    }
4150
    pOperator->fpSet =
4151
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionNonblockAggNext, NULL, destroyStreamSessionAggOperatorInfo,
×
4152
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4153
    setOperatorStreamStateFn(pOperator, streamSessionNonblockReleaseState, streamSessionNonblockReloadState);
×
4154
  } else {
4155
    pOperator->fpSet =
4156
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionAggNext, NULL, destroyStreamSessionAggOperatorInfo,
904✔
4157
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4158
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
904✔
4159
  }
4160

4161
  if (downstream) {
904✔
4162
    pInfo->basic.primaryPkIndex = -1;
779✔
4163
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
779✔
4164
                          &pInfo->twAggSup, &pInfo->basic, pSessionNode->window.recalculateInterval);
779✔
4165
    QUERY_CHECK_CODE(code, lino, _error);
779!
4166

4167
    code = appendDownstream(pOperator, &downstream, 1);
779✔
4168
    QUERY_CHECK_CODE(code, lino, _error);
779!
4169
  }
4170

4171
  *pOptrInfo = pOperator;
904✔
4172
  return TSDB_CODE_SUCCESS;
904✔
4173

4174
_error:
×
4175
  if (pInfo != NULL) {
×
4176
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4177
  }
4178
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
4179
  pTaskInfo->code = code;
×
4180
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4181
  return code;
×
4182
}
4183

4184
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
533✔
4185
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
533✔
4186
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
533✔
4187
  pInfo->clearState = false;
535✔
4188
}
535✔
4189

4190
int32_t deleteSessionWinState(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SSHashObj* pMapUpdate,
658✔
4191
                              SSHashObj* pMapDelete, SSHashObj* pPkDelete, bool needAdd) {
4192
  int32_t code = TSDB_CODE_SUCCESS;
658✔
4193
  int32_t lino = 0;
658✔
4194
  SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
658✔
4195
  if (!pWins) {
658!
4196
    code = terrno;
×
4197
    QUERY_CHECK_CODE(code, lino, _end);
×
4198
  }
4199
  code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
658✔
4200
  QUERY_CHECK_CODE(code, lino, _end);
658!
4201

4202
  removeSessionResults(pAggSup, pMapUpdate, pWins);
658✔
4203
  code = copyDeleteWindowInfo(pWins, pMapDelete);
658✔
4204
  QUERY_CHECK_CODE(code, lino, _end);
658!
4205

4206
  if (needAdd) {
658!
4207
    code = copyDeleteWindowInfo(pWins, pPkDelete);
×
4208
    QUERY_CHECK_CODE(code, lino, _end);
×
4209
  }
4210
  taosArrayDestroy(pWins);
658✔
4211

4212
_end:
658✔
4213
  if (code != TSDB_CODE_SUCCESS) {
658!
4214
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4215
  }
4216
  return code;
658✔
4217
}
4218

4219
static int32_t doStreamSessionSemiAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
983✔
4220
  int32_t                        code = TSDB_CODE_SUCCESS;
983✔
4221
  int32_t                        lino = 0;
983✔
4222
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
983✔
4223
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
983✔
4224
  TSKEY                          maxTs = INT64_MIN;
983✔
4225
  SExprSupp*                     pSup = &pOperator->exprSupp;
983✔
4226
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
983✔
4227
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
983✔
4228

4229
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
983✔
4230
  if (pOperator->status == OP_EXEC_DONE) {
983!
4231
    (*ppRes) = NULL;
×
4232
    return code;
×
4233
  }
4234

4235
  {
4236
    SSDataBlock* opRes = NULL;
983✔
4237
    code = buildSessionResult(pOperator, &opRes);
983✔
4238
    QUERY_CHECK_CODE(code, lino, _end);
983!
4239
    if (opRes) {
983✔
4240
      (*ppRes) = opRes;
98✔
4241
      return code;
243✔
4242
    }
4243

4244
    if (pInfo->clearState) {
885✔
4245
      clearFunctionContext(&pOperator->exprSupp);
56✔
4246
      // semi session operator clear disk buffer
4247
      clearStreamSessionOperator(pInfo);
56✔
4248
    }
4249

4250
    if (pOperator->status == OP_RES_TO_RETURN) {
885✔
4251
      if (pInfo->reCkBlock) {
145!
4252
        pInfo->reCkBlock = false;
×
4253
        printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
4254
        (*ppRes) = pInfo->pCheckpointRes;
×
4255
        return code;
×
4256
      }
4257
      clearFunctionContext(&pOperator->exprSupp);
145✔
4258
      // semi session operator clear disk buffer
4259
      clearStreamSessionOperator(pInfo);
145✔
4260
      setStreamOperatorCompleted(pOperator);
145✔
4261
      (*ppRes) = NULL;
145✔
4262
      return code;
145✔
4263
    }
4264
  }
4265

4266
  SOperatorInfo* downstream = pOperator->pDownstream[0];
740✔
4267
  if (!pInfo->pUpdated) {
740✔
4268
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
535✔
4269
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
535!
4270
  }
4271
  if (!pInfo->pStUpdated) {
740✔
4272
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
535✔
4273
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
535✔
4274
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
535!
4275
  }
4276
  while (1) {
373✔
4277
    SSDataBlock* pBlock = NULL;
1,113✔
4278
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,113✔
4279
    QUERY_CHECK_CODE(code, lino, _end);
1,113!
4280

4281
    if (pBlock == NULL) {
1,113✔
4282
      pOperator->status = OP_RES_TO_RETURN;
479✔
4283
      break;
479✔
4284
    }
4285
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
634✔
4286
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
634✔
4287

4288
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
634✔
4289
        pBlock->info.type == STREAM_CLEAR) {
583✔
4290
      // gap must be 0
4291
      code = deleteSessionWinState(pAggSup, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, NULL, false);
56✔
4292
      QUERY_CHECK_CODE(code, lino, _end);
56!
4293
      pInfo->clearState = true;
56✔
4294
      break;
56✔
4295
    } else if (pBlock->info.type == STREAM_GET_ALL) {
578!
4296
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
×
4297
      QUERY_CHECK_CODE(code, lino, _end);
×
4298
      continue;
15✔
4299
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
578✔
4300
      (*ppRes) = pBlock;
205✔
4301
      return code;
205✔
4302
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
373✔
4303
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
15✔
4304
      doStreamSessionSaveCheckpoint(pOperator);
15✔
4305
      continue;
15✔
4306
    } else {
4307
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
358!
4308
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4309
        QUERY_CHECK_CODE(code, lino, _end);
×
4310
      }
4311
    }
4312

4313
    if (pInfo->scalarSupp.pExprInfo != NULL) {
358!
4314
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
4315
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
4316
      QUERY_CHECK_CODE(code, lino, _end);
×
4317
    }
4318
    // the pDataBlock are always the same one, no need to call this again
4319
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
358✔
4320
    QUERY_CHECK_CODE(code, lino, _end);
358!
4321
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
358✔
4322
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
358✔
4323
  }
4324

4325
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
535✔
4326
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
535✔
4327

4328
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
535✔
4329
  QUERY_CHECK_CODE(code, lino, _end);
535!
4330

4331
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
535✔
4332

4333
  if (pInfo->isHistoryOp) {
535✔
4334
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
15✔
4335
    QUERY_CHECK_CODE(code, lino, _end);
15!
4336
  }
4337

4338
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
535✔
4339
  pInfo->pUpdated = NULL;
535✔
4340
  code = blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
535✔
4341
  QUERY_CHECK_CODE(code, lino, _end);
535!
4342

4343
  SSDataBlock* opRes = NULL;
535✔
4344
  code = buildSessionResult(pOperator, &opRes);
535✔
4345
  QUERY_CHECK_CODE(code, lino, _end);
535!
4346
  if (opRes) {
535✔
4347
    (*ppRes) = opRes;
201✔
4348
    return code;
201✔
4349
  }
4350

4351
_end:
334✔
4352
  if (code != TSDB_CODE_SUCCESS) {
334!
4353
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4354
    pTaskInfo->code = code;
×
4355
    T_LONG_JMP(pTaskInfo->env, code);
×
4356
  }
4357

4358
  clearFunctionContext(&pOperator->exprSupp);
334✔
4359
  // semi session operator clear disk buffer
4360
  clearStreamSessionOperator(pInfo);
332✔
4361
  setStreamOperatorCompleted(pOperator);
334✔
4362
  (*ppRes) = NULL;
334✔
4363
  return code;
334✔
4364
}
4365

4366
static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
×
4367
  SSDataBlock* pRes = NULL;
×
4368
  int32_t      code = doStreamSessionSemiAggNext(pOperator, &pRes);
×
4369
  return pRes;
×
4370
}
4371

4372
int32_t createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
288✔
4373
                                                SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle,
4374
                                                SOperatorInfo** pOptrInfo) {
4375
  QRY_PARAM_CHECK(pOptrInfo);
288!
4376

4377
  int32_t        code = TSDB_CODE_SUCCESS;
288✔
4378
  int32_t        lino = 0;
288✔
4379
  SOperatorInfo* pOperator = NULL;
288✔
4380
  code = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, &pOperator);
288✔
4381
  if (pOperator == NULL || code != 0) {
288!
4382
    downstream = NULL;
×
4383
    QUERY_CHECK_CODE(code, lino, _error);
×
4384
  }
4385

4386
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
288✔
4387
  pInfo->pOperator = pOperator;
288✔
4388

4389
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
288✔
4390
    pOperator->fpSet =
125✔
4391
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAggNext, NULL, destroyStreamSessionAggOperatorInfo,
125✔
4392
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4393
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionSemiReloadState);
125✔
4394
  }
4395

4396
  if (numOfChild > 0) {
288✔
4397
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
38✔
4398
    QUERY_CHECK_NULL(pInfo->pChildren, code, lino, _error, terrno);
38!
4399
    for (int32_t i = 0; i < numOfChild; i++) {
163✔
4400
      SOperatorInfo* pChildOp = NULL;
125✔
4401
      code = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0, pHandle, &pChildOp);
125✔
4402
      if (pChildOp == NULL || code != 0) {
125!
4403
        QUERY_CHECK_CODE(code, lino, _error);
×
4404
      }
4405

4406
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
125✔
4407
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
125✔
4408
      pTaskInfo->storageAPI.stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i, pInfo->primaryTsIndex);
125✔
4409
      void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
125✔
4410
      if (!tmp) {
125!
4411
        code = terrno;
×
4412
        QUERY_CHECK_CODE(code, lino, _error);
×
4413
      }
4414
    }
4415

4416
    void*   buff = NULL;
38✔
4417
    int32_t len = 0;
38✔
4418
    int32_t res =
4419
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
38✔
4420
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4421
    if (res == TSDB_CODE_SUCCESS) {
38!
4422
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4423
      taosMemoryFree(buff);
×
4424
      QUERY_CHECK_CODE(code, lino, _error);
×
4425
    }
4426
  }
4427

4428
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
288✔
4429
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
250✔
4430
  }
4431

4432
  *pOptrInfo = pOperator;
288✔
4433
  return code;
288✔
4434

4435
_error:
×
4436
  if (pInfo != NULL) {
×
4437
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4438
  }
4439
  if (pOperator != NULL) {
×
4440
    pOperator->info = NULL;
×
4441
    destroyOperator(pOperator);
×
4442
  }
4443
  pTaskInfo->code = code;
×
4444
  if (code != TSDB_CODE_SUCCESS) {
×
4445
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4446
  }
4447
  return code;
×
4448
}
4449

4450
void destroyStreamStateOperatorInfo(void* param) {
356✔
4451
  if (param == NULL) {
356!
4452
    return;
×
4453
  }
4454
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
356✔
4455
  cleanupBasicInfo(&pInfo->binfo);
356✔
4456
  if (pInfo->pOperator) {
356!
4457
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
356✔
4458
                              &pInfo->groupResInfo);
4459
    pInfo->pOperator = NULL;
356✔
4460
  }
4461

4462
  destroyStreamBasicInfo(&pInfo->basic);
356✔
4463
  clearGroupResInfo(&pInfo->groupResInfo);
356✔
4464
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
356✔
4465
  pInfo->pUpdated = NULL;
356✔
4466
  destroyStreamAggSupporter(&pInfo->streamAggSup);
356✔
4467

4468
  cleanupExprSupp(&pInfo->scalarSupp);
356✔
4469
  if (pInfo->pChildren != NULL) {
356!
4470
    int32_t size = taosArrayGetSize(pInfo->pChildren);
×
4471
    for (int32_t i = 0; i < size; i++) {
×
4472
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
×
4473
      destroyOperator(pChild);
×
4474
    }
4475
    taosArrayDestroy(pInfo->pChildren);
×
4476
  }
4477
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
356✔
4478
  blockDataDestroy(pInfo->pDelRes);
356✔
4479
  tSimpleHashCleanup(pInfo->pSeUpdated);
356✔
4480
  tSimpleHashCleanup(pInfo->pSeDeleted);
356✔
4481
  cleanupGroupResInfo(&pInfo->groupResInfo);
356✔
4482

4483
  taosArrayDestroy(pInfo->historyWins);
356✔
4484
  blockDataDestroy(pInfo->pCheckpointRes);
356✔
4485
  tSimpleHashCleanup(pInfo->pPkDeleted);
356✔
4486
  destroyNonBlockAggSupptor(&pInfo->nbSup);
356✔
4487

4488
  taosMemoryFreeClear(param);
356!
4489
}
4490

4491
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
4,024✔
4492
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
4,024✔
4493
    return true;
1,322✔
4494
  }
4495
  return false;
2,702✔
4496
}
4497

4498
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
6,616✔
4499
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
6,616!
4500
}
4501

4502
bool compareStateKey(void* data, void* key) {
2,693✔
4503
  if (!data || !key) {
2,693!
4504
    return true;
×
4505
  }
4506
  SStateKeys* stateKey = (SStateKeys*)key;
2,693✔
4507
  stateKey->pData = (char*)key + sizeof(SStateKeys);
2,693✔
4508
  return compareVal(data, stateKey);
2,693✔
4509
}
4510

4511
bool compareWinStateKey(SStateKeys* left, SStateKeys* right) {
128✔
4512
  if (!left || !right) {
128!
4513
    return false;
128✔
4514
  }
4515
  return compareVal(left->pData, right);
×
4516
}
4517

4518
void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
3,424✔
4519
  SStreamStateCur* pCur = NULL;
3,424✔
4520

4521
  if (pAggSup == NULL || pNextWin == NULL) {
3,424!
4522
    return;
×
4523
  }
4524

4525
  if (asc)
3,424!
4526
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
3,424✔
4527
  else
4528
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyPrev(pAggSup->pState, &pNextWin->winInfo.sessionWin);
×
4529
  int32_t nextSize = pAggSup->resultRowSize;
3,424✔
4530
  int32_t winCode = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin,
3,424✔
4531
                                                                     (void**)&pNextWin->winInfo.pStatePos, &nextSize);
3,424✔
4532
  if (winCode != TSDB_CODE_SUCCESS) {
3,424✔
4533
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
3,249✔
4534
  } else {
4535
    pNextWin->pStateKey =
175✔
4536
        (SStateKeys*)((char*)pNextWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
175✔
4537
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
175✔
4538
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
175✔
4539
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
175✔
4540
    pNextWin->pStateKey->isNull = false;
175✔
4541
    pNextWin->winInfo.isOutput = true;
175✔
4542
  }
4543
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,424✔
4544
}
4545

4546
int32_t getStateWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SStateWindowInfo* pCurWin,
128✔
4547
                                SStateWindowInfo* pNextWin) {
4548
  int32_t code = TSDB_CODE_SUCCESS;
128✔
4549
  int32_t lino = 0;
128✔
4550
  int32_t size = pAggSup->resultRowSize;
128✔
4551
  pCurWin->winInfo.sessionWin.groupId = pKey->groupId;
128✔
4552
  pCurWin->winInfo.sessionWin.win.skey = pKey->win.skey;
128✔
4553
  pCurWin->winInfo.sessionWin.win.ekey = pKey->win.ekey;
128✔
4554
  code = getSessionWindowInfoByKey(pAggSup, pKey, &pCurWin->winInfo);
128✔
4555
  QUERY_CHECK_CODE(code, lino, _end);
128!
4556
  QUERY_CHECK_CONDITION((IS_VALID_SESSION_WIN(pCurWin->winInfo)), code, lino, _end,
128!
4557
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4558

4559
  pCurWin->pStateKey =
128✔
4560
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
128✔
4561
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
128✔
4562
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
128✔
4563
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
128✔
4564
  pCurWin->pStateKey->isNull = false;
128✔
4565
  pCurWin->winInfo.isOutput = true;
128✔
4566
  if (pCurWin->winInfo.pStatePos->needFree) {
128!
4567
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
128✔
4568
  }
4569

4570
  qDebug("===stream===get state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
128✔
4571
         pCurWin->winInfo.sessionWin.win.ekey);
4572

4573
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
128✔
4574
  getNextStateWin(pAggSup, pNextWin, true);
128✔
4575

4576
_end:
128✔
4577
  qDebug("===stream===get state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
128✔
4578
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4579
  if (code != TSDB_CODE_SUCCESS) {
128!
4580
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4581
  }
4582
  return code;
128✔
4583
}
4584

4585
int32_t setStateOutputBuf(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
3,296✔
4586
                          SStateWindowInfo* pCurWin, SStateWindowInfo* pNextWin, int32_t* pWinCode) {
4587
  int32_t size = pAggSup->resultRowSize;
3,296✔
4588
  pCurWin->winInfo.sessionWin.groupId = groupId;
3,296✔
4589
  pCurWin->winInfo.sessionWin.win.skey = ts;
3,296✔
4590
  pCurWin->winInfo.sessionWin.win.ekey = ts;
3,296✔
4591
  int32_t code = TSDB_CODE_SUCCESS;
3,296✔
4592
  int32_t lino = 0;
3,296✔
4593
  int32_t winCode = TSDB_CODE_SUCCESS;
3,296✔
4594
  code = pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData,
3,296✔
4595
                                                           pAggSup->stateKeySize, compareStateKey,
4596
                                                           (void**)&pCurWin->winInfo.pStatePos, &size, &winCode);
3,296✔
4597
  QUERY_CHECK_CODE(code, lino, _end);
3,296!
4598

4599
  pCurWin->pStateKey =
3,296✔
4600
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
3,296✔
4601
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
3,296✔
4602
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
3,296✔
4603
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
3,296✔
4604
  pCurWin->pStateKey->isNull = false;
3,296✔
4605

4606
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->winInfo.sessionWin.win)) {
3,296!
4607
    winCode = TSDB_CODE_FAILED;
×
4608
    clearOutputBuf(pAggSup->pState, pCurWin->winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
4609
    pCurWin->pStateKey =
×
4610
        (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
×
4611
    pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
×
4612
    pCurWin->pStateKey->type = pAggSup->stateKeyType;
×
4613
    pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
×
4614
    pCurWin->pStateKey->isNull = false;
×
4615
    pCurWin->winInfo.sessionWin.groupId = groupId;
×
4616
    pCurWin->winInfo.sessionWin.win.skey = ts;
×
4617
    pCurWin->winInfo.sessionWin.win.ekey = ts;
×
4618
    qDebug("===stream===reset state win key. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
×
4619
           pCurWin->winInfo.sessionWin.win.ekey);
4620
  }
4621

4622
  if (winCode == TSDB_CODE_SUCCESS) {
3,296✔
4623
    pCurWin->winInfo.isOutput = true;
2,028✔
4624
    if (pCurWin->winInfo.pStatePos->needFree) {
2,028✔
4625
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
66✔
4626
    }
4627
  } else if (pKeyData) {
1,268!
4628
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,268!
4629
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4630
    } else {
4631
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,264✔
4632
    }
4633
  }
4634

4635
  *pWinCode = winCode;
3,296✔
4636

4637
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
3,296✔
4638
         pCurWin->winInfo.sessionWin.win.ekey);
4639

4640
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
3,296✔
4641
  getNextStateWin(pAggSup, pNextWin, true);
3,296✔
4642
  qDebug("===stream===set state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
3,296✔
4643
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4644
_end:
1,544✔
4645
  if (code != TSDB_CODE_SUCCESS) {
3,296!
4646
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4647
  }
4648
  return code;
3,296✔
4649
}
4650

4651
int32_t updateStateWindowInfo(SStreamAggSupporter* pAggSup, SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin,
3,296✔
4652
                              TSKEY* pTs, uint64_t groupId, SColumnInfoData* pKeyCol, int32_t rows, int32_t start,
4653
                              bool* allEqual, SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted,
4654
                              int32_t* pWinRows) {
4655
  int32_t code = TSDB_CODE_SUCCESS;
3,296✔
4656
  int32_t lino = 0;
3,296✔
4657
  *allEqual = true;
3,296✔
4658
  for (int32_t i = start; i < rows; ++i) {
7,210✔
4659
    char* pKeyData = colDataGetData(pKeyCol, i);
4,024!
4660
    if (!isTsInWindow(pWinInfo, pTs[i])) {
4,024✔
4661
      if (isEqualStateKey(pWinInfo, pKeyData)) {
2,702✔
4662
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
2,592✔
4663
          // ts belongs to the next window
4664
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
137!
4665
            (*pWinRows) = i - start;
×
4666
            goto _end;
×
4667
          }
4668
        }
4669
      } else {
4670
        (*pWinRows) = i - start;
110✔
4671
        goto _end;
110✔
4672
      }
4673
    }
4674

4675
    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
3,914✔
4676
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
6!
4677
        code = saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
6✔
4678
        QUERY_CHECK_CODE(code, lino, _end);
6!
4679
      }
4680
      removeSessionResult(pAggSup, pSeUpdated, pResultRows, &pWinInfo->winInfo.sessionWin);
6✔
4681
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
6✔
4682
    }
4683
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
3,914✔
4684
    memcpy(pWinInfo->winInfo.pStatePos->pKey, &pWinInfo->winInfo.sessionWin, sizeof(SSessionKey));
3,914✔
4685
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
3,914✔
4686
      *allEqual = false;
24✔
4687
    }
4688
  }
4689
  (*pWinRows) = rows - start;
3,186✔
4690

4691
_end:
3,296✔
4692
  if (code != TSDB_CODE_SUCCESS) {
3,296!
4693
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4694
  }
4695
  return code;
3,296✔
4696
}
4697

4698
static bool isWinResult(SSessionKey* pKey, SSHashObj* pSeUpdate, SSHashObj* pResults) {
3,296✔
4699
  SSessionKey checkKey = {0};
3,296✔
4700
  getSessionHashKey(pKey, &checkKey);
3,296✔
4701
  if (tSimpleHashGet(pSeUpdate, &checkKey, sizeof(SSessionKey)) != NULL) {
3,296✔
4702
    return true;
30✔
4703
  }
4704

4705
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
3,266✔
4706
    return true;
17✔
4707
  }
4708
  return false;
3,249✔
4709
}
4710

4711
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
3,197✔
4712
                                 SSHashObj* pStDeleted) {
4713
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3,197✔
4714
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
3,197✔
4715

4716
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,197✔
4717
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
3,197✔
4718
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
3,197✔
4719
  int32_t                      code = TSDB_CODE_SUCCESS;
3,197✔
4720
  int32_t                      lino = 0;
3,197✔
4721
  TSKEY*                       tsCols = NULL;
3,197✔
4722
  SResultRow*                  pResult = NULL;
3,197✔
4723
  int32_t                      winRows = 0;
3,197✔
4724
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
3,197✔
4725
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
3,197✔
4726
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
3,197✔
4727

4728
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,197✔
4729
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,197✔
4730
  if (pAggSup->winRange.ekey <= 0) {
3,197!
4731
    pAggSup->winRange.ekey = INT64_MAX;
×
4732
  }
4733

4734
  if (pSDataBlock->pDataBlock != NULL) {
3,197!
4735
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,198✔
4736
    if (!pColDataInfo) {
3,198!
4737
      code = TSDB_CODE_FAILED;
×
4738
      QUERY_CHECK_CODE(code, lino, _end);
×
4739
    }
4740
    tsCols = (int64_t*)pColDataInfo->pData;
3,198✔
4741
  } else {
4742
    return;
×
4743
  }
4744

4745
  int32_t rows = pSDataBlock->info.rows;
3,198✔
4746
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
3,198✔
4747
  QUERY_CHECK_CODE(code, lino, _end);
3,198!
4748

4749
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
3,198✔
4750
  for (int32_t i = 0; i < rows; i += winRows) {
6,515✔
4751
    if (pInfo->ignoreExpiredData && checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo,
3,381✔
4752
                                                     &pInfo->twAggSup, pSDataBlock->info.id.uid, tsCols[i], NULL, 0) ||
64✔
4753
        colDataIsNull_s(pKeyColInfo, i)) {
6,608✔
4754
      i++;
21✔
4755
      continue;
42✔
4756
    }
4757
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
3,296!
4758
    int32_t          winIndex = 0;
3,296✔
4759
    bool             allEqual = true;
3,296✔
4760
    SStateWindowInfo curWin = {0};
3,296✔
4761
    SStateWindowInfo nextWin = {0};
3,296✔
4762
    int32_t          winCode = TSDB_CODE_SUCCESS;
3,296✔
4763
    code = setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin, &winCode);
3,296✔
4764
    QUERY_CHECK_CODE(code, lino, _end);
3,296!
4765

4766
    if (winCode != TSDB_CODE_SUCCESS && pTaskInfo->streamInfo.eventTypes) {
3,296!
4767
      SStateWindowInfo prevWin = {.winInfo.sessionWin = curWin.winInfo.sessionWin};
×
4768
      getNextStateWin(pAggSup, &prevWin, false);
×
4769
      qDebug("===stream===get state prev win buff. skey:%" PRId64 ", endkey:%" PRId64,
×
4770
             prevWin.winInfo.sessionWin.win.skey, prevWin.winInfo.sessionWin.win.ekey);
4771
      releaseOutputBuf(pAggSup->pState, prevWin.winInfo.pStatePos, &pAPI->stateStore);
×
4772
      // For ordered data, the previous window's closure did not record the corresponding state values, so they need to
4773
      // be added here.
4774
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE) &&
×
4775
          IS_VALID_SESSION_WIN(prevWin.winInfo)) {
×
4776
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &prevWin.winInfo.sessionWin, prevWin.pStateKey,
×
4777
                                      curWin.pStateKey, true, pNotifySup, pNotifyEventStat);
×
4778
        QUERY_CHECK_CODE(code, lino, _end);
×
4779
      }
4780
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
×
4781
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4782
                                      prevWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4783
        QUERY_CHECK_CODE(code, lino, _end);
×
4784
      }
4785
    }
4786

4787
    if (isWinResult(&nextWin.winInfo.sessionWin, pSeUpdated, pAggSup->pResultRows) == false) {
3,296✔
4788
      releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,249✔
4789
    }
4790

4791
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
3,296✔
4792
    code = updateStateWindowInfo(pAggSup, &curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
3,296✔
4793
                                 pAggSup->pResultRows, pSeUpdated, pStDeleted, &winRows);
4794
    QUERY_CHECK_CODE(code, lino, _end);
3,296!
4795

4796
    if (!allEqual) {
3,296✔
4797
      uint64_t uid = 0;
21✔
4798
      code = appendDataToSpecialBlock(pAggSup->pScanBlock, &curWin.winInfo.sessionWin.win.skey,
21✔
4799
                                      &curWin.winInfo.sessionWin.win.ekey, &uid, &groupId, NULL);
4800
      QUERY_CHECK_CODE(code, lino, _end);
21!
4801
      int32_t tmpRes = tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
21✔
4802
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
21!
4803

4804
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
21✔
4805
      releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
21✔
4806
      continue;
21✔
4807
    }
4808

4809
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
3,275✔
4810
                              pOperator, 0);
4811
    QUERY_CHECK_CODE(code, lino, _end);
3,275!
4812

4813
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,275✔
4814
    QUERY_CHECK_CODE(code, lino, _end);
3,275!
4815

4816
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
3,275!
4817
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
1✔
4818
      QUERY_CHECK_CODE(code, lino, _end);
1!
4819
    }
4820

4821
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,275✔
4822
      code = saveResult(curWin.winInfo, pSeUpdated);
2,960✔
4823
      QUERY_CHECK_CODE(code, lino, _end);
2,960!
4824
    }
4825

4826
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,275✔
4827
      curWin.winInfo.pStatePos->beUpdated = true;
315✔
4828
      SSessionKey key = {0};
315✔
4829
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
315✔
4830
      code =
4831
          tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
315✔
4832
      QUERY_CHECK_CODE(code, lino, _end);
315!
4833
    }
4834

4835
    // If this is a windown recalculation, add the corresponding state values here since the next window may not require
4836
    // recalculation.
4837
    if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE)) {
3,275!
4838
      code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4839
                                    nextWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4840
      QUERY_CHECK_CODE(code, lino, _end);
×
4841
    }
4842
  }
4843

4844
_end:
3,198✔
4845
  if (code != TSDB_CODE_SUCCESS) {
3,198!
4846
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4847
  }
4848
}
4849

4850
int32_t doStreamStateEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
4✔
4851
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4✔
4852
  if (!pInfo) {
4!
4853
    return 0;
×
4854
  }
4855

4856
  void* pData = (buf == NULL) ? NULL : *buf;
4✔
4857

4858
  // 1.streamAggSup.pResultRows
4859
  int32_t tlen = 0;
4✔
4860
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
4✔
4861
  tlen += taosEncodeFixedI32(buf, mapSize);
4✔
4862
  void*   pIte = NULL;
4✔
4863
  size_t  keyLen = 0;
4✔
4864
  int32_t iter = 0;
4✔
4865
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
8✔
4866
    void* key = tSimpleHashGetKey(pIte, &keyLen);
4✔
4867
    tlen += encodeSSessionKey(buf, key);
4✔
4868
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
4✔
4869
  }
4870

4871
  // 2.twAggSup
4872
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
4✔
4873

4874
  // 3.pChildren
4875
  int32_t size = taosArrayGetSize(pInfo->pChildren);
4✔
4876
  tlen += taosEncodeFixedI32(buf, size);
4✔
4877
  for (int32_t i = 0; i < size; i++) {
4!
4878
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4879
    tlen += doStreamStateEncodeOpState(buf, 0, pChOp, false);
×
4880
  }
4881

4882
  // 4.dataVersion
4883
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
4✔
4884

4885
  // 5.basicInfo
4886
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
4✔
4887

4888
  // 6.checksum
4889
  if (isParent) {
4!
4890
    if (buf) {
4✔
4891
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
4!
4892
      tlen += taosEncodeFixedU32(buf, cksum);
2✔
4893
    } else {
4894
      tlen += sizeof(uint32_t);
2✔
4895
    }
4896
  }
4897

4898
  return tlen;
4✔
4899
}
4900

4901
int32_t doStreamStateDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
1✔
4902
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
1✔
4903
  int32_t                      code = TSDB_CODE_SUCCESS;
1✔
4904
  int32_t                      lino = 0;
1✔
4905
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
1✔
4906
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1✔
4907
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
1✔
4908
  if (!pInfo) {
1!
4909
    code = TSDB_CODE_FAILED;
×
4910
    QUERY_CHECK_CODE(code, lino, _end);
×
4911
  }
4912

4913
  // 6.checksum
4914
  if (isParent) {
1!
4915
    int32_t dataLen = len - sizeof(uint32_t);
1✔
4916
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
1✔
4917
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
2!
4918
      qError("stream state_window state is invalid");
×
4919
      code = TSDB_CODE_FAILED;
×
4920
      QUERY_CHECK_CODE(code, lino, _end);
×
4921
    }
4922
    pDataEnd = pCksum;
1✔
4923
  }
4924

4925
  // 1.streamAggSup.pResultRows
4926
  int32_t mapSize = 0;
1✔
4927
  buf = taosDecodeFixedI32(buf, &mapSize);
1!
4928
  for (int32_t i = 0; i < mapSize; i++) {
2✔
4929
    SResultWindowInfo winfo = {0};
1✔
4930
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
1✔
4931
    int32_t winCode = TSDB_CODE_SUCCESS;
1✔
4932
    code = pAggSup->stateStore.streamStateStateAddIfNotExist(
1✔
4933
        pAggSup->pState, &winfo.sessionWin, NULL, pAggSup->stateKeySize, compareStateKey, (void**)&winfo.pStatePos,
4934
        &pAggSup->resultRowSize, &winCode);
4935
    QUERY_CHECK_CODE(code, lino, _end);
1!
4936

4937
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
1✔
4938
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
1✔
4939
                          sizeof(SResultWindowInfo));
4940
    QUERY_CHECK_CODE(code, lino, _end);
1!
4941
  }
4942

4943
  // 2.twAggSup
4944
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
1✔
4945

4946
  // 3.pChildren
4947
  int32_t size = 0;
1✔
4948
  buf = taosDecodeFixedI32(buf, &size);
1!
4949
  for (int32_t i = 0; i < size; i++) {
1!
4950
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4951
    code = doStreamStateDecodeOpState(buf, 0, pChOp, false, &buf);
×
4952
    QUERY_CHECK_CODE(code, lino, _end);
×
4953
  }
4954

4955
  // 4.dataVersion
4956
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
1!
4957

4958
  if (ppBuf) {
1!
4959
    (*ppBuf) = buf;
×
4960
  }
4961

4962
  // 5.basicInfo
4963
  if (buf < pDataEnd) {
1!
4964
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
1✔
4965
    QUERY_CHECK_CODE(code, lino, _end);
1!
4966
  }
4967

4968
_end:
1✔
4969
  if (code != TSDB_CODE_SUCCESS) {
1!
4970
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4971
  }
4972
  return code;
1✔
4973
}
4974

4975
void doStreamStateSaveCheckpoint(SOperatorInfo* pOperator) {
449✔
4976
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
449✔
4977
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
449✔
4978
    int32_t len = doStreamStateEncodeOpState(NULL, 0, pOperator, true);
2✔
4979
    void*   buf = taosMemoryCalloc(1, len);
2!
4980
    if (!buf) {
2!
4981
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
4982
      return;
×
4983
    }
4984
    void* pBuf = buf;
2✔
4985
    len = doStreamStateEncodeOpState(&pBuf, len, pOperator, true);
2✔
4986
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
2✔
4987
                                                       strlen(STREAM_STATE_OP_CHECKPOINT_NAME), buf, len);
4988
    taosMemoryFree(buf);
2!
4989
    saveStreamOperatorStateComplete(&pInfo->basic);
2✔
4990
  }
4991
}
4992

4993
static int32_t buildStateResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,238✔
4994
  int32_t                      code = TSDB_CODE_SUCCESS;
4,238✔
4995
  int32_t                      lino = 0;
4,238✔
4996
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4,238✔
4997
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
4,238✔
4998
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4,238✔
4999
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
4,238✔
5000
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
4,238✔
5001
  bool                         addNotifyEvent = false;
4,238✔
5002
  addNotifyEvent = BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
4,238✔
5003
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
4,238✔
5004
  if (pInfo->pDelRes->info.rows > 0) {
4,238✔
5005
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
207✔
5006
    if (addNotifyEvent) {
207!
5007
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
5008
      QUERY_CHECK_CODE(code, lino, _end);
×
5009
    }
5010
    (*ppRes) = pInfo->pDelRes;
207✔
5011
    return code;
207✔
5012
  }
5013

5014
  doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes,
4,031!
5015
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
5016
  if (pBInfo->pRes->info.rows > 0) {
4,032✔
5017
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,298✔
5018
    if (addNotifyEvent) {
1,298!
5019
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
5020
                                     pNotifySup, pNotifyEventStat);
5021
      QUERY_CHECK_CODE(code, lino, _end);
×
5022
    }
5023
    (*ppRes) = pBInfo->pRes;
1,298✔
5024
    return code;
1,298✔
5025
  }
5026

5027
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
2,734✔
5028
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5029
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
2,734!
5030
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5031
    (*ppRes) = pNotifySup->pEventBlock;
×
5032
    return code;
×
5033
  }
5034

5035
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
2,734✔
5036
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5037

5038
_end:
2,734✔
5039
  if (code != TSDB_CODE_SUCCESS) {
2,734!
5040
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5041
  }
5042
  (*ppRes) = NULL;
2,734✔
5043
  return code;
2,734✔
5044
}
5045

5046
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,642✔
5047
  if (pOperator->status == OP_EXEC_DONE) {
4,642!
5048
    (*ppRes) = NULL;
×
5049
    return TSDB_CODE_SUCCESS;
×
5050
  }
5051

5052
  int32_t                      code = TSDB_CODE_SUCCESS;
4,642✔
5053
  int32_t                      lino = 0;
4,642✔
5054
  SExprSupp*                   pSup = &pOperator->exprSupp;
4,642✔
5055
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4,642✔
5056
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
4,642✔
5057
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4,642✔
5058
  qDebug("===stream=== stream state agg");
4,642✔
5059
  if (pOperator->status == OP_RES_TO_RETURN) {
4,642✔
5060
    SSDataBlock* resBlock = NULL;
1,505✔
5061
    code = buildStateResult(pOperator, &resBlock);
1,505✔
5062
    QUERY_CHECK_CODE(code, lino, _end);
1,505!
5063
    if (resBlock != NULL) {
1,505✔
5064
      (*ppRes) = resBlock;
363✔
5065
      return code;
1,505✔
5066
    }
5067

5068
    if (pInfo->recvGetAll) {
1,142✔
5069
      pInfo->recvGetAll = false;
3✔
5070
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
3✔
5071
    }
5072

5073
    if (pInfo->reCkBlock) {
1,142!
5074
      pInfo->reCkBlock = false;
×
5075
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5076
      (*ppRes) = pInfo->pCheckpointRes;
×
5077
      return code;
×
5078
    }
5079

5080
    setStreamOperatorCompleted(pOperator);
1,142✔
5081
    (*ppRes) = NULL;
1,142✔
5082
    return code;
1,142✔
5083
  }
5084

5085
  SOperatorInfo* downstream = pOperator->pDownstream[0];
3,137✔
5086
  if (!pInfo->pUpdated) {
3,137✔
5087
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,734✔
5088
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,734!
5089
  }
5090
  if (!pInfo->pSeUpdated) {
3,137✔
5091
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,701✔
5092
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,701✔
5093
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,701!
5094
  }
5095
  while (1) {
4,203✔
5096
    SSDataBlock* pBlock = NULL;
7,340✔
5097
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,340✔
5098
    QUERY_CHECK_CODE(code, lino, _end);
7,340!
5099

5100
    if (pBlock == NULL) {
7,340✔
5101
      break;
2,734✔
5102
    }
5103
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,606✔
5104
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,607✔
5105

5106
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,607✔
5107
        pBlock->info.type == STREAM_CLEAR) {
4,126✔
5108
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
546!
5109
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
546✔
5110
                                   pInfo->pPkDeleted, add);
5111
      QUERY_CHECK_CODE(code, lino, _end);
546!
5112
      continue;
1,005✔
5113
    } else if (pBlock->info.type == STREAM_GET_ALL) {
4,061✔
5114
      pInfo->recvGetAll = true;
10✔
5115
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
10✔
5116
      QUERY_CHECK_CODE(code, lino, _end);
10!
5117
      continue;
10✔
5118
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
4,051✔
5119
      (*ppRes) = pBlock;
404✔
5120
      return code;
404✔
5121
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,647✔
5122
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
449✔
5123
      doStreamStateSaveCheckpoint(pOperator);
449✔
5124
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
449✔
5125
      QUERY_CHECK_CODE(code, lino, _end);
449!
5126

5127
      continue;
449✔
5128
    } else {
5129
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
3,198!
5130
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5131
        QUERY_CHECK_CODE(code, lino, _end);
×
5132
      }
5133
    }
5134

5135
    if (pInfo->scalarSupp.pExprInfo != NULL) {
3,198✔
5136
      SExprSupp* pExprSup = &pInfo->scalarSupp;
256✔
5137
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
256✔
5138
      QUERY_CHECK_CODE(code, lino, _end);
256!
5139
    }
5140
    // the pDataBlock are always the same one, no need to call this again
5141
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3,198✔
5142
    QUERY_CHECK_CODE(code, lino, _end);
3,198!
5143
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
3,198✔
5144
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
3,198✔
5145
  }
5146
  // restore the value
5147
  pOperator->status = OP_RES_TO_RETURN;
2,734✔
5148

5149
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,734✔
5150
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5151

5152
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,734✔
5153
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5154

5155
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,734✔
5156

5157
  if (pInfo->isHistoryOp) {
2,734✔
5158
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
102✔
5159
    QUERY_CHECK_CODE(code, lino, _end);
102!
5160
  }
5161
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,734!
5162
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
3✔
5163
    QUERY_CHECK_CODE(code, lino, _end);
3!
5164
  }
5165

5166
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,734✔
5167
  pInfo->pUpdated = NULL;
2,734✔
5168
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,734✔
5169
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5170

5171
  SSDataBlock* resBlock = NULL;
2,734✔
5172
  code = buildStateResult(pOperator, &resBlock);
2,734✔
5173
  QUERY_CHECK_CODE(code, lino, _end);
2,734!
5174
  if (resBlock != NULL) {
2,734✔
5175
    (*ppRes) = resBlock;
1,142✔
5176
    return code;
1,142✔
5177
  }
5178

5179
_end:
1,592✔
5180
  if (code != TSDB_CODE_SUCCESS) {
1,592!
5181
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5182
    pTaskInfo->code = code;
×
5183
    T_LONG_JMP(pTaskInfo->env, code);
×
5184
  }
5185
  setStreamOperatorCompleted(pOperator);
1,592✔
5186
  (*ppRes) = NULL;
1,592✔
5187
  return code;
1,592✔
5188
}
5189

5190
static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
×
5191
  SSDataBlock* pRes = NULL;
×
5192
  int32_t      code = doStreamStateAggNext(pOperator, &pRes);
×
5193
  return pRes;
×
5194
}
5195

5196
void streamStateReleaseState(SOperatorInfo* pOperator) {
87✔
5197
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
87✔
5198
  int32_t                      winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
87✔
5199
  int32_t                      resSize = winSize + sizeof(TSKEY);
87✔
5200
  char*                        pBuff = taosMemoryCalloc(1, resSize);
87!
5201
  if (!pBuff) {
87!
5202
    return;
×
5203
  }
5204
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
87✔
5205
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
87✔
5206
  qDebug("===stream=== relase state. save result count:%d", (int32_t)taosArrayGetSize(pInfo->historyWins));
87✔
5207
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_STATE_NAME,
87✔
5208
                                                     strlen(STREAM_STATE_OP_STATE_NAME), pBuff, resSize);
5209
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
87✔
5210
  taosMemoryFreeClear(pBuff);
87!
5211

5212
  SOperatorInfo* downstream = pOperator->pDownstream[0];
87✔
5213
  if (downstream->fpSet.releaseStreamStateFn) {
87!
5214
    downstream->fpSet.releaseStreamStateFn(downstream);
87✔
5215
  }
5216
}
5217

5218
int32_t compactStateWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
×
5219
                           SSHashObj* pStUpdated, SSHashObj* pStDeleted) {
5220
  SExprSupp*                   pSup = &pOperator->exprSupp;
×
5221
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
5222
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
5223
  return compactTimeWindow(pSup, &pInfo->streamAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, pNextWin, pStUpdated,
×
5224
                           pStDeleted, false);
5225
}
5226

5227
void streamStateReloadState(SOperatorInfo* pOperator) {
87✔
5228
  int32_t                      code = TSDB_CODE_SUCCESS;
87✔
5229
  int32_t                      lino = 0;
87✔
5230
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
87✔
5231
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
87✔
5232
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
87✔
5233
  resetWinRange(&pAggSup->winRange);
87✔
5234

5235
  SSessionKey seKey = {.win.skey = INT64_MIN, .win.ekey = INT64_MIN, .groupId = 0};
87✔
5236
  int32_t     size = 0;
87✔
5237
  void*       pBuf = NULL;
87✔
5238
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_STATE_OP_STATE_NAME,
87✔
5239
                                                strlen(STREAM_STATE_OP_STATE_NAME), &pBuf, &size);
5240
  QUERY_CHECK_CODE(code, lino, _end);
87!
5241

5242
  int32_t num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
87✔
5243
  qDebug("===stream=== reload state. get result count:%d", num);
87✔
5244
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
87✔
5245

5246
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
87✔
5247
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
87✔
5248
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
87✔
5249

5250
  if (!pInfo->pSeUpdated && num > 0) {
87!
5251
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
33✔
5252
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
33✔
5253
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
33!
5254
  }
5255
  if (!pInfo->pSeDeleted && num > 0) {
87!
5256
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
5257
    pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
×
5258
    QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _end, terrno);
×
5259
  }
5260
  for (int32_t i = 0; i < num; i++) {
215✔
5261
    SStateWindowInfo curInfo = {0};
128✔
5262
    SStateWindowInfo nextInfo = {0};
128✔
5263
    qDebug("===stream=== reload state. try process result %" PRId64 ", %" PRIu64 ", index:%d", pSeKeyBuf[i].win.skey,
128✔
5264
           pSeKeyBuf[i].groupId, i);
5265
    code = getStateWindowInfoByKey(pAggSup, pSeKeyBuf + i, &curInfo, &nextInfo);
128✔
5266
    QUERY_CHECK_CODE(code, lino, _end);
128!
5267

5268
    bool cpRes = compareWinStateKey(curInfo.pStateKey, nextInfo.pStateKey);
128✔
5269
    qDebug("===stream=== reload state. next window info %" PRId64 ", %" PRIu64 ", compare:%d",
128✔
5270
           nextInfo.winInfo.sessionWin.win.skey, nextInfo.winInfo.sessionWin.groupId, cpRes);
5271
    if (cpRes) {
128!
5272
      code = compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pSeUpdated, pInfo->pSeDeleted);
×
5273
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, curInfo.winInfo.sessionWin.win.skey,
×
5274
             curInfo.winInfo.sessionWin.groupId);
5275
      QUERY_CHECK_CODE(code, lino, _end);
×
5276

5277
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
5278
        code = saveResult(curInfo.winInfo, pInfo->pSeUpdated);
×
5279
        QUERY_CHECK_CODE(code, lino, _end);
×
5280
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
5281
        if (!isCloseWindow(&curInfo.winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
5282
          code = saveDeleteRes(pInfo->pSeDeleted, curInfo.winInfo.sessionWin);
×
5283
          QUERY_CHECK_CODE(code, lino, _end);
×
5284
        }
5285
        SSessionKey key = {0};
×
5286
        getSessionHashKey(&curInfo.winInfo.sessionWin, &key);
×
5287
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curInfo.winInfo,
×
5288
                              sizeof(SResultWindowInfo));
5289
        QUERY_CHECK_CODE(code, lino, _end);
×
5290
      }
5291
    } else if (IS_VALID_SESSION_WIN(nextInfo.winInfo)) {
128!
5292
      releaseOutputBuf(pAggSup->pState, nextInfo.winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
5293
    }
5294

5295
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
128!
5296
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
128✔
5297
      QUERY_CHECK_CODE(code, lino, _end);
128!
5298
    }
5299
  }
5300
  taosMemoryFreeClear(pBuf);
87!
5301

5302
  SOperatorInfo* downstream = pOperator->pDownstream[0];
87✔
5303
  if (downstream->fpSet.reloadStreamStateFn) {
87!
5304
    downstream->fpSet.reloadStreamStateFn(downstream);
87✔
5305
  }
5306
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
87✔
5307

5308
_end:
87✔
5309
  taosMemoryFreeClear(pBuf);
87!
5310
  if (code != TSDB_CODE_SUCCESS) {
87!
5311
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5312
  }
5313
}
87✔
5314

5315
int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
356✔
5316
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5317
  QRY_PARAM_CHECK(pOptrInfo);
356!
5318
  int32_t code = 0;
356✔
5319
  int32_t lino = 0;
356✔
5320

5321
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
356✔
5322
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
356✔
5323
  SColumnNode*                 pColNode = (SColumnNode*)(pStateNode->pStateKey);
356✔
5324
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
356!
5325
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
356!
5326
  if (pInfo == NULL || pOperator == NULL) {
356!
5327
    code = terrno;
×
5328
    QUERY_CHECK_CODE(code, lino, _error);
×
5329
  }
5330

5331
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
356✔
5332
  initResultSizeInfo(&pOperator->resultInfo, 4096);
356✔
5333
  if (pStateNode->window.pExprs != NULL) {
356✔
5334
    int32_t    numOfScalar = 0;
25✔
5335
    SExprInfo* pScalarExprInfo = NULL;
25✔
5336
    code = createExprInfo(pStateNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
25✔
5337
    QUERY_CHECK_CODE(code, lino, _error);
25!
5338

5339
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
25✔
5340
    QUERY_CHECK_CODE(code, lino, _error);
25!
5341
  }
5342

5343
  pInfo->twAggSup = (STimeWindowAggSupp){
356✔
5344
      .waterMark = pStateNode->window.watermark,
356✔
5345
      .calTrigger = pStateNode->window.triggerType,
356✔
5346
      .maxTs = INT64_MIN,
5347
      .minTs = INT64_MAX,
5348
      .deleteMark = getDeleteMark(&pStateNode->window, 0),
356✔
5349
  };
5350

5351
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
356✔
5352
  QUERY_CHECK_CODE(code, lino, _error);
356!
5353

5354
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
356✔
5355
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
356!
5356
  pInfo->binfo.pRes = pResBlock;
356✔
5357

5358
  SExprSupp* pExpSup = &pOperator->exprSupp;
356✔
5359
  int32_t    numOfCols = 0;
356✔
5360
  SExprInfo* pExprInfo = NULL;
356✔
5361
  code = createExprInfo(pStateNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
356✔
5362
  QUERY_CHECK_CODE(code, lino, _error);
356!
5363

5364
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
356✔
5365
  if (code != TSDB_CODE_SUCCESS) {
355!
5366
    goto _error;
×
5367
  }
5368
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
355✔
5369
  int16_t type = pColNode->node.resType.type;
355✔
5370
  pInfo->primaryTsIndex = tsSlotId;
355✔
5371
  code =
5372
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize, type,
355✔
5373
                             &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
355✔
5374
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
5375
  QUERY_CHECK_CODE(code, lino, _error);
356!
5376

5377
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
356✔
5378
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
356✔
5379
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
356!
5380
  pInfo->pDelIterator = NULL;
356✔
5381

5382
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
356✔
5383
  QUERY_CHECK_CODE(code, lino, _error);
356!
5384

5385
  pInfo->pChildren = NULL;
356✔
5386
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
356✔
5387
  pInfo->ignoreExpiredDataSaved = false;
356✔
5388
  pInfo->pUpdated = NULL;
356✔
5389
  pInfo->pSeUpdated = NULL;
356✔
5390
  pInfo->dataVersion = 0;
356✔
5391
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
356✔
5392
  if (!pInfo->historyWins) {
356!
5393
    code = terrno;
×
5394
    QUERY_CHECK_CODE(code, lino, _error);
×
5395
  }
5396

5397
  if (pHandle) {
356!
5398
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
356✔
5399
  }
5400

5401
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
356✔
5402
  QUERY_CHECK_CODE(code, lino, _error);
356!
5403

5404
  pInfo->recvGetAll = false;
356✔
5405
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
356✔
5406
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
356!
5407
  pInfo->destHasPrimaryKey = pStateNode->window.destHasPrimaryKey;
356✔
5408
  pInfo->pOperator = pOperator;
356✔
5409

5410
  setOperatorInfo(pOperator, "StreamStateAggOperator", nodeType(pPhyNode), true, OP_NOT_OPENED,
356✔
5411
                  pInfo, pTaskInfo);
5412
  // for stream
5413
  void*   buff = NULL;
356✔
5414
  int32_t len = 0;
356✔
5415
  int32_t res =
5416
      pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
356✔
5417
                                                        strlen(STREAM_STATE_OP_CHECKPOINT_NAME), &buff, &len);
5418
  if (res == TSDB_CODE_SUCCESS) {
356✔
5419
    code = doStreamStateDecodeOpState(buff, len, pOperator, true, NULL);
1✔
5420
    taosMemoryFree(buff);
1!
5421
    QUERY_CHECK_CODE(code, lino, _error);
1!
5422
  }
5423
  initNonBlockAggSupptor(&pInfo->nbSup, NULL, NULL);
356✔
5424
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
356✔
5425
  QUERY_CHECK_CODE(code, lino, _error);
356!
5426

5427
  if (pStateNode->window.triggerType == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
356!
5428
    if (pHandle->fillHistory == STREAM_HISTORY_OPERATOR) {
×
5429
      setFillHistoryOperatorFlag(&pInfo->basic);
×
5430
    } else if (pHandle->fillHistory == STREAM_RECALCUL_OPERATOR) {
×
5431
      setRecalculateOperatorFlag(&pInfo->basic);
×
5432
    }
5433

5434
    pOperator->fpSet =
5435
        createOperatorFpSet(optrDummyOpenFn, doStreamStateNonblockAggNext, NULL, destroyStreamStateOperatorInfo,
×
5436
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5437
    setOperatorStreamStateFn(pOperator, streamStateNonblockReleaseState, streamStateNonblockReloadState);
×
5438
  } else {
5439
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAggNext, NULL, destroyStreamStateOperatorInfo,
356✔
5440
                                           optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5441
    setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
356✔
5442
  }
5443

5444
  code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
356✔
5445
                        &pInfo->twAggSup, &pInfo->basic, 0);
356✔
5446
  QUERY_CHECK_CODE(code, lino, _error);
356!
5447

5448
  code = appendDownstream(pOperator, &downstream, 1);
356✔
5449
  QUERY_CHECK_CODE(code, lino, _error);
356!
5450

5451
  pInfo->trueForLimit = pStateNode->trueForLimit;
356✔
5452

5453
  *pOptrInfo = pOperator;
356✔
5454
  return TSDB_CODE_SUCCESS;
356✔
5455

5456
_error:
×
5457
  if (pInfo != NULL) destroyStreamStateOperatorInfo(pInfo);
×
5458
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5459
  pTaskInfo->code = code;
×
5460
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5461
  return code;
×
5462
}
5463

5464
#ifdef BUILD_NO_CALL
5465
static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type) {
5466
  for (int i = 0; i < num; i++) {
5467
    if (type == STREAM_INVERT) {
5468
      fmSetInvertFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5469
    } else if (type == STREAM_NORMAL) {
5470
      fmSetNormalFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5471
    }
5472
  }
5473
}
5474
#endif
5475

5476
static int32_t doStreamIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
130,948✔
5477
  int32_t                      code = TSDB_CODE_SUCCESS;
130,948✔
5478
  int32_t                      lino = 0;
130,948✔
5479
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
130,948✔
5480
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
130,948✔
5481
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
130,948✔
5482
  SExprSupp*                   pSup = &pOperator->exprSupp;
130,948✔
5483

5484
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
130,948✔
5485

5486
  if (pOperator->status == OP_EXEC_DONE) {
130,948✔
5487
    (*ppRes) = NULL;
668✔
5488
    return code;
668✔
5489
  }
5490

5491
  if (pOperator->status == OP_RES_TO_RETURN) {
130,280✔
5492
    SSDataBlock* resBlock = NULL;
103,009✔
5493
    code = buildIntervalResult(pOperator, &resBlock);
103,009✔
5494
    QUERY_CHECK_CODE(code, lino, _end);
103,009!
5495
    if (resBlock != NULL) {
103,009✔
5496
      (*ppRes) = resBlock;
88,317✔
5497
      return code;
103,009✔
5498
    }
5499

5500
    if (pInfo->recvGetAll) {
14,692✔
5501
      pInfo->recvGetAll = false;
178✔
5502
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
178✔
5503
    }
5504

5505
    if (pInfo->reCkBlock) {
14,692✔
5506
      pInfo->reCkBlock = false;
121✔
5507
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
121✔
5508
      (*ppRes) = pInfo->pCheckpointRes;
121✔
5509
      return code;
121✔
5510
    }
5511

5512
    setStreamOperatorCompleted(pOperator);
14,571✔
5513
    (*ppRes) = NULL;
14,571✔
5514
    return code;
14,571✔
5515
  }
5516

5517
  SOperatorInfo* downstream = pOperator->pDownstream[0];
27,271✔
5518

5519
  if (!pInfo->pUpdated) {
27,271✔
5520
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
24,387✔
5521
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
24,384!
5522
  }
5523

5524
  if (!pInfo->pUpdatedMap) {
27,268✔
5525
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
24,384✔
5526
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
24,383✔
5527
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
24,393!
5528
  }
5529

5530
  while (1) {
1,113,128✔
5531
    SSDataBlock* pBlock = NULL;
1,140,405✔
5532
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,140,405✔
5533
    QUERY_CHECK_CODE(code, lino, _end);
1,140,401✔
5534

5535
    if (pBlock == NULL) {
1,140,381✔
5536
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
24,388✔
5537
             pInfo->numOfDatapack);
5538
      pInfo->numOfDatapack = 0;
24,388✔
5539
      break;
24,388✔
5540
    }
5541

5542
    pInfo->numOfDatapack++;
1,115,993✔
5543
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
1,115,993✔
5544
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
1,115,992✔
5545

5546
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
1,115,991✔
5547
        pBlock->info.type == STREAM_CLEAR) {
1,115,492✔
5548
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,441✔
5549
      QUERY_CHECK_CODE(code, lino, _end);
1,442!
5550
      continue;
3,818✔
5551
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,114,550✔
5552
      pInfo->recvGetAll = true;
1,018✔
5553
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
1,018✔
5554
      QUERY_CHECK_CODE(code, lino, _end);
1,018!
5555
      continue;
1,018✔
5556
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
1,113,532✔
5557
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,812✔
5558
      (*ppRes) = pBlock;
2,812✔
5559
      return code;
2,867✔
5560
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
1,110,720✔
5561
      doDeleteWindowByGroupId(pOperator, pBlock);
55✔
5562
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
55✔
5563
      (*ppRes) = pBlock;
55✔
5564
      return code;
55✔
5565
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,110,665✔
5566
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,358✔
5567
      doStreamIntervalSaveCheckpoint(pOperator);
1,358✔
5568
      pInfo->reCkBlock = true;
1,358✔
5569
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,358✔
5570
      QUERY_CHECK_CODE(code, lino, _end);
1,358!
5571

5572
      continue;
1,358✔
5573
    } else {
5574
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,109,307!
5575
        qDebug("===stream===%s ignore recv block. type:%d", GET_TASKID(pTaskInfo), pBlock->info.type);
×
5576
        continue;
×
5577
      }
5578
    }
5579

5580
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
1,109,307✔
5581
      // set input version
5582
      pTaskInfo->version = pBlock->info.version;
321,831✔
5583
    }
5584

5585
    if (pInfo->scalarSupp.pExprInfo != NULL) {
1,109,307✔
5586
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5587
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5588
      QUERY_CHECK_CODE(code, lino, _end);
13!
5589
    }
5590

5591
    // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
5592
    // caller. Note that all the time window are not close till now.
5593
    // the pDataBlock are always the same one, no need to call this again
5594
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
1,109,307✔
5595
    QUERY_CHECK_CODE(code, lino, _end);
1,109,307!
5596
#ifdef BUILD_NO_CALL
5597
    if (pInfo->invertible) {
5598
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
5599
    }
5600
#endif
5601

5602
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
1,109,307✔
5603
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
1,109,310!
5604
      pOperator->status = OP_RES_TO_RETURN;
×
5605
      code = TSDB_CODE_SUCCESS;
×
5606
      break;
×
5607
    }
5608
    QUERY_CHECK_CODE(code, lino, _end);
1,109,310!
5609
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
1,109,310✔
5610
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
1,109,310✔
5611
  }
5612
  pOperator->status = OP_RES_TO_RETURN;
24,388✔
5613
  if (!pInfo->destHasPrimaryKey) {
24,388✔
5614
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
24,373✔
5615
  }
5616
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
24,385✔
5617
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5618
  QUERY_CHECK_CODE(code, lino, _end);
24,386!
5619

5620
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
24,386!
5621
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
16✔
5622
    QUERY_CHECK_CODE(code, lino, _end);
16!
5623
  }
5624

5625
  void*   pIte = NULL;
24,386✔
5626
  int32_t iter = 0;
24,386✔
5627
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
8,825,557✔
5628
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
8,801,171✔
5629
    if (!tmp) {
8,801,171!
5630
      code = terrno;
×
5631
      QUERY_CHECK_CODE(code, lino, _end);
×
5632
    }
5633
  }
5634
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
24,386✔
5635

5636
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
24,389✔
5637
  pInfo->pUpdated = NULL;
24,389✔
5638
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
24,389✔
5639
  QUERY_CHECK_CODE(code, lino, _end);
24,390!
5640

5641
  tSimpleHashCleanup(pInfo->pUpdatedMap);
24,390✔
5642
  pInfo->pUpdatedMap = NULL;
24,390✔
5643

5644
  code = buildIntervalResult(pOperator, ppRes);
24,390✔
5645
  QUERY_CHECK_CODE(code, lino, _end);
24,388!
5646

5647
  return code;
24,388✔
5648

5649
_end:
20✔
5650
  if (code != TSDB_CODE_SUCCESS) {
20!
5651
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
20!
5652
    pTaskInfo->code = code;
20✔
5653
    T_LONG_JMP(pTaskInfo->env, code);
20!
5654
  }
5655
  setStreamOperatorCompleted(pOperator);
×
5656
  (*ppRes) = NULL;
×
5657
  return code;
×
5658
}
5659

5660
int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
3,062✔
5661
                                               SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
5662
                                               SOperatorInfo** pOptrInfo) {
5663
  QRY_PARAM_CHECK(pOptrInfo);
3,062!
5664

5665
  int32_t code = TSDB_CODE_SUCCESS;
3,062✔
5666
  int32_t lino = 0;
3,062✔
5667
  int32_t numOfCols = 0;
3,062✔
5668

5669
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
3,062!
5670
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3,064!
5671
  if (pInfo == NULL || pOperator == NULL) {
3,064!
5672
    code = terrno;
×
5673
    QUERY_CHECK_CODE(code, lino, _error);
×
5674
  }
5675

5676
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3,064✔
5677

5678
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3,064✔
5679
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
3,064!
5680
  initBasicInfo(&pInfo->binfo, pResBlock);
3,064✔
5681

5682
  pInfo->interval = (SInterval){
3,064✔
5683
      .interval = pIntervalPhyNode->interval,
3,064✔
5684
      .sliding = pIntervalPhyNode->sliding,
3,064✔
5685
      .intervalUnit = pIntervalPhyNode->intervalUnit,
3,064✔
5686
      .slidingUnit = pIntervalPhyNode->slidingUnit,
3,064✔
5687
      .offset = pIntervalPhyNode->offset,
3,064✔
5688
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
3,064✔
5689
      .timeRange = pIntervalPhyNode->timeRange,
3,064✔
5690
  };
5691
  calcIntervalAutoOffset(&pInfo->interval);
3,064✔
5692

5693
  pInfo->twAggSup =
3,064✔
5694
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
3,064✔
5695
                           .calTrigger = pIntervalPhyNode->window.triggerType,
3,064✔
5696
                           .maxTs = INT64_MIN,
5697
                           .minTs = INT64_MAX,
5698
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
3,064✔
5699

5700
  pOperator->pTaskInfo = pTaskInfo;
3,064✔
5701
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,064✔
5702

5703
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
3,064✔
5704
  pInfo->ignoreExpiredDataSaved = false;
3,064✔
5705

5706
  SExprSupp* pSup = &pOperator->exprSupp;
3,064✔
5707
  pSup->hasWindowOrGroup = true;
3,064✔
5708

5709
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
3,064✔
5710
  QUERY_CHECK_CODE(code, lino, _error);
3,063!
5711

5712
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
3,063✔
5713
  initResultSizeInfo(&pOperator->resultInfo, 4096);
3,063✔
5714

5715
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
3,063!
5716
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
3,063!
5717
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
3,063✔
5718
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
3,063✔
5719

5720
  size_t     keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
3,063✔
5721
  SExprInfo* pExprInfo = NULL;
3,063✔
5722
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
3,063✔
5723
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5724
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str, pInfo->pState,
3,064✔
5725
                    &pTaskInfo->storageAPI.functionStore);
5726
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5727

5728
  if (pIntervalPhyNode->window.pExprs != NULL) {
3,064✔
5729
    int32_t    numOfScalar = 0;
1✔
5730
    SExprInfo* pScalarExprInfo = NULL;
1✔
5731

5732
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5733
    QUERY_CHECK_CODE(code, lino, _error);
1!
5734

5735
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
5736
    QUERY_CHECK_CODE(code, lino, _error);
1!
5737
  }
5738

5739
  pInfo->invertible = false;
3,064✔
5740
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
3,064✔
5741
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
3,064!
5742
  pInfo->delIndex = 0;
3,064✔
5743

5744
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
3,064✔
5745
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5746

5747
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
3,064✔
5748

5749
  pInfo->pPhyNode = NULL;  // create new child
3,064✔
5750
  pInfo->pPullDataMap = NULL;
3,064✔
5751
  pInfo->pFinalPullDataMap = NULL;
3,064✔
5752
  pInfo->pPullWins = NULL;  // SPullWindowInfo
3,064✔
5753
  pInfo->pullIndex = 0;
3,064✔
5754
  pInfo->pPullDataRes = NULL;
3,064✔
5755
  pInfo->numOfChild = 0;
3,064✔
5756
  pInfo->delKey.ts = INT64_MAX;
3,064✔
5757
  pInfo->delKey.groupId = 0;
3,064✔
5758
  pInfo->numOfDatapack = 0;
3,064✔
5759
  pInfo->pUpdated = NULL;
3,064✔
5760
  pInfo->pUpdatedMap = NULL;
3,064✔
5761
  int32_t funResSize = getMaxFunResSize(pSup, numOfCols);
3,064✔
5762

5763
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
3,064✔
5764
  pInfo->pState->pFileState = NULL;
3,064✔
5765

5766
  // used for backward compatibility of function's result info
5767
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
3,064✔
5768
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
3,064✔
5769
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
3,064✔
5770

5771
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
3,064✔
5772
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
3,064✔
5773
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
3,064✔
5774
      &pInfo->pState->pFileState);
3,064✔
5775
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5776

5777
  pInfo->pOperator = pOperator;
3,064✔
5778
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
3,064✔
5779
                  pInfo, pTaskInfo);
5780
  pOperator->fpSet =
5781
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
3,064✔
5782
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5783
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
3,064✔
5784

5785
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
3,064✔
5786
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5787

5788
  pInfo->recvGetAll = false;
3,064✔
5789

5790
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
3,064✔
5791
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5792

5793
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,064✔
5794
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
3,064✔
5795
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
3,063!
5796
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
3,063✔
5797

5798
  // for stream
5799
  void*   buff = NULL;
3,063✔
5800
  int32_t len = 0;
3,063✔
5801
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
3,063✔
5802
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
5803
  if (res == TSDB_CODE_SUCCESS) {
3,064✔
5804
    doStreamIntervalDecodeOpState(buff, len, pOperator);
15✔
5805
    taosMemoryFree(buff);
15!
5806
  }
5807

5808
  pInfo->basic.primaryPkIndex = -1;
3,064✔
5809
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
3,064✔
5810
  QUERY_CHECK_CODE(code, lino, _error);
3,063!
5811

5812
  code = appendDownstream(pOperator, &downstream, 1);
3,063✔
5813
  QUERY_CHECK_CODE(code, lino, _error);
3,064!
5814

5815
  *pOptrInfo = pOperator;
3,064✔
5816
  return TSDB_CODE_SUCCESS;
3,064✔
5817

5818
_error:
×
5819
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
5820
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5821
  pTaskInfo->code = code;
×
5822
  return code;
×
5823
}
5824

5825
static void doStreamMidIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pUpdatedMap) {
34✔
5826
  int32_t                      code = TSDB_CODE_SUCCESS;
34✔
5827
  int32_t                      lino = 0;
34✔
5828
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
34✔
5829
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
34✔
5830

5831
  SResultRowInfo*  pResultRowInfo = &(pInfo->binfo.resultRowInfo);
34✔
5832
  SExecTaskInfo*   pTaskInfo = pOperator->pTaskInfo;
34✔
5833
  SExprSupp*       pSup = &pOperator->exprSupp;
34✔
5834
  int32_t          numOfOutput = pSup->numOfExprs;
34✔
5835
  int32_t          step = 1;
34✔
5836
  SRowBuffPos*     pResPos = NULL;
34✔
5837
  SResultRow*      pResult = NULL;
34✔
5838
  int32_t          forwardRows = 1;
34✔
5839
  uint64_t         groupId = pSDataBlock->info.id.groupId;
34✔
5840
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
34✔
5841
  TSKEY*           tsCol = (int64_t*)pColDataInfo->pData;
34✔
5842

5843
  int32_t     startPos = 0;
34✔
5844
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
34✔
5845
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
34✔
5846

5847
  while (1) {
1,250✔
5848
    SWinKey key = {
1,284✔
5849
        .ts = nextWin.skey,
1,284✔
5850
        .groupId = groupId,
5851
    };
5852
    void*   chIds = taosHashGet(pInfo->pPullDataMap, &key, sizeof(SWinKey));
1,284✔
5853
    int32_t index = -1;
1,284✔
5854
    SArray* chArray = NULL;
1,284✔
5855
    int32_t chId = 0;
1,284✔
5856
    if (chIds) {
1,284✔
5857
      chArray = *(void**)chIds;
4✔
5858
      chId = getChildIndex(pSDataBlock);
4✔
5859
      index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
4✔
5860
    }
5861
    if (!(index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA)) {
1,284!
5862
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, startPos);
×
5863
      if (startPos < 0) {
×
5864
        break;
34✔
5865
      }
5866
      continue;
×
5867
    }
5868

5869
    if (!inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,284!
5870
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCol, startPos, nextWin.ekey, &nextWin);
×
5871
      if (startPos < 0) {
×
5872
        break;
×
5873
      }
5874
      continue;
×
5875
    }
5876

5877
    int32_t winCode = TSDB_CODE_SUCCESS;
1,284✔
5878
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
1,284✔
5879
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
5880
    QUERY_CHECK_CODE(code, lino, _end);
1,284!
5881

5882
    pResult = (SResultRow*)pResPos->pRowBuff;
1,284✔
5883

5884
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,284!
5885
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,284✔
5886
      QUERY_CHECK_CODE(code, lino, _end);
1,284!
5887
    }
5888

5889
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,284!
5890
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
×
5891
      QUERY_CHECK_CODE(code, lino, _end);
×
5892
    }
5893

5894
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
1,284✔
5895
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
1,284✔
5896
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
1,284✔
5897
    QUERY_CHECK_CODE(code, lino, _end);
1,284!
5898
    key.ts = nextWin.skey;
1,284✔
5899

5900
    if (pInfo->delKey.ts > key.ts) {
1,284✔
5901
      pInfo->delKey = key;
10✔
5902
    }
5903
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
1,284✔
5904
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
1,284!
5905
      qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64
×
5906
             ",maxKey %" PRId64,
5907
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5908
      code = blockDataUpdateTsWindow(pSDataBlock, 0);
×
5909
      QUERY_CHECK_CODE(code, lino, _end);
×
5910

5911
      // timestamp of the data is incorrect
5912
      if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
5913
        qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
5914
               pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5915
      }
5916
    }
5917
    startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, prevEndPos);
1,284✔
5918
    if (startPos < 0) {
1,284✔
5919
      break;
34✔
5920
    }
5921
  }
5922

5923
_end:
34✔
5924
  if (code != TSDB_CODE_SUCCESS) {
34!
5925
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5926
  }
5927
}
34✔
5928

5929
static int32_t addMidRetriveWindow(SArray* wins, SHashObj* pMidPullMap, int32_t numOfChild) {
12✔
5930
  int32_t code = TSDB_CODE_SUCCESS;
12✔
5931
  int32_t lino = 0;
12✔
5932
  int32_t size = taosArrayGetSize(wins);
12✔
5933
  for (int32_t i = 0; i < size; i++) {
18✔
5934
    SWinKey* winKey = taosArrayGet(wins, i);
6✔
5935
    void*    chIds = taosHashGet(pMidPullMap, winKey, sizeof(SWinKey));
6✔
5936
    if (!chIds) {
6!
5937
      code = addPullWindow(pMidPullMap, winKey, numOfChild);
6✔
5938
      qDebug("===stream===prepare mid operator retrive for delete %" PRId64 ", size:%d", winKey->ts, numOfChild);
6!
5939
      QUERY_CHECK_CODE(code, lino, _end);
6!
5940
    }
5941
  }
5942
_end:
12✔
5943
  if (code != TSDB_CODE_SUCCESS) {
12!
5944
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5945
  }
5946
  return code;
12✔
5947
}
5948

5949
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
105✔
5950
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
105✔
5951
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
105✔
5952
  uint16_t                     opType = pOperator->operatorType;
105✔
5953

5954
  if (pInfo->recvPullover) {
105✔
5955
    pInfo->recvPullover = false;
6✔
5956
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5957
    return pInfo->pMidPulloverRes;
6✔
5958
  }
5959

5960
  qDebug("===stream=== build mid interval result");
99!
5961
  doBuildDeleteResult(pTaskInfo, pInfo->pMidPullDatas, &pInfo->midDelIndex, pInfo->pDelRes);
99✔
5962
  if (pInfo->pDelRes->info.rows != 0) {
99!
5963
    // process the rest of the data
5964
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
×
5965
    return pInfo->pDelRes;
×
5966
  }
5967

5968
  if (pInfo->recvRetrive) {
99✔
5969
    pInfo->recvRetrive = false;
12✔
5970
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5971
    return pInfo->pMidRetriveRes;
12✔
5972
  }
5973

5974
  return NULL;
87✔
5975
}
5976

5977
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
99✔
5978
  int32_t                      code = TSDB_CODE_SUCCESS;
99✔
5979
  int32_t                      lino = 0;
99✔
5980
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
99✔
5981
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
99✔
5982
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
99✔
5983
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
99✔
5984
  SExprSupp*                   pSup = &pOperator->exprSupp;
99✔
5985

5986
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
99!
5987

5988
  if (pOperator->status == OP_EXEC_DONE) {
99!
5989
    (*ppRes) = NULL;
×
5990
    return code;
×
5991
  } else if (pOperator->status == OP_RES_TO_RETURN) {
99✔
5992
    SSDataBlock* resBlock = NULL;
30✔
5993
    code = buildIntervalResult(pOperator, &resBlock);
30✔
5994
    QUERY_CHECK_CODE(code, lino, _end);
30!
5995
    if (resBlock != NULL) {
30✔
5996
      (*ppRes) = resBlock;
6✔
5997
      return code;
30✔
5998
    }
5999

6000
    setOperatorCompleted(pOperator);
24✔
6001
    clearFunctionContext(&pOperator->exprSupp);
24✔
6002
    clearStreamIntervalOperator(pInfo);
24✔
6003
    qDebug("stask:%s  ===stream===%s clear", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType));
24!
6004
    (*ppRes) = NULL;
24✔
6005
    return code;
24✔
6006
  } else {
6007
    SSDataBlock* resBlock = NULL;
69✔
6008
    code = buildIntervalResult(pOperator, &resBlock);
69✔
6009
    QUERY_CHECK_CODE(code, lino, _end);
69!
6010
    if (resBlock != NULL) {
69!
6011
      (*ppRes) = resBlock;
×
6012
      return code;
3✔
6013
    }
6014

6015
    resBlock = buildMidIntervalResult(pOperator);
69✔
6016
    if (resBlock != NULL) {
69✔
6017
      (*ppRes) = resBlock;
3✔
6018
      return code;
3✔
6019
    }
6020

6021
    if (pInfo->clearState) {
66✔
6022
      pInfo->clearState = false;
18✔
6023
      clearFunctionContext(&pOperator->exprSupp);
18✔
6024
      clearStreamIntervalOperator(pInfo);
18✔
6025
    }
6026
  }
6027

6028
  if (!pInfo->pUpdated) {
66✔
6029
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
63✔
6030
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
63!
6031
  }
6032
  if (!pInfo->pUpdatedMap) {
66✔
6033
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
63✔
6034
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
63✔
6035
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
63!
6036
  }
6037

6038
  while (1) {
50✔
6039
    if (isTaskKilled(pTaskInfo)) {
116!
6040
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
6041
      (*ppRes) = NULL;
×
6042
      return code;
3✔
6043
    }
6044

6045
    SSDataBlock* pBlock = NULL;
116✔
6046
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
116✔
6047
    QUERY_CHECK_CODE(code, lino, _end);
116!
6048

6049
    if (pBlock == NULL) {
116✔
6050
      pOperator->status = OP_RES_TO_RETURN;
45✔
6051
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
45!
6052
             pInfo->numOfDatapack);
6053
      pInfo->numOfDatapack = 0;
45✔
6054
      break;
45✔
6055
    }
6056
    pInfo->numOfDatapack++;
71✔
6057
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
71✔
6058
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
71✔
6059

6060
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
71✔
6061
      pInfo->binfo.pRes->info.type = pBlock->info.type;
8✔
6062
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
63!
6063
               pBlock->info.type == STREAM_CLEAR) {
61✔
6064
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
3✔
6065
      if (!delWins) {
3!
6066
        code = terrno;
×
6067
        QUERY_CHECK_CODE(code, lino, _end);
×
6068
      }
6069
      code =
6070
          doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, pInfo->pFinalPullDataMap);
3✔
6071
      QUERY_CHECK_CODE(code, lino, _end);
3!
6072

6073
      removeResults(delWins, pInfo->pUpdatedMap);
3✔
6074
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
3✔
6075
      if (!tmp && taosArrayGetSize(delWins) > 0) {
3!
6076
        code = TSDB_CODE_OUT_OF_MEMORY;
×
6077
        QUERY_CHECK_CODE(code, lino, _end);
×
6078
      }
6079
      taosArrayDestroy(delWins);
3✔
6080

6081
      doBuildDeleteResult(pTaskInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
3✔
6082
      if (pInfo->pDelRes->info.rows != 0) {
3!
6083
        // process the rest of the data
6084
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
3✔
6085
        if (pBlock->info.type == STREAM_CLEAR) {
3✔
6086
          pInfo->pDelRes->info.type = STREAM_CLEAR;
1✔
6087
        } else {
6088
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
2✔
6089
        }
6090
        (*ppRes) = pInfo->pDelRes;
3✔
6091
        return code;
3✔
6092
      }
6093
      continue;
16✔
6094
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
60!
6095
      (*ppRes) = pBlock;
×
6096
      return code;
×
6097
    } else if (pBlock->info.type == STREAM_PULL_OVER) {
60✔
6098
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
12✔
6099
                             pInfo->numOfChild, pOperator, &pInfo->recvPullover);
6100
      QUERY_CHECK_CODE(code, lino, _end);
12!
6101

6102
      if (pInfo->recvPullover) {
12✔
6103
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
6104
        QUERY_CHECK_CODE(code, lino, _end);
6!
6105

6106
        pInfo->clearState = true;
6✔
6107
        break;
6✔
6108
      }
6109
      continue;
6✔
6110
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
48✔
6111
      pAPI->stateStore.streamStateCommit(pInfo->pState);
10✔
6112
      doStreamIntervalSaveCheckpoint(pOperator);
10✔
6113
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
10✔
6114
      QUERY_CHECK_CODE(code, lino, _end);
10!
6115

6116
      continue;
10✔
6117
    } else if (pBlock->info.type == STREAM_MID_RETRIEVE) {
38✔
6118
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
12✔
6119
      if (!delWins) {
12!
6120
        code = terrno;
×
6121
        QUERY_CHECK_CODE(code, lino, _end);
×
6122
      }
6123
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, NULL);
12✔
6124
      QUERY_CHECK_CODE(code, lino, _end);
12!
6125

6126
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
6127
      QUERY_CHECK_CODE(code, lino, _end);
12!
6128

6129
      taosArrayDestroy(delWins);
12✔
6130
      pInfo->recvRetrive = true;
12✔
6131
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
12✔
6132
      QUERY_CHECK_CODE(code, lino, _end);
12!
6133

6134
      pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
12✔
6135
      pInfo->clearState = true;
12✔
6136
      break;
12✔
6137
    } else {
6138
      if (pBlock->info.type != STREAM_INVALID) {
26!
6139
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
6140
        QUERY_CHECK_CODE(code, lino, _end);
×
6141
      }
6142
    }
6143

6144
    if (pInfo->scalarSupp.pExprInfo != NULL) {
34!
6145
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
6146
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
6147
      QUERY_CHECK_CODE(code, lino, _end);
×
6148
    }
6149
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
34✔
6150
    QUERY_CHECK_CODE(code, lino, _end);
34!
6151
    doStreamMidIntervalAggImpl(pOperator, pBlock, pInfo->pUpdatedMap);
34✔
6152
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
34✔
6153
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
34✔
6154
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
34✔
6155
  }
6156

6157
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
63✔
6158
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
63✔
6159

6160
  void*   pIte = NULL;
63✔
6161
  int32_t iter = 0;
63✔
6162
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,247✔
6163
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,184✔
6164
    if (!tmp) {
1,184!
6165
      code = terrno;
×
6166
      QUERY_CHECK_CODE(code, lino, _end);
×
6167
    }
6168
  }
6169

6170
  tSimpleHashCleanup(pInfo->pUpdatedMap);
63✔
6171
  pInfo->pUpdatedMap = NULL;
63✔
6172
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
63✔
6173

6174
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
63✔
6175
  pInfo->pUpdated = NULL;
63✔
6176
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
63✔
6177
  QUERY_CHECK_CODE(code, lino, _end);
63!
6178

6179
  SSDataBlock* resBlock = NULL;
63✔
6180
  code = buildIntervalResult(pOperator, &resBlock);
63✔
6181
  QUERY_CHECK_CODE(code, lino, _end);
63!
6182
  if (resBlock != NULL) {
63✔
6183
    (*ppRes) = resBlock;
27✔
6184
    return code;
27✔
6185
  }
6186

6187
  resBlock = buildMidIntervalResult(pOperator);
36✔
6188
  if (resBlock != NULL) {
36✔
6189
    (*ppRes) = resBlock;
15✔
6190
    return code;
15✔
6191
  }
6192

6193
  if (pInfo->clearState) {
21!
6194
    pInfo->clearState = false;
×
6195
    clearFunctionContext(&pOperator->exprSupp);
×
6196
    clearStreamIntervalOperator(pInfo);
×
6197
  }
6198

6199
_end:
21✔
6200
  if (code != TSDB_CODE_SUCCESS) {
21!
6201
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
6202
    pTaskInfo->code = code;
×
6203
    T_LONG_JMP(pTaskInfo->env, code);
×
6204
  }
6205
  (*ppRes) = NULL;
21✔
6206
  return code;
21✔
6207
}
6208

6209
static SSDataBlock* doStreamMidIntervalAgg(SOperatorInfo* pOperator) {
×
6210
  SSDataBlock* pRes = NULL;
×
6211
  int32_t      code = doStreamMidIntervalAggNext(pOperator, &pRes);
×
6212
  return pRes;
×
6213
}
6214

6215
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
35,966✔
6216
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
35,966✔
6217
         getStreamOpName(pOperator->operatorType), pOperator->status);
6218
  setOperatorCompleted(pOperator);
35,966✔
6219
}
35,969✔
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