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

taosdata / TDengine / #3746

26 Mar 2025 06:20AM UTC coverage: 60.312% (+0.2%) from 60.086%
#3746

push

travis-ci

web-flow
feat(taosBenchmark): supports decimal data type (#30456)

* feat: taosBenchmark supports decimal data type

* build: decimal script not use pytest.sh

* fix: fix typo for decimal script

* test: insertBasic.py debug

150489 of 318466 branches covered (47.25%)

Branch coverage included in aggregate %.

422 of 511 new or added lines in 9 files covered. (82.58%)

1153 existing lines in 21 files now uncovered.

233417 of 318070 relevant lines covered (73.39%)

12525884.77 hits per line

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

71.3
/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,562✔
51
  int firstPos = 0, lastPos = num - 1, midPos = -1;
1,562✔
52
  int numOfRows = 0;
1,562✔
53

54
  if (num <= 0) return -1;
1,562✔
55
  if (order == TSDB_ORDER_DESC) {
1,352!
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,432✔
59
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
363✔
60
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
198✔
61

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

65
      if (comparefn(pKey, keyList, midPos) < 0) {
149✔
66
        lastPos = midPos - 1;
46✔
67
      } else if (comparefn(pKey, keyList, midPos) > 0) {
103✔
68
        firstPos = midPos + 1;
34✔
69
      } else {
70
        break;
69✔
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;
69✔
102
}
103

104
static int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
148✔
105
  SArray*          res = (SArray*)data;
148✔
106
  SPullWindowInfo* pos = taosArrayGet(res, index);
148✔
107
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
148✔
108
  if (pData->groupId > pos->groupId) {
148✔
109
    return 1;
56✔
110
  } else if (pData->groupId < pos->groupId) {
92✔
111
    return -1;
37✔
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) {
223✔
123
  int32_t size = taosArrayGetSize(pPullWins);
223✔
124
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
223✔
125
  if (index == -1) {
223✔
126
    index = 0;
175✔
127
  } else {
128
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
48✔
129
    if (code == 0) {
48✔
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) {
45!
137
      index++;
45✔
138
    }
139
  }
140
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
220!
141
    return terrno;
×
142
  }
143
  return TSDB_CODE_SUCCESS;
220✔
144
}
145

146
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
10,509✔
147
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
10,509!
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,508✔
152
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
10,508✔
153
}
154

155
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
9,963,842✔
156
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
9,963,842!
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,963,821✔
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,406✔
183
  void* pDataPos = taosArrayGet((SArray*)data, index);
3,406✔
184
  return winKeyCmprImpl(pKey, pDataPos);
3,406✔
185
}
186

187
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
32,698✔
188
  taosArraySort(pDelWins, winKeyCmprImpl);
32,698✔
189
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
32,698✔
190
  int32_t delSize = taosArrayGetSize(pDelWins);
32,698✔
191
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
32,698✔
192
    return;
32,120✔
193
  }
194
  void*   pIte = NULL;
578✔
195
  int32_t iter = 0;
578✔
196
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,646✔
197
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
1,068✔
198
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
1,068✔
199
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
1,068✔
200
      taosArrayRemove(pDelWins, index);
877✔
201
      delSize = taosArrayGetSize(pDelWins);
877✔
202
    }
203
  }
204
}
205

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

210
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
46,685,046✔
211

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

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

222
int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,455✔
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) {
70✔
235
      size_t keyLen = 0;
15✔
236
      SWinKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
15!
237
      if (pKey->groupId == groupId) {
15!
238
        int32_t tmpRes = tSimpleHashIterateRemove(pInfo->aggSup.pResultRowHashTable, pKey, keyLen, &pIte, &iter);
15✔
239
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
15!
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,407✔
248
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
249
  int32_t                      code = TSDB_CODE_SUCCESS;
2,407✔
250
  int32_t                      lino = 0;
2,407✔
251
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,407✔
252
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2,407✔
253
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,407✔
254
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
2,407✔
255
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,407✔
256
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
2,407✔
257
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
2,407✔
258
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
2,407✔
259
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
2,407✔
260
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
2,407✔
261
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,407✔
262
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
2,407✔
263
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5,108✔
264
    SResultRowInfo dumyInfo = {0};
2,701✔
265
    dumyInfo.cur.pageId = -1;
2,701✔
266

267
    STimeWindow win = {0};
2,701✔
268
    if (IS_FINAL_INTERVAL_OP(pOperator) || IS_MID_INTERVAL_OP(pOperator)) {
2,701✔
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,440✔
273
    }
274

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

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

323
static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) {
1,055✔
324
  void*   pIte = NULL;
1,055✔
325
  int32_t iter = 0;
1,055✔
326
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1,373✔
327
    SWinKey*     pKey = tSimpleHashGetKey(pIte, NULL);
318✔
328
    uint64_t     groupId = pKey->groupId;
318✔
329
    TSKEY        ts = pKey->ts;
318✔
330
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
318✔
331
    if (!pPos->beUpdated) {
318✔
332
      continue;
9✔
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,055✔
341
}
342

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

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

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

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

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

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

410
void doBuildDeleteResultImpl(SStateStore* pAPI, SStreamState* pState, SArray* pWins, int32_t* index,
160,087✔
411
                             SSDataBlock* pBlock) {
412
  int32_t code = TSDB_CODE_SUCCESS;
160,087✔
413
  int32_t lino = 0;
160,087✔
414
  blockDataCleanup(pBlock);
160,087✔
415
  int32_t size = taosArrayGetSize(pWins);
160,088✔
416
  if (*index == size) {
160,088✔
417
    *index = 0;
159,353✔
418
    taosArrayClear(pWins);
159,353✔
419
    goto _end;
159,353✔
420
  }
421
  code = blockDataEnsureCapacity(pBlock, size - *index);
735✔
422
  QUERY_CHECK_CODE(code, lino, _end);
735!
423

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

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

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

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

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

465
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
4,126✔
466
  int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
4,126✔
467
  if (pGroupResInfo->index >= 0 && pGroupResInfo->index < size) {
4,127!
468
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
67,550✔
469
      void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
67,548✔
470
      destroyFlusedPos(pPos);
67,548✔
471
    }
472
  }
473

474
  pGroupResInfo->freeItem = false;
4,127✔
475
  taosArrayDestroy(pGroupResInfo->pRows);
4,127✔
476
  pGroupResInfo->pRows = NULL;
4,127✔
477
  pGroupResInfo->index = 0;
4,127✔
478
  pGroupResInfo->delIndex = 0;
4,127✔
479
}
4,127✔
480

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

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

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

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

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

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

535
  blockDataDestroy(pInfo->pCheckpointRes);
3,966✔
536

537
  taosMemoryFreeClear(param);
3,966!
538
}
539

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

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

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

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

563
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
10,529,302✔
564

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

572
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
4,007✔
573
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
257✔
574
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
257✔
575
  }
576

577
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
4,007✔
578
    return initIntervalDownStream(downstream->pDownstream[0], type, pInfo, pBasic);
257✔
579
  }
580

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

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

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

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

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

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

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

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

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

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

660
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
9,969,920✔
661
  QUERY_CHECK_CODE(code, lino, _end);
9,969,661!
662

663
  *pResult = (SRowBuffPos*)value;
9,969,661✔
664
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
9,969,661✔
665

666
  // set time window for current result
667
  res->win = (*win);
9,969,661✔
668
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
9,969,661✔
669
  QUERY_CHECK_CODE(code, lino, _end);
9,969,366!
670

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

678
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
35,802,798✔
679
                           SStateStore* pStore) {
680
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
35,802,798✔
681
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
25✔
682
    if (!hasIntervalWindow(pState, &key, pStore)) {
25✔
683
      return true;
15✔
684
    }
685
    return false;
10✔
686
  }
687
  return false;
35,802,773✔
688
}
689

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

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

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

727
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
3,588✔
728
  if (pBlock->info.rows <= 0) {
3,588✔
729
    return;
3,423✔
730
  }
731
  blockDataCleanup(pBlock);
165✔
732
}
733

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

920
static void clearFunctionContext(SExprSupp* pSup) {
2,372✔
921
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
25,399✔
922
    pSup->pCtx[i].saveHandle.currentPage = -1;
23,027✔
923
  }
924
}
2,372✔
925

926
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
9,487,576✔
927
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
9,487,576✔
928
}
929

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

941
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
116,533✔
942

943
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
9,506,376✔
944
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
9,487,615✔
945
    SResultRow*  pRow = NULL;
9,487,582✔
946
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
9,487,582✔
947
    QUERY_CHECK_CODE(code, lino, _end);
9,487,536!
948
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
9,487,536✔
949
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
9,487,536✔
950
    // no results, continue to check the next one
951
    if (pRow->numOfRows == 0) {
9,487,439!
952
      pGroupResInfo->index += 1;
×
953
      continue;
×
954
    }
955
    if (pBlock->info.id.groupId == 0) {
9,487,439✔
956
      pBlock->info.id.groupId = groupId;
572,579✔
957
      void*   tbname = NULL;
572,579✔
958
      int32_t winCode = TSDB_CODE_SUCCESS;
572,579✔
959
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
572,579✔
960
                                                    false, &winCode);
961
      QUERY_CHECK_CODE(code, lino, _end);
572,578!
962
      if (winCode != TSDB_CODE_SUCCESS) {
572,578✔
963
        pBlock->info.parTbName[0] = 0;
567,353✔
964
      } else {
965
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
5,225✔
966
      }
967
      pAPI->stateStore.streamStateFreeVal(tbname);
572,578✔
968
    } else {
969
      // current value belongs to different group, it can't be packed into one datablock
970
      if (pBlock->info.id.groupId != groupId) {
8,914,860✔
971
        break;
97,774✔
972
      }
973
    }
974

975
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
9,390,860✔
976
      break;
1,194✔
977
    }
978
    pGroupResInfo->index += 1;
9,389,666✔
979

980
    for (int32_t j = 0; j < numOfExprs; ++j) {
72,080,698✔
981
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
62,690,855✔
982

983
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
62,690,855✔
984

985
      if (pCtx[j].fpSet.finalize) {
62,690,741✔
986
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
41,642,646✔
987
        if (TAOS_FAILED(tmpRes)) {
41,642,775!
988
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
989
          QUERY_CHECK_CODE(code, lino, _end);
53!
990
        }
991
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
21,048,095✔
992
        // do nothing, todo refactor
993
      } else {
994
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
995
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
996
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
20,997,161✔
997
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
20,997,147✔
998
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
41,994,419✔
999
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
20,997,149✔
1000
          QUERY_CHECK_CODE(code, lino, _end);
20,997,272!
1001
        }
1002
      }
1003
    }
1004

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

1013
    pBlock->info.rows += pRow->numOfRows;
9,389,843✔
1014
  }
1015

1016
  pBlock->info.dataLoad = 1;
116,535✔
1017
  code = blockDataUpdateTsWindow(pBlock, 0);
116,535✔
1018
  QUERY_CHECK_CODE(code, lino, _end);
116,534!
1019

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

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

1032
  blockDataCleanup(pBlock);
159,789✔
1033
  taosArrayClear(pSessionKeys);
159,789✔
1034
  if (!hasRemainResults(pGroupResInfo)) {
159,789✔
1035
    return;
43,257✔
1036
  }
1037

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

1043
int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
234,243✔
1044
                                    TSKEY* primaryKeys, int32_t prevPosition) {
1045
  int32_t startPos = prevPosition + 1;
234,243✔
1046
  if (startPos == pDataBlockInfo->rows) {
234,243✔
1047
    startPos = -1;
2,187✔
1048
  } else {
1049
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
232,056✔
1050
  }
1051
  return startPos;
234,243✔
1052
}
1053

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

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

1072
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
544,873✔
1073
  tsCols = (int64_t*)pColDataInfo->pData;
544,876✔
1074

1075
  void*            pPkVal = NULL;
544,876✔
1076
  int32_t          pkLen = 0;
544,876✔
1077
  SColumnInfoData* pPkColDataInfo = NULL;
544,876✔
1078
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
544,876✔
1079
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
452,752✔
1080
  }
1081

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

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

1095
  int32_t     startPos = 0;
544,876✔
1096
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
544,876✔
1097
  STimeWindow nextWin = {0};
544,875✔
1098
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
544,875✔
1099
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,089✔
1100
  } else {
1101
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
542,786✔
1102
  }
1103
  while (1) {
9,423,814✔
1104
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
9,968,687✔
1105
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
9,968,553!
1106
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1107
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1108
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1109
    }
1110

1111
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
9,969,094✔
1112
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
594✔
1113
                          nextWin.ekey, pPkVal, pkLen)) ||
9,968,420✔
1114
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
9,968,477✔
1115
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
30✔
1116
      if (startPos < 0) {
42✔
1117
        break;
544,874✔
1118
      }
1119
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
19!
1120
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1121
      continue;
56✔
1122
    }
1123

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

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

1159
      if (ignore) {
232,838✔
1160
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
126✔
1161
        if (startPos < 0) {
126✔
1162
          break;
89✔
1163
        }
1164
        continue;
37✔
1165
      }
1166
    }
1167

1168
    int32_t winCode = TSDB_CODE_SUCCESS;
9,968,287✔
1169
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
9,968,287✔
1170
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1171
    QUERY_CHECK_CODE(code, lino, _end);
9,968,063!
1172

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

1181
    pResult = (SResultRow*)pResPos->pRowBuff;
9,968,063✔
1182

1183
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,968,063✔
1184
      forwardRows = 1;
232,712✔
1185
    } else {
1186
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
9,735,351✔
1187
                                             NULL, TSDB_ORDER_ASC);
1188
    }
1189

1190
    SWinKey key = {
9,968,902✔
1191
        .ts = pResult->win.skey,
9,968,902✔
1192
        .groupId = groupId,
1193
    };
1194

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

1200
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
9,968,902!
1201
      code = saveWinResult(&key, pResPos, pUpdatedMap);
9,960,332✔
1202
      QUERY_CHECK_CODE(code, lino, _end);
9,960,526!
1203
    }
1204

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

1211
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
9,969,094✔
1212
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
9,968,489✔
1213
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
9,968,489✔
1214
    QUERY_CHECK_CODE(code, lino, _end);
9,968,897!
1215
    key.ts = nextWin.skey;
9,968,897✔
1216

1217
    if (pInfo->delKey.ts > key.ts) {
9,968,897✔
1218
      pInfo->delKey = key;
2,066✔
1219
    }
1220
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
9,968,897✔
1221
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,968,897✔
1222
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
232,712✔
1223
    } else {
1224
      startPos =
1225
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
9,736,185✔
1226
    }
1227
    if (startPos < 0) {
9,968,520✔
1228
      break;
544,762✔
1229
    }
1230
  }
1231
_end:
544,874✔
1232
  if (code != TSDB_CODE_SUCCESS) {
544,874!
1233
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1234
  }
1235
  return code;
544,874✔
1236
}
1237

1238
int winPosCmprImpl(const void* pKey1, const void* pKey2) {
132,225,218✔
1239
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
132,225,218✔
1240
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
132,225,218✔
1241
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
132,225,218✔
1242
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
132,225,218✔
1243

1244
  if (pWin1->groupId > pWin2->groupId) {
132,225,218✔
1245
    return 1;
21,112,722✔
1246
  } else if (pWin1->groupId < pWin2->groupId) {
111,112,496✔
1247
    return -1;
19,713,173✔
1248
  }
1249

1250
  if (pWin1->ts > pWin2->ts) {
91,399,323✔
1251
    return 1;
46,016,717✔
1252
  } else if (pWin1->ts < pWin2->ts) {
45,382,606!
1253
    return -1;
45,390,018✔
1254
  }
1255

UNCOV
1256
  return 0;
×
1257
}
1258

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

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

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

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

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

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

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

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

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

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

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

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

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

1362
  void* pData = (buf == NULL) ? NULL : *buf;
70✔
1363

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

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

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

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

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

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

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

1413
  return tlen;
70✔
1414
}
1415

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1552
  // check if query task is closed or not
1553
  if (isTaskKilled(pTaskInfo)) {
157,420✔
1554
    (*ppRes) = NULL;
3✔
1555
    return code;
3✔
1556
  }
1557

1558
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
302,997✔
1559
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
145,580!
1560
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
157,417✔
1561
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
3,462✔
1562
    if (pInfo->pPullDataRes->info.rows != 0) {
3,462✔
1563
      // process the rest of the data
1564
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
163✔
1565
      (*ppRes) = pInfo->pPullDataRes;
163✔
1566
      return code;
163✔
1567
    }
1568
  }
1569

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

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

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

1603
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
40,529✔
1604
  QUERY_CHECK_CODE(code, lino, _end);
40,525!
1605

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

1614
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
18,323✔
1615
  int32_t code = TSDB_CODE_SUCCESS;
18,323✔
1616
  int32_t lino = 0;
18,323✔
1617
  void*   pIte = NULL;
18,323✔
1618
  int32_t iter = 0;
18,323✔
1619
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
490,497✔
1620
    void* tmp = taosArrayPush(pUpdated, pIte);
472,174✔
1621
    if (!tmp) {
472,174!
1622
      code = terrno;
×
1623
      QUERY_CHECK_CODE(code, lino, _end);
×
1624
    }
1625
  }
1626
  taosArraySort(pUpdated, compar);
18,324✔
1627
  tSimpleHashCleanup(*ppWinUpdated);
18,323✔
1628
  *ppWinUpdated = NULL;
18,327✔
1629

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

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

1644
  SOperatorInfo* downstream = pOperator->pDownstream[0];
11,805✔
1645
  SExprSupp*     pSup = &pOperator->exprSupp;
11,805✔
1646

1647
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
11,805✔
1648

1649
  if (pOperator->status == OP_EXEC_DONE) {
11,808!
1650
    (*ppRes) = NULL;
×
1651
    return code;
×
1652
  } else if (pOperator->status == OP_RES_TO_RETURN) {
11,808✔
1653
    SSDataBlock* resBlock = NULL;
3,988✔
1654
    code = buildIntervalResult(pOperator, &resBlock);
3,988✔
1655
    QUERY_CHECK_CODE(code, lino, _end);
3,987!
1656
    if (resBlock != NULL) {
3,987✔
1657
      (*ppRes) = resBlock;
801✔
1658
      return code;
3,988✔
1659
    }
1660

1661
    if (pInfo->recvGetAll) {
3,186✔
1662
      pInfo->recvGetAll = false;
82✔
1663
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
82✔
1664
    }
1665

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

1673
    setStreamOperatorCompleted(pOperator);
3,187✔
1674
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
3,186✔
1675
      clearFunctionContext(&pOperator->exprSupp);
1,795✔
1676
      // semi interval operator clear disk buffer
1677
      clearStreamIntervalOperator(pInfo);
1,796✔
1678
      qDebug("===stream===clear semi operator");
1,796✔
1679
    }
1680
    (*ppRes) = NULL;
3,187✔
1681
    return code;
3,187✔
1682
  } else {
1683
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
7,820✔
1684
      SSDataBlock* resBlock = NULL;
5,313✔
1685
      code = buildIntervalResult(pOperator, &resBlock);
5,313✔
1686
      QUERY_CHECK_CODE(code, lino, _end);
5,313!
1687
      if (resBlock != NULL) {
5,313!
1688
        (*ppRes) = resBlock;
×
1689
        return code;
×
1690
      }
1691

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

1701
  if (!pInfo->pUpdated) {
7,820✔
1702
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5,834✔
1703
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
5,835!
1704
  }
1705
  if (!pInfo->pUpdatedMap) {
7,821✔
1706
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5,835✔
1707
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5,834✔
1708
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
5,834!
1709
  }
1710

1711
  while (1) {
23,363✔
1712
    if (isTaskKilled(pTaskInfo)) {
31,183!
1713
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
1714
      (*ppRes) = NULL;
×
1715
      return code;
1,986✔
1716
    }
1717

1718
    SSDataBlock* pBlock = NULL;
31,183✔
1719
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
31,183✔
1720
    QUERY_CHECK_CODE(code, lino, _end);
31,186!
1721

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

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

1734
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
25,893✔
1735
      pInfo->binfo.pRes->info.type = pBlock->info.type;
21,039✔
1736
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,854✔
1737
               pBlock->info.type == STREAM_CLEAR) {
4,622✔
1738
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
408✔
1739
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
408!
1740
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
408✔
1741
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
408✔
1742
      QUERY_CHECK_CODE(code, lino, _end);
408!
1743

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

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

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

1780
      break;
×
1781
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
4,446!
1782
      pInfo->recvGetAll = true;
82✔
1783
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
82✔
1784
      QUERY_CHECK_CODE(code, lino, _end);
82!
1785
      continue;
82✔
1786
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
4,364✔
1787
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
542!
1788
        pInfo->recvRetrive = true;
542✔
1789
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
542✔
1790
        QUERY_CHECK_CODE(code, lino, _end);
542!
1791

1792
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
542✔
1793
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
542✔
1794
        QUERY_CHECK_CODE(code, lino, _end);
542!
1795
        break;
542✔
1796
      }
1797
      continue;
×
1798
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
3,822!
1799
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
536✔
1800
                             pInfo->numOfChild, pOperator, NULL);
1801
      QUERY_CHECK_CODE(code, lino, _end);
536!
1802
      continue;
536✔
1803
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,286✔
1804
      (*ppRes) = pBlock;
1,782✔
1805
      return code;
1,782✔
1806
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,504✔
1807
      pAPI->stateStore.streamStateCommit(pInfo->pState);
219✔
1808
      doStreamIntervalSaveCheckpoint(pOperator);
219✔
1809
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
219✔
1810
      QUERY_CHECK_CODE(code, lino, _end);
219!
1811

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

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

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

1841
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
5,835✔
1842
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,612✔
1843
  }
1844
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
5,835✔
1845
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,614✔
1846
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1847
    QUERY_CHECK_CODE(code, lino, _end);
1,614!
1848

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

1856
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
5,835✔
1857
  QUERY_CHECK_CODE(code, lino, _end);
5,835!
1858

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

1864
  SSDataBlock* resBlock = NULL;
5,835✔
1865
  code = buildIntervalResult(pOperator, &resBlock);
5,835✔
1866
  QUERY_CHECK_CODE(code, lino, _end);
5,834!
1867
  if (resBlock != NULL) {
5,834✔
1868
    (*ppRes) = resBlock;
3,187✔
1869
    return code;
3,187✔
1870
  }
1871

1872
  if (pInfo->recvRetrive) {
2,647✔
1873
    pInfo->recvRetrive = false;
541✔
1874
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
541✔
1875
    (*ppRes) = pInfo->pMidRetriveRes;
542✔
1876
    return code;
542✔
1877
  }
1878

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

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

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

1907
TSKEY compareTs(void* pKey) {
83,355,344✔
1908
  SWinKey* pWinKey = (SWinKey*)pKey;
83,355,344✔
1909
  return pWinKey->ts;
83,355,344✔
1910
}
1911

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

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

1926
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
6,157✔
1927
  int32_t size = 0;
6,157✔
1928
  for (int32_t i = 0; i < numOfCols; ++i) {
233,735✔
1929
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
227,570✔
1930
    size = TMAX(size, resSize);
227,578✔
1931
  }
1932
  return size;
6,165✔
1933
}
1934

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2165
  *pOptrInfo = pOperator;
891✔
2166
  return TSDB_CODE_SUCCESS;
891✔
2167

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

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

2186
void destroyResultWinInfo(void* pRes) {
×
2187
  SResultWindowInfo* pWinRes = (SResultWindowInfo*)pRes;
×
2188
  destroyFlusedPos(pWinRes->pStatePos);
×
2189
}
×
2190

2191
void clearSessionGroupResInfo(SGroupResInfo* pGroupResInfo) {
1,791✔
2192
  int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
1,791✔
2193
  if (pGroupResInfo->index >= 0 && pGroupResInfo->index < size) {
1,791!
2194
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
×
2195
      SResultWindowInfo* pRes = (SResultWindowInfo*) taosArrayGet(pGroupResInfo->pRows, i);
×
2196
      destroyFlusedPos(pRes->pStatePos);
×
2197
      pRes->pStatePos = NULL;
×
2198
    }
2199
  }
2200

2201
  pGroupResInfo->freeItem = false;
1,791✔
2202
  taosArrayDestroy(pGroupResInfo->pRows);
1,791✔
2203
  pGroupResInfo->pRows = NULL;
1,791✔
2204
  pGroupResInfo->index = 0;
1,791✔
2205
}
1,791✔
2206

2207
void destroyStreamSessionAggOperatorInfo(void* param) {
906✔
2208
  if (param == NULL) {
906!
2209
    return;
×
2210
  }
2211
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
906✔
2212
  cleanupBasicInfo(&pInfo->binfo);
906✔
2213
  if (pInfo->pOperator) {
906!
2214
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
906✔
2215
                              &pInfo->groupResInfo);
2216
    pInfo->pOperator = NULL;
906✔
2217
  }
2218

2219
  destroyStreamBasicInfo(&pInfo->basic);
906✔
2220
  cleanupExprSupp(&pInfo->scalarSupp);
906✔
2221
  clearSessionGroupResInfo(&pInfo->groupResInfo);
906✔
2222
  taosArrayDestroyEx(pInfo->pUpdated, destroyResultWinInfo);
906✔
2223
  pInfo->pUpdated = NULL;
906✔
2224
  destroyStreamAggSupporter(&pInfo->streamAggSup);
906✔
2225

2226
  if (pInfo->pChildren != NULL) {
906✔
2227
    int32_t size = taosArrayGetSize(pInfo->pChildren);
38✔
2228
    for (int32_t i = 0; i < size; i++) {
163✔
2229
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
125✔
2230
      destroyOperator(pChild);
125✔
2231
    }
2232
    taosArrayDestroy(pInfo->pChildren);
38✔
2233
  }
2234

2235
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
906✔
2236
  blockDataDestroy(pInfo->pDelRes);
906✔
2237
  blockDataDestroy(pInfo->pWinBlock);
906✔
2238
  tSimpleHashCleanup(pInfo->pStUpdated);
906✔
2239
  tSimpleHashCleanup(pInfo->pStDeleted);
906✔
2240
  cleanupGroupResInfo(&pInfo->groupResInfo);
906✔
2241

2242
  taosArrayDestroy(pInfo->historyWins);
906✔
2243
  blockDataDestroy(pInfo->pCheckpointRes);
906✔
2244
  tSimpleHashCleanup(pInfo->pPkDeleted);
906✔
2245
  destroyNonBlockAggSupptor(&pInfo->nbSup);
906✔
2246

2247
  taosMemoryFreeClear(param);
906!
2248
}
2249

2250
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
1,789✔
2251
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
2252
  initBasicInfo(pBasicInfo, pResultBlock);
1,789✔
2253
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
1,791✔
2254
  if (code != TSDB_CODE_SUCCESS) {
1,788!
2255
    return code;
×
2256
  }
2257

2258
  for (int32_t i = 0; i < numOfCols; ++i) {
28,545✔
2259
    pSup->pCtx[i].saveHandle.pBuf = NULL;
26,757✔
2260
  }
2261

2262
  return TSDB_CODE_SUCCESS;
1,788✔
2263
}
2264

2265
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
2,193✔
2266
  for (int i = 0; i < nums; i++) {
31,139✔
2267
    pDummy[i].functionId = pCtx[i].functionId;
28,946✔
2268
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
28,946✔
2269
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
28,946✔
2270
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
28,946✔
2271
  }
2272
}
2,193✔
2273

2274
int32_t initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
2,303✔
2275
                       STimeWindowAggSupp* pTwSup, struct SSteamOpBasicInfo* pBasic, int64_t recalculateInterval) {
2276
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
2,303✔
2277
  int32_t        code = TSDB_CODE_SUCCESS;
2,303✔
2278
  int32_t        lino = 0;
2,303✔
2279
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
2,303✔
2280
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
638✔
2281
    pScanInfo->tsColIndex = tsColIndex;
638✔
2282
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
638✔
2283
  }
2284

2285
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
2,303✔
2286
    code = initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup, pBasic, recalculateInterval);
638✔
2287
    return code;
638✔
2288
  }
2289
  SStreamScanInfo* pScanInfo = downstream->info;
1,665✔
2290
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
1,665✔
2291
  pScanInfo->pState = pAggSup->pState;
1,665✔
2292
  if (!pScanInfo->pUpdateInfo) {
1,665✔
2293
    code = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark,
1,027✔
2294
                                              pScanInfo->igCheckUpdate, pScanInfo->pkColType, pScanInfo->pkColLen,
1,027✔
2295
                                              &pScanInfo->pUpdateInfo);
1,027✔
2296
    QUERY_CHECK_CODE(code, lino, _end);
1,027!
2297
  }
2298
  pScanInfo->twAggSup = *pTwSup;
1,665✔
2299
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
1,665✔
2300
  if (!hasSrcPrimaryKeyCol(pBasic)) {
1,665✔
2301
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
1,662✔
2302
  }
2303

2304
  pBasic->pTsDataState = pScanInfo->basic.pTsDataState;
1,666✔
2305

2306
  if (type == QUERY_NODE_PHYSICAL_PLAN_STREAM_CONTINUE_SEMI_SESSION) {
1,666!
2307
    pScanInfo->scanAllTables = true;
×
2308
  }
2309
  pScanInfo->recalculateInterval = recalculateInterval;
1,666✔
2310
  pScanInfo->windowSup.parentType = type;
1,666✔
2311
  pScanInfo->recParam.gap = pAggSup->gap;
1,666✔
2312

2313
_end:
1,666✔
2314
  if (code != TSDB_CODE_SUCCESS) {
1,666!
2315
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2316
  }
2317
  return code;
1,666✔
2318
}
2319

2320
static TSKEY sesionTs(void* pKey) {
5,469✔
2321
  SSessionKey* pWinKey = (SSessionKey*)pKey;
5,469✔
2322
  return pWinKey->win.skey;
5,469✔
2323
}
2324

2325
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SExprSupp* pExpSup, int32_t numOfOutput, int64_t gap,
2,192✔
2326
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore,
2327
                               SReadHandle* pHandle, STimeWindowAggSupp* pTwAggSup, const char* taskIdStr,
2328
                               SStorageAPI* pApi, int32_t tsIndex, int8_t stateType, int32_t ratio) {
2329
  pSup->resultRowSize = (keySize + getResultRowSize(pExpSup->pCtx, numOfOutput)) * ratio;
2,192✔
2330
  int32_t lino = 0;
2,193✔
2331
  int32_t code = createSpecialDataBlock(STREAM_CLEAR, &pSup->pScanBlock);
2,193✔
2332
  QUERY_CHECK_CODE(code, lino, _end);
2,192!
2333

2334
  pSup->gap = gap;
2,192✔
2335
  pSup->stateKeySize = keySize;
2,192✔
2336
  pSup->stateKeyType = keyType;
2,192✔
2337
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
2,192!
2338
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
2,194!
2339

2340
  pSup->stateStore = *pStore;
2,194✔
2341
  pSup->pSessionAPI = pApi;
2,194✔
2342

2343
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
2,194✔
2344
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
2,192!
2345
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
2,194!
2346

2347
  *(pSup->pState) = *pState;
2,194✔
2348
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1, tsIndex);
2,194✔
2349
  int32_t funResSize = getMaxFunResSize(pExpSup, numOfOutput);
2,193✔
2350
  if (stateType != STREAM_STATE_BUFF_HASH_SORT) {
2,193✔
2351
    // used for backward compatibility of function's result info
2352
    pSup->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
1,952✔
2353
    pSup->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
1,952✔
2354
    pSup->pState->pExprSupp = pExpSup;
1,952✔
2355
  }
2356

2357
  if (stateType == STREAM_STATE_BUFF_SORT) {
2,193✔
2358
    pSup->pState->pFileState = NULL;
1,791✔
2359
    code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SSessionKey), pSup->resultRowSize,
1,791✔
2360
                                                funResSize, sesionTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
1,791✔
2361
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
1,791✔
2362
  } else if (stateType == STREAM_STATE_BUFF_HASH_SORT || stateType == STREAM_STATE_BUFF_HASH_SEARCH) {
402✔
2363
    pSup->pState->pFileState = NULL;
401✔
2364
    code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pSup->resultRowSize, funResSize,
401✔
2365
                                                compareTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
401✔
2366
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
401✔
2367
  }
2368
  QUERY_CHECK_CODE(code, lino, _end);
2,190!
2369

2370
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,190✔
2371
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
2,194✔
2372
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
2,189!
2373

2374
  for (int32_t i = 0; i < numOfOutput; ++i) {
31,068✔
2375
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
28,879✔
2376
  }
2377

2378
  pSup->pCur = NULL;
2,189✔
2379

2380
_end:
2,189✔
2381
  if (code != TSDB_CODE_SUCCESS) {
2,189!
2382
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2383
  }
2384
  return code;
2,185✔
2385
}
2386

2387
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5,691✔
2388
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5,691✔
2389
    return true;
4,175✔
2390
  }
2391
  return false;
1,516✔
2392
}
2393

2394
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
4,762✔
2395
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
4,762✔
2396
}
2397

2398
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
4,557✔
2399
                         SSessionKey* pKey) {
2400
  pKey->win.skey = startTs;
4,557✔
2401
  pKey->win.ekey = endTs;
4,557✔
2402
  pKey->groupId = groupId;
4,557✔
2403
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
4,557✔
2404
  if (code != TSDB_CODE_SUCCESS) {
4,557✔
2405
    SET_SESSION_WIN_KEY_INVALID(pKey);
1,296✔
2406
  }
2407
}
4,557✔
2408

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

2411
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
52,137✔
2412
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
52,137!
2413
    return true;
52,153✔
2414
  }
2415
  return false;
×
2416
}
2417

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

2420
int32_t setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
3,265✔
2421
                            SResultWindowInfo* pCurWin, int32_t* pWinCode) {
2422
  int32_t code = TSDB_CODE_SUCCESS;
3,265✔
2423
  int32_t lino = 0;
3,265✔
2424
  pCurWin->sessionWin.groupId = groupId;
3,265✔
2425
  pCurWin->sessionWin.win.skey = startTs;
3,265✔
2426
  pCurWin->sessionWin.win.ekey = endTs;
3,265✔
2427
  int32_t size = pAggSup->resultRowSize;
3,265✔
2428
  code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin, pAggSup->gap,
3,265✔
2429
                                                             (void**)&pCurWin->pStatePos, &size, pWinCode);
3,265✔
2430
  QUERY_CHECK_CODE(code, lino, _end);
3,266!
2431

2432
  if (*pWinCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->sessionWin.win)) {
3,266!
2433
    *pWinCode = TSDB_CODE_FAILED;
×
2434
    clearOutputBuf(pAggSup->pState, pCurWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2435
  }
2436

2437
  if (*pWinCode == TSDB_CODE_SUCCESS) {
3,266✔
2438
    pCurWin->isOutput = true;
940✔
2439
    if (pCurWin->pStatePos->needFree) {
940✔
2440
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
135✔
2441
    }
2442
  } else {
2443
    pCurWin->sessionWin.win.skey = startTs;
2,326✔
2444
    pCurWin->sessionWin.win.ekey = endTs;
2,326✔
2445
  }
2446
  qDebug("===stream===set session window buff .start:%" PRId64 ",end:%" PRId64 ",groupid:%" PRIu64,
3,266✔
2447
         pCurWin->sessionWin.win.skey, pCurWin->sessionWin.win.ekey, pCurWin->sessionWin.groupId);
2448
_end:
1,797✔
2449
  if (code != TSDB_CODE_SUCCESS) {
3,266!
2450
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2451
  }
2452
  return code;
3,266✔
2453
}
2454

2455
void getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo,
215✔
2456
                      int32_t* pWinCode) {
2457
  int32_t size = 0;
215✔
2458
  (*pWinCode) = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin,
430✔
2459
                                                                 (void**)&pWinInfo->pStatePos, &size);
215✔
2460
  if ((*pWinCode) != TSDB_CODE_SUCCESS) {
215✔
2461
    return;
182✔
2462
  }
2463

2464
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
33✔
2465
}
2466

2467
int32_t saveDeleteInfo(SArray* pWins, SSessionKey key) {
1,235✔
2468
  int32_t code = TSDB_CODE_SUCCESS;
1,235✔
2469
  int32_t lino = 0;
1,235✔
2470
  void*   res = taosArrayPush(pWins, &key);
1,236✔
2471
  if (!res) {
1,236!
2472
    code = terrno;
×
2473
    QUERY_CHECK_CODE(code, lino, _end);
×
2474
  }
2475

2476
_end:
1,236✔
2477
  if (code != TSDB_CODE_SUCCESS) {
1,236!
2478
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2479
  }
2480
  return code;
1,234✔
2481
}
2482

2483
int32_t saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
77✔
2484
  key.win.ekey = key.win.skey;
77✔
2485
  return tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
77✔
2486
}
2487

2488
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
13,699✔
2489
  pAPI->streamStateReleaseBuf(pState, pPos, false);
13,699✔
2490
}
13,698✔
2491

2492
void removeSessionResult(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SSHashObj* pResMap, SSessionKey* pKey) {
76✔
2493
  int32_t     code = TSDB_CODE_SUCCESS;
76✔
2494
  int32_t     lino = 0;
76✔
2495
  SSessionKey key = {0};
76✔
2496
  getSessionHashKey(pKey, &key);
76✔
2497
  void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
76✔
2498
  if (pVal) {
76✔
2499
    releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
4✔
2500
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
4✔
2501
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
4!
2502
  }
2503
  int32_t tmpRes = tSimpleHashRemove(pResMap, &key, sizeof(SSessionKey));
76✔
2504
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
76✔
2505
}
76✔
2506

2507
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
13,437✔
2508
  *pHashKey = *pKey;
13,437✔
2509
  pHashKey->win.ekey = pKey->win.skey;
13,437✔
2510
}
13,437✔
2511

2512
void removeSessionDeleteResults(SSHashObj* pHashMap, SArray* pWins) {
10,467✔
2513
  if (tSimpleHashGetSize(pHashMap) == 0) {
10,467✔
2514
    return;
9,447✔
2515
  }
2516
  int32_t size = taosArrayGetSize(pWins);
1,026✔
2517
  for (int32_t i = 0; i < size; i++) {
2,372✔
2518
    SResultWindowInfo* pWin = taosArrayGet(pWins, i);
1,346✔
2519
    if (!pWin) continue;
1,346!
2520
    SSessionKey key = {0};
1,346✔
2521
    getSessionHashKey(&pWin->sessionWin, &key);
1,346✔
2522
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
1,346✔
2523
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,346✔
2524
  }
2525
}
2526

2527
void removeSessionResults(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SArray* pWins) {
1,119✔
2528
  if (tSimpleHashGetSize(pHashMap) == 0) {
1,119✔
2529
    return;
848✔
2530
  }
2531
  int32_t size = taosArrayGetSize(pWins);
271✔
2532
  for (int32_t i = 0; i < size; i++) {
591✔
2533
    SSessionKey* pWin = taosArrayGet(pWins, i);
320✔
2534
    if (!pWin) continue;
320!
2535
    SSessionKey key = {0};
320✔
2536
    getSessionHashKey(pWin, &key);
320✔
2537
    void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
320✔
2538
    if (pVal) {
320✔
2539
      releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
196✔
2540
      int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
196✔
2541
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
196!
2542
    }
2543
  }
2544
}
2545

2546
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
3,245✔
2547
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2548
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2549
                                int32_t* pWinRos) {
2550
  int32_t code = TSDB_CODE_SUCCESS;
3,245✔
2551
  int32_t lino = 0;
3,245✔
2552
  for (int32_t i = start; i < rows; ++i) {
7,352✔
2553
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
4,206!
2554
      (*pWinRos) = i - start;
98✔
2555
      goto _end;
98✔
2556
    }
2557
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
4,107✔
2558
      if (pStDeleted && pWinInfo->isOutput) {
24!
2559
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
19✔
2560
        QUERY_CHECK_CODE(code, lino, _end);
19!
2561
      }
2562

2563
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
24✔
2564
      pWinInfo->sessionWin.win.skey = pStartTs[i];
24✔
2565
    }
2566
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
4,107✔
2567
    if (pEndTs) {
4,107!
2568
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
4,107✔
2569
    }
2570
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
4,107✔
2571
  }
2572
  (*pWinRos) = rows - start;
3,146✔
2573

2574
_end:
3,244✔
2575
  if (code != TSDB_CODE_SUCCESS) {
3,244!
2576
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2577
  }
2578
  return code;
3,244✔
2579
}
2580

2581
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
12,501✔
2582
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
2583
  *pResult = (SResultRow*)pWinInfo->pStatePos->pRowBuff;
12,501✔
2584
  // set time window for current result
2585
  (*pResult)->win = pWinInfo->sessionWin.win;
12,501✔
2586
  return setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
12,501✔
2587
}
2588

2589
int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
12,409✔
2590
                           int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
2591
                           SOperatorInfo* pOperator, int64_t winDelta) {
2592
  int32_t        code = TSDB_CODE_SUCCESS;
12,409✔
2593
  int32_t        lino = 0;
12,409✔
2594
  SExprSupp*     pSup = &pOperator->exprSupp;
12,409✔
2595
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
12,409✔
2596
  code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
12,409✔
2597
  QUERY_CHECK_CODE(code, lino, _end);
12,409!
2598

2599
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
12,409✔
2600
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
12,408✔
2601

2602
_end:
12,408✔
2603
  if (code != TSDB_CODE_SUCCESS) {
12,408!
2604
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2605
  }
2606
  return code;
12,408✔
2607
}
2608

2609
void doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
1,325✔
2610
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
1,325✔
2611
  SSessionKey hashKey = {0};
1,325✔
2612
  getSessionHashKey(pKey, &hashKey);
1,325✔
2613
  int32_t tmpRes = tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
1,325✔
2614
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,325✔
2615
}
1,325✔
2616

2617
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
16,036✔
2618
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
16,036✔
2619
  if (pVal) {
16,036✔
2620
    SResultWindowInfo* pWin = pVal;
700✔
2621
    pWinInfo->isOutput = pWin->isOutput;
700✔
2622
  }
2623
}
16,036✔
2624

2625
void getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
3,549✔
2626
                           SResultWindowInfo* pNextWin) {
2627
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
3,549✔
2628
  pNextWin->isOutput = true;
3,549✔
2629
  setSessionWinOutputInfo(pStUpdated, pNextWin);
3,549✔
2630
  int32_t size = 0;
3,549✔
2631
  pNextWin->sessionWin = pCurWin->sessionWin;
3,549✔
2632
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin,
3,549✔
2633
                                                                  (void**)&pNextWin->pStatePos, &size);
3,549✔
2634
  if (code != TSDB_CODE_SUCCESS) {
3,549✔
2635
    SET_SESSION_WIN_INVALID(*pNextWin);
3,089✔
2636
  }
2637
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,549✔
2638
}
3,547✔
2639

2640
int32_t compactTimeWindow(SExprSupp* pSup, SStreamAggSupporter* pAggSup, STimeWindowAggSupp* pTwAggSup,
25✔
2641
                          SExecTaskInfo* pTaskInfo, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
2642
                          SSHashObj* pStUpdated, SSHashObj* pStDeleted, bool addGap) {
2643
  int32_t     code = TSDB_CODE_SUCCESS;
25✔
2644
  int32_t     lino = 0;
25✔
2645
  SResultRow* pCurResult = NULL;
25✔
2646
  int32_t     numOfOutput = pSup->numOfExprs;
25✔
2647
  code = initSessionOutputBuf(pCurWin, &pCurResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
25✔
2648
  QUERY_CHECK_CODE(code, lino, _end);
25!
2649

2650
  SResultRow* pWinResult = NULL;
25✔
2651
  code = initSessionOutputBuf(pNextWin, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
25✔
2652
  QUERY_CHECK_CODE(code, lino, _end);
25!
2653

2654
  pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, pNextWin->sessionWin.win.ekey);
25✔
2655
  memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
25✔
2656

2657
  int64_t winDelta = 0;
25✔
2658
  if (addGap) {
25✔
2659
    winDelta = pAggSup->gap;
21✔
2660
  }
2661
  updateTimeWindowInfo(&pTwAggSup->timeWindowData, &pCurWin->sessionWin.win, winDelta);
25✔
2662
  code = compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pTwAggSup->timeWindowData);
25✔
2663
  QUERY_CHECK_CODE(code, lino, _end);
25✔
2664

2665
  int32_t tmpRes = tSimpleHashRemove(pStUpdated, &pNextWin->sessionWin, sizeof(SSessionKey));
23✔
2666
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
23✔
2667

2668
  if (pNextWin->isOutput && pStDeleted) {
23!
2669
    qDebug("===stream=== save delete window info %" PRId64 ", %" PRIu64, pNextWin->sessionWin.win.skey,
22!
2670
           pNextWin->sessionWin.groupId);
2671
    code = saveDeleteRes(pStDeleted, pNextWin->sessionWin);
22✔
2672
    QUERY_CHECK_CODE(code, lino, _end);
22!
2673
  }
2674
  removeSessionResult(pAggSup, pStUpdated, pAggSup->pResultRows, &pNextWin->sessionWin);
23✔
2675
  doDeleteSessionWindow(pAggSup, &pNextWin->sessionWin);
23✔
2676
  releaseOutputBuf(pAggSup->pState, pNextWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
23✔
2677

2678
_end:
25✔
2679
  if (code != TSDB_CODE_SUCCESS) {
25✔
2680
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2681
  }
2682
  return code;
25✔
2683
}
2684

2685
int32_t compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
3,427✔
2686
                             SSHashObj* pStDeleted, bool addGap, int32_t* pWinNum, bool* pIsEnd) {
2687
  int32_t                        code = TSDB_CODE_SUCCESS;
3,427✔
2688
  int32_t                        lino = 0;
3,427✔
2689
  SExprSupp*                     pSup = &pOperator->exprSupp;
3,427✔
2690
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,427✔
2691
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
3,427✔
2692
  int32_t                        winNum = 0;
3,427✔
2693
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,427✔
2694
  SResultRow*                    pCurResult = NULL;
3,427✔
2695
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,427✔
2696
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,427✔
2697

2698
  if (pIsEnd != NULL) {
3,427!
2699
    (*pIsEnd) = false;
×
2700
  }
2701
  // Just look for the window behind StartIndex
2702
  while (1) {
19✔
2703
    SResultWindowInfo winInfo = {0};
3,446✔
2704
    getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
3,446✔
2705
    if (!IS_VALID_SESSION_WIN(winInfo)) {
3,445✔
2706
      if (pIsEnd != NULL) {
2,989!
2707
        (*pIsEnd) = true;
×
2708
      }
2709
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
2,989✔
2710
      break;
2,990✔
2711
    }
2712
    if (!isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
456✔
2713
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
21!
2714
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
435✔
2715
      break;
435✔
2716
    }
2717
    code =
2718
        compactTimeWindow(pSup, pAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, &winInfo, pStUpdated, pStDeleted, true);
21✔
2719
    QUERY_CHECK_CODE(code, lino, _end);
21✔
2720
    winNum++;
19✔
2721
  }
2722
  if (pWinNum) {
3,425✔
2723
    (*pWinNum) = winNum;
162✔
2724
  }
2725

2726
_end:
3,263✔
2727
  if (code != TSDB_CODE_SUCCESS) {
3,427✔
2728
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2729
  }
2730
  return code;
3,427✔
2731
}
2732

2733
static void compactSessionSemiWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin) {
25✔
2734
  SExprSupp*                     pSup = &pOperator->exprSupp;
25✔
2735
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
25✔
2736
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
25✔
2737
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
25✔
2738
  SResultRow*                    pCurResult = NULL;
25✔
2739
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
25✔
2740
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
25✔
2741
  // Just look for the window behind StartIndex
2742
  while (1) {
×
2743
    SResultWindowInfo winInfo = {0};
25✔
2744
    getNextSessionWinInfo(pAggSup, NULL, pCurWin, &winInfo);
25✔
2745
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
25!
2746
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
×
2747
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
25✔
2748
      break;
25✔
2749
    }
2750
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
×
2751
    memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
×
2752
    doDeleteSessionWindow(pAggSup, &winInfo.sessionWin);
×
2753
    releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2754
  }
2755
}
25✔
2756

2757
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
12,770✔
2758
  qDebug("===stream===try save session result skey:%" PRId64 ", ekey:%" PRId64 ".pos%d", pWinInfo->sessionWin.win.skey,
12,770✔
2759
         pWinInfo->sessionWin.win.ekey, pWinInfo->pStatePos->needFree);
2760
  return pAggSup->stateStore.streamStateSessionPut(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pStatePos,
12,770✔
2761
                                                   pAggSup->resultRowSize);
2762
}
2763

2764
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3,157✔
2765
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
2766
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,157✔
2767
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,157✔
2768
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,157✔
2769
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
3,157✔
2770
  int32_t                        code = TSDB_CODE_SUCCESS;
3,157✔
2771
  int32_t                        lino = 0;
3,157✔
2772
  SResultRow*                    pResult = NULL;
3,157✔
2773
  int32_t                        rows = pSDataBlock->info.rows;
3,157✔
2774
  int32_t                        winRows = 0;
3,157✔
2775
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,157✔
2776

2777
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,157✔
2778
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,157✔
2779
  if (pAggSup->winRange.ekey <= 0) {
3,157!
2780
    pAggSup->winRange.ekey = INT64_MAX;
×
2781
  }
2782

2783
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,157✔
2784
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,157✔
2785
  SColumnInfoData* pEndTsCol = NULL;
3,157✔
2786
  if (hasEndTs) {
3,157✔
2787
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
474✔
2788
  } else {
2789
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,683✔
2790
  }
2791

2792
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
3,157✔
2793

2794
  void*            pPkVal = NULL;
3,157✔
2795
  int32_t          pkLen = 0;
3,157✔
2796
  SColumnInfoData* pPkColDataInfo = NULL;
3,157✔
2797
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
3,157✔
2798
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
14✔
2799
  }
2800

2801
  for (int32_t i = 0; i < rows;) {
6,410✔
2802
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
3,255!
2803
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2804
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2805
    }
2806
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
3,441✔
2807
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
186✔
2808
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
186✔
2809
      i++;
11✔
2810
      continue;
11✔
2811
    }
2812
    SResultWindowInfo winInfo = {0};
3,244✔
2813
    int32_t           winCode = TSDB_CODE_SUCCESS;
3,244✔
2814
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo, &winCode);
3,244✔
2815
    QUERY_CHECK_CODE(code, lino, _end);
3,246!
2816

2817
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_SESSION_OP(pOperator) &&
3,244✔
2818
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
2,039!
2819
      code = addSessionAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &winInfo.sessionWin, &pInfo->basic.notifyEventSup,
×
2820
                                      pTaskInfo->streamInfo.pNotifyEventStat);
2821
      QUERY_CHECK_CODE(code, lino, _end);
×
2822
    }
2823

2824
    // coverity scan error
2825
    if (!winInfo.pStatePos) {
3,244!
2826
      continue;
×
2827
    }
2828
    setSessionWinOutputInfo(pStUpdated, &winInfo);
3,244✔
2829
    code = updateSessionWindowInfo(pAggSup, &winInfo, startTsCols, endTsCols, groupId, rows, i, pAggSup->gap,
3,245✔
2830
                                   pAggSup->pResultRows, pStUpdated, pStDeleted, &winRows);
2831
    QUERY_CHECK_CODE(code, lino, _end);
3,244!
2832

2833
    int64_t winDelta = 0;
3,244✔
2834
    if (addGap) {
3,244✔
2835
      winDelta = pAggSup->gap;
2,608✔
2836
    }
2837
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
3,244✔
2838
                              pOperator, winDelta);
2839
    QUERY_CHECK_CODE(code, lino, _end);
3,244!
2840

2841
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL, NULL);
3,244✔
2842
    QUERY_CHECK_CODE(code, lino, _end);
3,242✔
2843

2844
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,240✔
2845
    QUERY_CHECK_CODE(code, lino, _end);
3,242!
2846

2847
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
3,242✔
2848
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
5✔
2849
      QUERY_CHECK_CODE(code, lino, _end);
6!
2850
    }
2851
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
3,243✔
2852
      code = saveResult(winInfo, pStUpdated);
2,347✔
2853
      QUERY_CHECK_CODE(code, lino, _end);
2,346!
2854
    }
2855
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,242✔
2856
      winInfo.pStatePos->beUpdated = true;
620✔
2857
      SSessionKey key = {0};
620✔
2858
      getSessionHashKey(&winInfo.sessionWin, &key);
620✔
2859
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
620✔
2860
      QUERY_CHECK_CODE(code, lino, _end);
620!
2861
    }
2862

2863
    i += winRows;
3,242✔
2864
  }
2865

2866
_end:
3,155✔
2867
  if (code != TSDB_CODE_SUCCESS) {
3,157✔
2868
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2869
  }
2870
}
3,157✔
2871

2872
int32_t doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
1,162✔
2873
  int32_t          code = TSDB_CODE_SUCCESS;
1,162✔
2874
  int32_t          lino = 0;
1,162✔
2875
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,162✔
2876
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
1,162✔
2877
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,162✔
2878
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
1,162✔
2879
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,162✔
2880
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
1,162✔
2881
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
2,386✔
2882
    while (1) {
1,255✔
2883
      SSessionKey curWin = {0};
2,479✔
2884
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
2,479✔
2885
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
2,480✔
2886
        break;
1,224✔
2887
      }
2888
      doDeleteSessionWindow(pAggSup, &curWin);
1,256✔
2889
      if (result) {
1,255✔
2890
        code = saveDeleteInfo(result, curWin);
1,209✔
2891
        QUERY_CHECK_CODE(code, lino, _end);
1,209!
2892
      }
2893
    }
2894
  }
2895

2896
_end:
1,162✔
2897
  if (code != TSDB_CODE_SUCCESS) {
1,162!
2898
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2899
  }
2900
  return code;
1,162✔
2901
}
2902

2903
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
6,558✔
2904
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
6,558✔
2905
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
6,558✔
2906
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
6,558✔
2907
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
6,558✔
2908

2909
  if (pWin1->groupId > pWin2->groupId) {
6,558✔
2910
    return 1;
2,167✔
2911
  } else if (pWin1->groupId < pWin2->groupId) {
4,391✔
2912
    return -1;
1,941✔
2913
  }
2914

2915
  if (pWin1->win.skey > pWin2->win.skey) {
2,450✔
2916
    return 1;
1,366✔
2917
  } else if (pWin1->win.skey < pWin2->win.skey) {
1,084!
2918
    return -1;
1,084✔
2919
  }
2920

2921
  return 0;
×
2922
}
2923

2924
static int32_t appendToDeleteDataBlock(SOperatorInfo* pOp, SSDataBlock *pBlock, SSessionKey *pKey) {
688✔
2925
  int32_t        code = TSDB_CODE_SUCCESS;
688✔
2926
  int32_t        lino = 0;
688✔
2927
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
688✔
2928

2929
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
688!
2930
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
688!
2931

2932
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
688✔
2933
  code = colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
688✔
2934
  QUERY_CHECK_CODE(code, lino, _end);
688!
2935

2936
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
688✔
2937
  code = colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&pKey->win.skey, false);
688✔
2938
  QUERY_CHECK_CODE(code, lino, _end);
688!
2939

2940
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
688✔
2941
  colDataSetNULL(pUidCol, pBlock->info.rows);
688!
2942

2943
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
688✔
2944
  code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&pKey->groupId, false);
688✔
2945
  QUERY_CHECK_CODE(code, lino, _end);
688!
2946

2947
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
688✔
2948
  colDataSetNULL(pCalStCol, pBlock->info.rows);
688!
2949

2950
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
688✔
2951
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
688!
2952

2953
  SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
688✔
2954
  if (!pTableCol) {
688!
2955
    QUERY_CHECK_CODE(code, lino, _end);
×
2956
  }
2957

2958
  void*        tbname = NULL;
688✔
2959
  int32_t      winCode = TSDB_CODE_SUCCESS;
688✔
2960
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;
688✔
2961
  code =
2962
      pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, pKey->groupId, &tbname, false, &winCode);
688✔
2963
  QUERY_CHECK_CODE(code, lino, _end);
688!
2964

2965
  if (winCode != TSDB_CODE_SUCCESS) {
688✔
2966
    colDataSetNULL(pTableCol, pBlock->info.rows);
246!
2967
  } else {
2968
    char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
2969
    STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
442✔
2970
    code = colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
442✔
2971
    QUERY_CHECK_CODE(code, lino, _end);
442!
2972
    pAPI->stateStore.streamStateFreeVal(tbname);
442✔
2973
  }
2974
  pBlock->info.rows += 1;
688✔
2975

2976
_end:
688✔
2977
  if (code != TSDB_CODE_SUCCESS) {
688!
2978
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2979
  }
2980
  return code;
688✔
2981
}
2982

2983
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite,
17,335✔
2984
                            SGroupResInfo* pGroupResInfo) {
2985
  int32_t        code = TSDB_CODE_SUCCESS;
17,335✔
2986
  int32_t        lino = 0;
17,335✔
2987
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
17,335✔
2988
  int64_t        minWindowSize = getMinWindowSize(pOp);
17,335✔
2989
  int32_t        numOfRows = getNumOfTotalRes(pGroupResInfo);
17,334✔
2990

2991
  blockDataCleanup(pBlock);
17,333✔
2992
  int32_t size = tSimpleHashGetSize(pStDeleted);
17,329✔
2993
  if (minWindowSize > 0) {
17,329✔
2994
    // Add the number of windows that are below the minimum width limit.
2995
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
252✔
2996
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
2997
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
2998
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
2999
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
3000
        size++;
60✔
3001
      }
3002
    }
3003
  }
3004
  if (size == 0) {
17,329✔
3005
    return;
16,790✔
3006
  }
3007
  code = blockDataEnsureCapacity(pBlock, size);
539✔
3008
  QUERY_CHECK_CODE(code, lino, _end);
539!
3009

3010
  int32_t iter = 0;
539✔
3011
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
1,167✔
3012
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
628!
3013
      break;
×
3014
    }
3015
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
628!
3016
    code = appendToDeleteDataBlock(pOp, pBlock, res);
628✔
3017
    QUERY_CHECK_CODE(code, lino, _end);
628!
3018
  }
3019

3020
  if (minWindowSize > 0) {
539✔
3021
    for (int32_t i = pGroupResInfo->delIndex; i < numOfRows; ++i) {
138✔
3022
      SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
120✔
3023
      SRowBuffPos*       pPos = pWinInfo->pStatePos;
120✔
3024
      SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
120✔
3025
      if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
120✔
3026
        code = appendToDeleteDataBlock(pOp, pBlock, pKey);
60✔
3027
        QUERY_CHECK_CODE(code, lino, _end);
60!
3028
      }
3029
    }
3030
    pGroupResInfo->delIndex = numOfRows;
18✔
3031
  }
3032

3033
_end:
521✔
3034
  if ((*Ite) == NULL) {
539!
3035
    tSimpleHashClear(pStDeleted);
539✔
3036
  }
3037

3038
  if (code != TSDB_CODE_SUCCESS) {
539!
3039
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3040
  }
3041
}
3042

3043
static int32_t rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
56✔
3044
  int32_t        winCode = TSDB_CODE_SUCCESS;
56✔
3045
  int32_t        code = TSDB_CODE_SUCCESS;
56✔
3046
  int32_t        lino = 0;
56✔
3047
  SExprSupp*     pSup = &pOperator->exprSupp;
56✔
3048
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
56✔
3049
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
56✔
3050

3051
  int32_t                        size = taosArrayGetSize(pWinArray);
56✔
3052
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
56✔
3053
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
56✔
3054
  int32_t                        numOfOutput = pSup->numOfExprs;
56✔
3055
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
56✔
3056

3057
  for (int32_t i = 0; i < size; i++) {
111✔
3058
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
55✔
3059
    int32_t           num = 0;
55✔
3060
    SResultWindowInfo parentWin = {0};
55✔
3061
    for (int32_t j = 0; j < numOfChild; j++) {
249✔
3062
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
194✔
3063
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
194✔
3064
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
194✔
3065
      SSessionKey                    chWinKey = {0};
194✔
3066
      getSessionHashKey(pWinKey, &chWinKey);
194✔
3067
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
194✔
3068
      SResultRow*      pResult = NULL;
194✔
3069
      SResultRow*      pChResult = NULL;
194✔
3070
      while (1) {
21✔
3071
        SResultWindowInfo childWin = {0};
215✔
3072
        childWin.sessionWin = *pWinKey;
215✔
3073
        getSessionWinBuf(pChAggSup, pCur, &childWin, &winCode);
215✔
3074

3075
        if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
215!
3076
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
×
3077
          continue;
×
3078
        }
3079

3080
        if (winCode == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
215✔
3081
          if (num == 0) {
21!
3082
            code = setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin,
21✔
3083
                                       &winCode);
3084
            QUERY_CHECK_CODE(code, lino, _end);
21!
3085

3086
            parentWin.sessionWin = childWin.sessionWin;
21✔
3087
            memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3088
            code = initSessionOutputBuf(&parentWin, &pResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
21✔
3089
            QUERY_CHECK_CODE(code, lino, _end);
21!
3090
          }
3091
          num++;
21✔
3092
          parentWin.sessionWin.win.skey = TMIN(parentWin.sessionWin.win.skey, childWin.sessionWin.win.skey);
21✔
3093
          parentWin.sessionWin.win.ekey = TMAX(parentWin.sessionWin.win.ekey, childWin.sessionWin.win.ekey);
21✔
3094
          memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
21✔
3095

3096
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap);
21✔
3097
          code = initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
21✔
3098
                                      pChild->exprSupp.rowEntryInfoOffset);
3099
          QUERY_CHECK_CODE(code, lino, _end);
21!
3100

3101
          code = compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo,
21✔
3102
                                  &pInfo->twAggSup.timeWindowData);
3103
          QUERY_CHECK_CODE(code, lino, _end);
21!
3104

3105
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL, NULL);
21✔
3106
          QUERY_CHECK_CODE(code, lino, _end);
21!
3107

3108
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
21✔
3109
        } else {
3110
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
194✔
3111
          break;
194✔
3112
        }
3113
      }
3114
      pAPI->stateStore.streamStateFreeCur(pCur);
194✔
3115
    }
3116
    if (num > 0) {
55✔
3117
      code = saveResult(parentWin, pStUpdated);
21✔
3118
      QUERY_CHECK_CODE(code, lino, _end);
21!
3119

3120
      code = saveSessionOutputBuf(pAggSup, &parentWin);
21✔
3121
      QUERY_CHECK_CODE(code, lino, _end);
21!
3122
    }
3123
  }
3124

3125
_end:
56✔
3126
  if (code != TSDB_CODE_SUCCESS) {
56!
3127
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3128
  }
3129
  return code;
56✔
3130
}
3131

3132
int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) {
10,529✔
3133
  int32_t code = TSDB_CODE_SUCCESS;
10,529✔
3134
  int32_t lino = 0;
10,529✔
3135
  void*   pIte = NULL;
10,529✔
3136
  int32_t iter = 0;
10,529✔
3137
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
12,335✔
3138
    SResultWindowInfo* pWinInfo = pIte;
1,806✔
3139
    if (isCloseWindow(&pWinInfo->sessionWin.win, pTwSup)) {
1,806✔
3140
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
635!
3141
        code = saveResult(*pWinInfo, pClosed);
635✔
3142
        QUERY_CHECK_CODE(code, lino, _end);
635!
3143
      }
3144
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
635!
3145
      code = tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
635✔
3146
      QUERY_CHECK_CODE(code, lino, _end);
635!
3147
    }
3148
  }
3149
_end:
10,530✔
3150
  if (code != TSDB_CODE_SUCCESS) {
10,530!
3151
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3152
  }
3153
  return code;
10,530✔
3154
}
3155

3156
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
3,777✔
3157
  int32_t code = TSDB_CODE_SUCCESS;
3,777✔
3158
  int32_t lino = 0;
3,777✔
3159

3160
  int32_t size = taosArrayGetSize(pChildren);
3,777✔
3161
  for (int32_t i = 0; i < size; i++) {
4,354✔
3162
    SOperatorInfo*                 pChildOp = taosArrayGetP(pChildren, i);
577✔
3163
    SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
577✔
3164
    pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
577✔
3165
    code = closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
577✔
3166
    QUERY_CHECK_CODE(code, lino, _end);
577!
3167
  }
3168
_end:
3,777✔
3169
  if (code != TSDB_CODE_SUCCESS) {
3,777!
3170
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3171
  }
3172
  return code;
3,777✔
3173
}
3174

3175
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
285✔
3176
  int32_t code = TSDB_CODE_SUCCESS;
285✔
3177
  int32_t lino = 0;
285✔
3178
  void*   pIte = NULL;
285✔
3179
  int32_t iter = 0;
285✔
3180
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
417✔
3181
    SResultWindowInfo* pWinInfo = pIte;
132✔
3182
    if (!pWinInfo->pStatePos->beUpdated) {
132✔
3183
      continue;
1✔
3184
    }
3185
    pWinInfo->pStatePos->beUpdated = false;
131✔
3186
    code = saveResult(*pWinInfo, pStUpdated);
131✔
3187
    QUERY_CHECK_CODE(code, lino, _end);
131!
3188
  }
3189

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

3197
int32_t copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
1,121✔
3198
  int32_t code = TSDB_CODE_SUCCESS;
1,121✔
3199
  int32_t lino = 0;
1,121✔
3200
  int32_t size = taosArrayGetSize(pResWins);
1,121✔
3201
  for (int32_t i = 0; i < size; i++) {
2,362✔
3202
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
1,241✔
3203
    if (!pWinKey) continue;
1,240!
3204
    SSessionKey winInfo = {0};
1,240✔
3205
    getSessionHashKey(pWinKey, &winInfo);
1,240✔
3206
    code = tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
1,240✔
3207
    QUERY_CHECK_CODE(code, lino, _end);
1,241!
3208
  }
3209

3210
_end:
1,121✔
3211
  if (code != TSDB_CODE_SUCCESS) {
1,121!
3212
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3213
  }
3214
  return code;
1,121✔
3215
}
3216

3217
// the allocated memory comes from outer function.
3218
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
10,486✔
3219
  pGroupResInfo->pRows = pArrayList;
10,486✔
3220
  pGroupResInfo->index = 0;
10,486✔
3221
  pGroupResInfo->pBuf = NULL;
10,486✔
3222
  pGroupResInfo->freeItem = false;
10,486✔
3223
  pGroupResInfo->delIndex = 0;
10,486✔
3224
}
10,486✔
3225

3226
int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
5,613✔
3227
                                    SGroupResInfo* pGroupResInfo, SArray* pSessionKeys) {
3228
  int32_t         code = TSDB_CODE_SUCCESS;
5,613✔
3229
  int32_t         lino = 0;
5,613✔
3230
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
5,613✔
3231
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
5,613✔
3232
  SExprInfo*      pExprInfo = pSup->pExprInfo;
5,613✔
3233
  int32_t         numOfExprs = pSup->numOfExprs;
5,613✔
3234
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
5,613✔
3235
  SqlFunctionCtx* pCtx = pSup->pCtx;
5,613✔
3236
  int64_t         minWindowSize = getMinWindowSize(pOperator);
5,613✔
3237

3238
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
5,613✔
3239

3240
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
12,525✔
3241
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
8,711✔
3242
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
8,712✔
3243
    SResultRow*        pRow = NULL;
8,712✔
3244
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
8,712✔
3245

3246
    if (pBlock->info.id.groupId == 0) {
8,712✔
3247
      pBlock->info.id.groupId = pKey->groupId;
6,190✔
3248

3249
      void*   tbname = NULL;
6,190✔
3250
      int32_t winCode = TSDB_CODE_SUCCESS;
6,190✔
3251
      code = pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
6,190✔
3252
                                                    &tbname, false, &winCode);
3253
      QUERY_CHECK_CODE(code, lino, _end);
6,190!
3254

3255
      if (winCode != TSDB_CODE_SUCCESS) {
6,190✔
3256
        pBlock->info.parTbName[0] = 0;
1,760✔
3257
      } else {
3258
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,430✔
3259
      }
3260
      pAPI->stateStore.streamStateFreeVal(tbname);
6,190✔
3261
    } else {
3262
      // current value belongs to different group, it can't be packed into one datablock
3263
      if (pBlock->info.id.groupId != pKey->groupId) {
2,522✔
3264
        break;
1,797✔
3265
      }
3266
    }
3267

3268
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
6,915✔
3269
    QUERY_CHECK_CODE(code, lino, _end);
6,913!
3270

3271
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
6,913✔
3272
    // no results, continue to check the next one
3273
    if (pRow->numOfRows == 0) {
6,914!
3274
      pGroupResInfo->index += 1;
×
3275
      continue;
60✔
3276
    }
3277
    // skip the window which is less than the windowMinSize
3278
    if (pKey->win.ekey - pKey->win.skey < minWindowSize) {
6,914✔
3279
      qDebug("skip small window, groupId: %" PRId64 ", windowSize: %" PRId64 ", minWindowSize: %" PRId64, pKey->groupId,
60!
3280
             pKey->win.ekey - pKey->win.skey, minWindowSize);
3281
      pGroupResInfo->index += 1;
60✔
3282
      continue;
60✔
3283
    }
3284

3285
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,854!
3286
      break;
×
3287
    }
3288

3289
    pGroupResInfo->index += 1;
6,854✔
3290

3291
    for (int32_t j = 0; j < numOfExprs; ++j) {
114,499✔
3292
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
107,647✔
3293

3294
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
107,647✔
3295
      if (pCtx[j].fpSet.finalize) {
107,651✔
3296
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
98,344✔
3297
        if (TAOS_FAILED(tmpRes)) {
98,354!
3298
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
3299
          QUERY_CHECK_CODE(code, lino, _end);
×
3300
        }
3301
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
9,307✔
3302
        // do nothing, todo refactor
3303
      } else {
3304
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
3305
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
3306
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
9,270✔
3307
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
9,270✔
3308
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
18,541✔
3309
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
9,270✔
3310
          QUERY_CHECK_CODE(code, lino, _end);
9,271!
3311
        }
3312
      }
3313
    }
3314

3315
    if (pSessionKeys) {
6,852!
3316
      for (int32_t j = 0; j < pRow->numOfRows; ++j) {
×
3317
        const void* px = taosArrayPush(pSessionKeys, pKey);
×
3318
        QUERY_CHECK_NULL(px, code, lino, _end, terrno);
×
3319
      }
3320
    }
3321

3322
    pBlock->info.dataLoad = 1;
6,852✔
3323
    pBlock->info.rows += pRow->numOfRows;
6,852✔
3324
  }
3325
  code = blockDataUpdateTsWindow(pBlock, 0);
5,611✔
3326
  QUERY_CHECK_CODE(code, lino, _end);
5,613!
3327

3328
_end:
5,613✔
3329
  if (code != TSDB_CODE_SUCCESS) {
5,613!
3330
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3331
  }
3332
  return code;
5,613✔
3333
}
3334

3335
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo, SSDataBlock* pBlock,
16,791✔
3336
                          SArray* pSessionKeys) {
3337
  int32_t        code = TSDB_CODE_SUCCESS;
16,791✔
3338
  int32_t        lino = 0;
16,791✔
3339
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
16,791✔
3340
  // set output datablock version
3341
  pBlock->info.version = pTaskInfo->version;
16,791✔
3342

3343
  blockDataCleanup(pBlock);
16,791✔
3344
  taosArrayClear(pSessionKeys);
16,793✔
3345
  if (!hasRemainResults(pGroupResInfo)) {
16,793✔
3346
    cleanupGroupResInfo(pGroupResInfo);
11,182✔
3347
    goto _end;
11,192✔
3348
  }
3349

3350
  // clear the existed group id
3351
  pBlock->info.id.groupId = 0;
5,613✔
3352
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
5,613✔
3353
  QUERY_CHECK_CODE(code, lino, _end);
5,613!
3354

3355
  if (pBlock->info.rows == 0) {
5,613!
3356
    cleanupGroupResInfo(pGroupResInfo);
×
3357
  }
3358

3359
_end:
5,613✔
3360
  if (code != TSDB_CODE_SUCCESS) {
16,805!
3361
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3362
  }
3363
}
16,805✔
3364

3365
static int32_t buildSessionResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,162✔
3366
  int32_t                        code = TSDB_CODE_SUCCESS;
7,162✔
3367
  int32_t                        lino = 0;
7,162✔
3368
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
7,162✔
3369
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
7,162✔
3370
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
7,162✔
3371
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
7,162✔
3372
  SStreamNotifyEventSupp*        pNotifySup = &pInfo->basic.notifyEventSup;
7,162✔
3373
  STaskNotifyEventStat*          pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
7,162✔
3374
  bool                           addNotifyEvent = false;
7,162✔
3375
  addNotifyEvent = IS_NORMAL_SESSION_OP(pOperator) &&
12,812✔
3376
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
5,650!
3377
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
7,162✔
3378
  if (pInfo->pDelRes->info.rows > 0) {
7,164✔
3379
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
260✔
3380
    if (addNotifyEvent) {
259!
3381
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
3382
      QUERY_CHECK_CODE(code, lino, _end);
×
3383
    }
3384
    (*ppRes) = pInfo->pDelRes;
259✔
3385
    return code;
259✔
3386
  }
3387

3388
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes,
6,904!
3389
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
3390
  if (pBInfo->pRes->info.rows > 0) {
6,910✔
3391
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,911✔
3392
    if (addNotifyEvent) {
1,911!
3393
      // Adjust the window end time based on the Session Window gap
3394
      for (int32_t i = 0; i < taosArrayGetSize(pNotifySup->pSessionKeys); ++i) {
×
3395
        SSessionKey* pKey = taosArrayGet(pNotifySup->pSessionKeys, i);
×
3396
        pKey->win.ekey += pAggSup->gap;
×
3397
      }
3398
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
3399
                                     pNotifySup, pNotifyEventStat);
3400
      QUERY_CHECK_CODE(code, lino, _end);
×
3401
    }
3402
    (*ppRes) = pBInfo->pRes;
1,911✔
3403
    return code;
1,911✔
3404
  }
3405

3406
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
4,999✔
3407
  QUERY_CHECK_CODE(code, lino, _end);
4,996!
3408
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
4,996!
3409
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3410
    (*ppRes) = pNotifySup->pEventBlock;
×
3411
    return code;
×
3412
  }
3413

3414
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
4,996✔
3415
  QUERY_CHECK_CODE(code, lino, _end);
4,994!
3416

3417
_end:
4,994✔
3418
  if (code != TSDB_CODE_SUCCESS) {
4,994!
3419
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3420
  }
3421
  (*ppRes) = NULL;
4,995✔
3422
  return code;
4,995✔
3423
}
3424

3425
int32_t getMaxTsWins(const SArray* pAllWins, SArray* pMaxWins) {
373✔
3426
  int32_t code = TSDB_CODE_SUCCESS;
373✔
3427
  int32_t lino = 0;
373✔
3428
  int32_t size = taosArrayGetSize(pAllWins);
373✔
3429
  if (size == 0) {
373✔
3430
    goto _end;
240✔
3431
  }
3432
  SResultWindowInfo* pWinInfo = taosArrayGet(pAllWins, size - 1);
133✔
3433
  SSessionKey*       pSeKey = &pWinInfo->sessionWin;
133✔
3434
  void*              tmp = taosArrayPush(pMaxWins, pSeKey);
133✔
3435
  if (!tmp) {
133!
3436
    code = terrno;
×
3437
    QUERY_CHECK_CODE(code, lino, _end);
×
3438
  }
3439

3440
  if (pSeKey->groupId == 0) {
133✔
3441
    goto _end;
17✔
3442
  }
3443
  uint64_t preGpId = pSeKey->groupId;
116✔
3444
  for (int32_t i = size - 2; i >= 0; i--) {
442✔
3445
    pWinInfo = taosArrayGet(pAllWins, i);
326✔
3446
    pSeKey = &pWinInfo->sessionWin;
326✔
3447
    if (preGpId != pSeKey->groupId) {
326✔
3448
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
211✔
3449
      if (!tmp) {
211!
3450
        code = terrno;
×
3451
        QUERY_CHECK_CODE(code, lino, _end);
×
3452
      }
3453
      preGpId = pSeKey->groupId;
211✔
3454
    }
3455
  }
3456

3457
_end:
116✔
3458
  if (code != TSDB_CODE_SUCCESS) {
373!
3459
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3460
  }
3461
  return code;
373✔
3462
}
3463

3464
int32_t encodeSSessionKey(void** buf, SSessionKey* key) {
20✔
3465
  int32_t tlen = 0;
20✔
3466
  tlen += encodeSTimeWindow(buf, &key->win);
20✔
3467
  tlen += taosEncodeFixedU64(buf, key->groupId);
20✔
3468
  return tlen;
20✔
3469
}
3470

3471
void* decodeSSessionKey(void* buf, SSessionKey* key) {
10✔
3472
  buf = decodeSTimeWindow(buf, &key->win);
10✔
3473
  buf = taosDecodeFixedU64(buf, &key->groupId);
10!
3474
  return buf;
10✔
3475
}
3476

3477
int32_t encodeSResultWindowInfo(void** buf, SResultWindowInfo* key, int32_t outLen) {
10✔
3478
  int32_t tlen = 0;
10✔
3479
  tlen += taosEncodeFixedBool(buf, key->isOutput);
10✔
3480
  tlen += encodeSSessionKey(buf, &key->sessionWin);
10✔
3481
  return tlen;
10✔
3482
}
3483

3484
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
5✔
3485
  buf = taosDecodeFixedBool(buf, &key->isOutput);
5✔
3486
  buf = decodeSSessionKey(buf, &key->sessionWin);
5✔
3487
  return buf;
5✔
3488
}
3489

3490
int32_t doStreamSessionEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
×
3491
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3492
  if (!pInfo) {
×
3493
    return 0;
×
3494
  }
3495

3496
  void* pData = (buf == NULL) ? NULL : *buf;
×
3497

3498
  // 1.streamAggSup.pResultRows
3499
  int32_t tlen = 0;
×
3500
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
×
3501
  tlen += taosEncodeFixedI32(buf, mapSize);
×
3502
  void*   pIte = NULL;
×
3503
  size_t  keyLen = 0;
×
3504
  int32_t iter = 0;
×
3505
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
×
3506
    void* key = tSimpleHashGetKey(pIte, &keyLen);
×
3507
    tlen += encodeSSessionKey(buf, key);
×
3508
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
×
3509
  }
3510

3511
  // 2.twAggSup
3512
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3513

3514
  // 3.pChildren
3515
  int32_t size = taosArrayGetSize(pInfo->pChildren);
×
3516
  tlen += taosEncodeFixedI32(buf, size);
×
3517
  for (int32_t i = 0; i < size; i++) {
×
3518
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3519
    tlen += doStreamSessionEncodeOpState(buf, 0, pChOp, false);
×
3520
  }
3521

3522
  // 4.dataVersion
3523
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
3524

3525
  // 5.basicInfo
3526
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
×
3527

3528
  // 6.checksum
3529
  if (isParent) {
×
3530
    if (buf) {
×
3531
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
×
3532
      tlen += taosEncodeFixedU32(buf, cksum);
×
3533
    } else {
3534
      tlen += sizeof(uint32_t);
×
3535
    }
3536
  }
3537

3538
  return tlen;
×
3539
}
3540

3541
int32_t doStreamSessionDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
3542
  int32_t                        code = TSDB_CODE_SUCCESS;
×
3543
  int32_t                        lino = 0;
×
3544
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3545
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
×
3546
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
×
3547
  if (!pInfo) {
×
3548
    code = TSDB_CODE_FAILED;
×
3549
    QUERY_CHECK_CODE(code, lino, _end);
×
3550
  }
3551
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
×
3552

3553
  // 6.checksum
3554
  if (isParent) {
×
3555
    int32_t dataLen = len - sizeof(uint32_t);
×
3556
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
3557
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
3558
      qError("stream session state is invalid");
×
3559
      code = TSDB_CODE_FAILED;
×
3560
      QUERY_CHECK_CODE(code, lino, _end);
×
3561
    }
3562
    pDataEnd = pCksum;
×
3563
  }
3564

3565
  // 1.streamAggSup.pResultRows
3566
  int32_t mapSize = 0;
×
3567
  buf = taosDecodeFixedI32(buf, &mapSize);
×
3568
  for (int32_t i = 0; i < mapSize; i++) {
×
3569
    SResultWindowInfo winfo = {0};
×
3570
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
3571
    int32_t winCode = TSDB_CODE_SUCCESS;
×
3572
    code = pAggSup->stateStore.streamStateSessionAddIfNotExist(
×
3573
        pAggSup->pState, &winfo.sessionWin, pAggSup->gap, (void**)&winfo.pStatePos, &pAggSup->resultRowSize, &winCode);
3574
    QUERY_CHECK_CODE(code, lino, _end);
×
3575
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
3576

3577
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
3578
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
3579
                          sizeof(SResultWindowInfo));
3580
    QUERY_CHECK_CODE(code, lino, _end);
×
3581
  }
3582

3583
  // 2.twAggSup
3584
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3585

3586
  // 3.pChildren
3587
  int32_t size = 0;
×
3588
  buf = taosDecodeFixedI32(buf, &size);
×
3589
  for (int32_t i = 0; i < size; i++) {
×
3590
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3591
    code = doStreamSessionDecodeOpState(buf, 0, pChOp, false, &buf);
×
3592
    QUERY_CHECK_CODE(code, lino, _end);
×
3593
  }
3594

3595
  // 4.dataVersion
3596
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
3597
  if (ppBuf) {
×
3598
    (*ppBuf) = buf;
×
3599
  }
3600

3601
  // 5.basicInfo
3602
  if (buf < pDataEnd) {
×
3603
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
×
3604
    QUERY_CHECK_CODE(code, lino, _end);
×
3605
  }
3606

3607
_end:
×
3608
  if (code != TSDB_CODE_SUCCESS) {
×
3609
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3610
  }
3611
  return code;
×
3612
}
3613

3614
void doStreamSessionSaveCheckpoint(SOperatorInfo* pOperator) {
191✔
3615
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3616
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
191!
3617
    int32_t len = doStreamSessionEncodeOpState(NULL, 0, pOperator, true);
×
3618
    void*   buf = taosMemoryCalloc(1, len);
×
3619
    if (!buf) {
×
3620
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
3621
      return;
×
3622
    }
3623
    void* pBuf = buf;
×
3624
    len = doStreamSessionEncodeOpState(&pBuf, len, pOperator, true);
×
3625
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
×
3626
                                                       strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), buf, len);
3627
    taosMemoryFree(buf);
×
3628
    saveStreamOperatorStateComplete(&pInfo->basic);
×
3629
  }
3630
}
3631

3632
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
116✔
3633
  void*   pIte = NULL;
116✔
3634
  int32_t iter = 0;
116✔
3635
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
247✔
3636
    SResultWindowInfo* pResInfo = pIte;
131✔
3637
    pResInfo->pStatePos->beUsed = true;
131✔
3638
  }
3639
}
116✔
3640

3641
int32_t copyDeleteSessionKey(SSHashObj* source, SSHashObj* dest) {
32✔
3642
  int32_t code = TSDB_CODE_SUCCESS;
32✔
3643
  int32_t lino = 0;
32✔
3644
  if (tSimpleHashGetSize(source) == 0) {
32✔
3645
    goto _end;
23✔
3646
  }
3647
  void*   pIte = NULL;
9✔
3648
  int32_t iter = 0;
9✔
3649
  size_t  keyLen = 0;
9✔
3650
  while ((pIte = tSimpleHashIterate(source, pIte, &iter)) != NULL) {
21✔
3651
    SSessionKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
12✔
3652
    code = saveDeleteRes(dest, *pKey);
12✔
3653
    QUERY_CHECK_CODE(code, lino, _end);
12!
3654
  }
3655
  tSimpleHashClear(source);
9✔
3656

3657
_end:
32✔
3658
  if (code != TSDB_CODE_SUCCESS) {
32!
3659
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3660
  }
3661
  return code;
32✔
3662
}
3663

3664
static int32_t doStreamSessionAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
6,511✔
3665
  int32_t                        code = TSDB_CODE_SUCCESS;
6,511✔
3666
  int32_t                        lino = 0;
6,511✔
3667
  SExprSupp*                     pSup = &pOperator->exprSupp;
6,511✔
3668
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
6,511✔
3669
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
6,511✔
3670
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
6,511✔
3671
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
6,511✔
3672
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
6,511✔
3673
  if (pOperator->status == OP_EXEC_DONE) {
6,509!
3674
    (*ppRes) = NULL;
×
3675
    return code;
×
3676
  } else if (pOperator->status == OP_RES_TO_RETURN) {
6,509✔
3677
    SSDataBlock* opRes = NULL;
1,877✔
3678
    code = buildSessionResult(pOperator, &opRes);
1,877✔
3679
    QUERY_CHECK_CODE(code, lino, _end);
1,877!
3680
    if (opRes) {
1,877✔
3681
      (*ppRes) = opRes;
448✔
3682
      return code;
1,877✔
3683
    }
3684

3685
    if (pInfo->recvGetAll) {
1,429✔
3686
      pInfo->recvGetAll = false;
83✔
3687
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
83✔
3688
    }
3689

3690
    if (pInfo->reCkBlock) {
1,429!
3691
      pInfo->reCkBlock = false;
×
3692
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3693
      (*ppRes) = pInfo->pCheckpointRes;
×
3694
      return code;
×
3695
    }
3696

3697
    setStreamOperatorCompleted(pOperator);
1,429✔
3698
    (*ppRes) = NULL;
1,429✔
3699
    return code;
1,429✔
3700
  }
3701

3702
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,632✔
3703
  if (!pInfo->pUpdated) {
4,632✔
3704
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
3,777✔
3705
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
3,776!
3706
  }
3707
  if (!pInfo->pStUpdated) {
4,631✔
3708
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,706✔
3709
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
3,707✔
3710
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
3,709!
3711
  }
3712
  while (1) {
3,336✔
3713
    SSDataBlock* pBlock = NULL;
7,970✔
3714
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,970✔
3715
    QUERY_CHECK_CODE(code, lino, _end);
7,971!
3716

3717
    if (pBlock == NULL) {
7,971✔
3718
      break;
3,777✔
3719
    }
3720
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,194✔
3721
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,195✔
3722

3723
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,195✔
3724
        pBlock->info.type == STREAM_CLEAR) {
3,955✔
3725
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
410✔
3726
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
410!
3727
      // gap must be 0
3728
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
410✔
3729
      QUERY_CHECK_CODE(code, lino, _end);
410!
3730

3731
      removeSessionResults(pAggSup, pInfo->pStUpdated, pWins);
410✔
3732
      if (IS_FINAL_SESSION_OP(pOperator)) {
410✔
3733
        int32_t                        childIndex = getChildIndex(pBlock);
56✔
3734
        SOperatorInfo*                 pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
56✔
3735
        SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
56✔
3736
        // gap must be 0
3737
        code = doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
56✔
3738
        QUERY_CHECK_CODE(code, lino, _end);
56!
3739

3740
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
56✔
3741
        QUERY_CHECK_CODE(code, lino, _end);
56!
3742
      }
3743
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
410✔
3744
      QUERY_CHECK_CODE(code, lino, _end);
410!
3745

3746
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
410!
3747
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
2✔
3748
        QUERY_CHECK_CODE(code, lino, _end);
2!
3749
      }
3750
      taosArrayDestroy(pWins);
410✔
3751
      continue;
772✔
3752
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,785✔
3753
      pInfo->recvGetAll = true;
186✔
3754
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
186✔
3755
      QUERY_CHECK_CODE(code, lino, _end);
186!
3756
      continue;
186✔
3757
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,599✔
3758
      (*ppRes) = pBlock;
858✔
3759
      return code;
858✔
3760
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,741✔
3761
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
176✔
3762
      doStreamSessionSaveCheckpoint(pOperator);
176✔
3763
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
176✔
3764
      QUERY_CHECK_CODE(code, lino, _end);
176!
3765

3766
      continue;
176✔
3767
    } else {
3768
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
2,565!
3769
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3770
        QUERY_CHECK_CODE(code, lino, _end);
×
3771
      }
3772
    }
3773

3774
    if (pInfo->scalarSupp.pExprInfo != NULL) {
2,565✔
3775
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
3776
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
3777
      QUERY_CHECK_CODE(code, lino, _end);
13!
3778
    }
3779
    // the pDataBlock are always the same one, no need to call this again
3780
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
2,565✔
3781
    QUERY_CHECK_CODE(code, lino, _end);
2,564!
3782

3783
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_SESSION_OP(pOperator),
2,564✔
3784
                           true);
3785
    if (IS_FINAL_SESSION_OP(pOperator)) {
2,564✔
3786
      int32_t chIndex = getChildIndex(pBlock);
237✔
3787
      int32_t size = taosArrayGetSize(pInfo->pChildren);
237✔
3788
      // if chIndex + 1 - size > 0, add new child
3789
      for (int32_t i = 0; i < chIndex + 1 - size; i++) {
237!
3790
        SOperatorInfo* pChildOp = NULL;
×
3791
        code = createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0, NULL, &pChildOp);
×
3792
        if (pChildOp == NULL || code != 0) {
×
3793
          qError("%s create stream child of final session error", GET_TASKID(pTaskInfo));
×
3794
          code = TSDB_CODE_FAILED;
×
3795
          QUERY_CHECK_CODE(code, lino, _end);
×
3796
        }
3797

3798
        void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
×
3799
        if (!tmp) {
×
3800
          code = terrno;
×
3801
          QUERY_CHECK_CODE(code, lino, _end);
×
3802
        }
3803
      }
3804

3805
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
237✔
3806
      code = setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
237✔
3807
      QUERY_CHECK_CODE(code, lino, _end);
237!
3808
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
237✔
3809
    }
3810
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
2,564✔
3811
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
2,564✔
3812
  }
3813
  // restore the value
3814
  pOperator->status = OP_RES_TO_RETURN;
3,777✔
3815

3816
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
3,777✔
3817
  QUERY_CHECK_CODE(code, lino, _end);
3,777!
3818

3819
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
3,777✔
3820
  QUERY_CHECK_CODE(code, lino, _end);
3,777!
3821

3822
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
3,777✔
3823
  QUERY_CHECK_CODE(code, lino, _end);
3,779!
3824

3825
  if (!pInfo->destHasPrimaryKey) {
3,779✔
3826
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
3,759✔
3827
  }
3828
  if (pInfo->isHistoryOp) {
3,778✔
3829
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
196✔
3830
    QUERY_CHECK_CODE(code, lino, _end);
196!
3831
  }
3832
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
3,778!
3833
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
20✔
3834
    QUERY_CHECK_CODE(code, lino, _end);
20!
3835
  }
3836
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
3,778✔
3837
  pInfo->pUpdated = NULL;
3,773✔
3838
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3,773✔
3839
  QUERY_CHECK_CODE(code, lino, _end);
3,776!
3840

3841
  SSDataBlock* opRes = NULL;
3,776✔
3842
  code = buildSessionResult(pOperator, &opRes);
3,776✔
3843
  QUERY_CHECK_CODE(code, lino, _end);
3,780!
3844
  if (opRes) {
3,780✔
3845
    (*ppRes) = opRes;
1,429✔
3846
    return code;
1,429✔
3847
  }
3848

3849
_end:
2,351✔
3850
  if (code != TSDB_CODE_SUCCESS) {
2,351!
3851
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3852
    pTaskInfo->code = code;
×
3853
    T_LONG_JMP(pTaskInfo->env, code);
×
3854
  }
3855
  setStreamOperatorCompleted(pOperator);
2,351✔
3856
  (*ppRes) = NULL;
2,348✔
3857
  return code;
2,348✔
3858
}
3859

3860
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
×
3861
  SSDataBlock* pRes = NULL;
×
3862
  int32_t      code = doStreamSessionAggNext(pOperator, &pRes);
×
3863
  return pRes;
×
3864
}
3865

3866
void streamSessionReleaseState(SOperatorInfo* pOperator) {
191✔
3867
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3868
  int32_t                        winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
191✔
3869
  int32_t                        resSize = winSize + sizeof(TSKEY);
191✔
3870
  char*                          pBuff = taosMemoryCalloc(1, resSize);
191!
3871
  if (!pBuff) {
191!
3872
    return;
×
3873
  }
3874
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
191✔
3875
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
191✔
3876
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_STATE_NAME,
191✔
3877
                                                     strlen(STREAM_SESSION_OP_STATE_NAME), pBuff, resSize);
3878
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
191✔
3879
  taosMemoryFreeClear(pBuff);
191!
3880
  SOperatorInfo* downstream = pOperator->pDownstream[0];
191✔
3881
  if (downstream->fpSet.releaseStreamStateFn) {
191!
3882
    downstream->fpSet.releaseStreamStateFn(downstream);
191✔
3883
  }
3884
}
3885

3886
void resetWinRange(STimeWindow* winRange) {
357✔
3887
  winRange->skey = INT64_MIN;
357✔
3888
  winRange->ekey = INT64_MAX;
357✔
3889
}
357✔
3890

3891
int32_t getSessionWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SResultWindowInfo* pWinInfo) {
344✔
3892
  int32_t code = TSDB_CODE_SUCCESS;
344✔
3893
  int32_t lino = 0;
344✔
3894
  int32_t rowSize = pAggSup->resultRowSize;
344✔
3895
  int32_t winCode = TSDB_CODE_SUCCESS;
344✔
3896
  code = pAggSup->stateStore.streamStateSessionGet(pAggSup->pState, pKey, (void**)&pWinInfo->pStatePos, &rowSize,
344✔
3897
                                                   &winCode);
3898
  QUERY_CHECK_CODE(code, lino, _end);
344!
3899

3900
  if (winCode == TSDB_CODE_SUCCESS) {
344!
3901
    pWinInfo->sessionWin = *pKey;
344✔
3902
    pWinInfo->isOutput = true;
344✔
3903
    if (pWinInfo->pStatePos->needFree) {
344!
3904
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pWinInfo->sessionWin);
344✔
3905
    }
3906
  } else {
3907
    SET_SESSION_WIN_INVALID((*pWinInfo));
×
3908
  }
3909

3910
_end:
344✔
3911
  if (code != TSDB_CODE_SUCCESS) {
344!
3912
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3913
  }
3914
  return code;
344✔
3915
}
3916

3917
void reloadAggSupFromDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup) {
639✔
3918
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
639✔
3919

3920
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
639✔
3921
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
203✔
3922
    return;
203✔
3923
  }
3924

3925
  SStreamScanInfo* pScanInfo = downstream->info;
436✔
3926
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
436✔
3927
}
3928

3929
void streamSessionSemiReloadState(SOperatorInfo* pOperator) {
15✔
3930
  int32_t                        code = TSDB_CODE_SUCCESS;
15✔
3931
  int32_t                        lino = 0;
15✔
3932
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
15✔
3933
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
15✔
3934
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
15✔
3935
  resetWinRange(&pAggSup->winRange);
15✔
3936

3937
  SResultWindowInfo winInfo = {0};
15✔
3938
  int32_t           size = 0;
15✔
3939
  void*             pBuf = NULL;
15✔
3940
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
15✔
3941
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3942
  QUERY_CHECK_CODE(code, lino, _end);
15!
3943

3944
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
15✔
3945
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
15✔
3946
  for (int32_t i = 0; i < num; i++) {
40✔
3947
    SResultWindowInfo winInfo = {0};
25✔
3948
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
25✔
3949
    QUERY_CHECK_CODE(code, lino, _end);
25!
3950
    if (!IS_VALID_SESSION_WIN(winInfo)) {
25!
3951
      continue;
×
3952
    }
3953
    compactSessionSemiWindow(pOperator, &winInfo);
25✔
3954
    code = saveSessionOutputBuf(pAggSup, &winInfo);
25✔
3955
    QUERY_CHECK_CODE(code, lino, _end);
25!
3956
  }
3957
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
15✔
3958
  taosMemoryFree(pBuf);
15!
3959
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
15✔
3960
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
15✔
3961

3962
  SOperatorInfo* downstream = pOperator->pDownstream[0];
15✔
3963
  if (downstream->fpSet.reloadStreamStateFn) {
15!
3964
    downstream->fpSet.reloadStreamStateFn(downstream);
15✔
3965
  }
3966
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
15✔
3967

3968
_end:
15✔
3969
  if (code != TSDB_CODE_SUCCESS) {
15!
3970
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3971
  }
3972
}
15✔
3973

3974
void streamSessionReloadState(SOperatorInfo* pOperator) {
176✔
3975
  int32_t                        code = TSDB_CODE_SUCCESS;
176✔
3976
  int32_t                        lino = 0;
176✔
3977
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
176✔
3978
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
176✔
3979
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
176✔
3980
  resetWinRange(&pAggSup->winRange);
176✔
3981

3982
  int32_t size = 0;
176✔
3983
  void*   pBuf = NULL;
176✔
3984
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
176✔
3985
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3986

3987
  QUERY_CHECK_CODE(code, lino, _end);
176!
3988

3989
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
176✔
3990
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
176✔
3991

3992
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
176✔
3993
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
176✔
3994
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
176✔
3995

3996
  if (!pInfo->pStUpdated && num > 0) {
176!
3997
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
70✔
3998
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
70✔
3999
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
70!
4000
  }
4001
  for (int32_t i = 0; i < num; i++) {
338✔
4002
    SResultWindowInfo winInfo = {0};
162✔
4003
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
162✔
4004
    QUERY_CHECK_CODE(code, lino, _end);
162!
4005
    if (!IS_VALID_SESSION_WIN(winInfo)) {
162!
4006
      continue;
×
4007
    }
4008

4009
    int32_t winNum = 0;
162✔
4010
    code = compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted, true, &winNum, NULL);
162✔
4011
    QUERY_CHECK_CODE(code, lino, _end);
162!
4012

4013
    if (winNum > 0) {
162!
4014
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, winInfo.sessionWin.win.skey,
×
4015
             winInfo.sessionWin.groupId);
4016
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
4017
        code = saveResult(winInfo, pInfo->pStUpdated);
×
4018
        QUERY_CHECK_CODE(code, lino, _end);
×
4019
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
4020
        if (!isCloseWindow(&winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
4021
          code = saveDeleteRes(pInfo->pStDeleted, winInfo.sessionWin);
×
4022
          QUERY_CHECK_CODE(code, lino, _end);
×
4023
        }
4024
        SSessionKey key = {0};
×
4025
        getSessionHashKey(&winInfo.sessionWin, &key);
×
4026
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
×
4027
        QUERY_CHECK_CODE(code, lino, _end);
×
4028
      }
4029
    }
4030
    code = saveSessionOutputBuf(pAggSup, &winInfo);
162✔
4031
    QUERY_CHECK_CODE(code, lino, _end);
162!
4032
  }
4033
  taosMemoryFree(pBuf);
176!
4034

4035
  SOperatorInfo* downstream = pOperator->pDownstream[0];
176✔
4036
  if (downstream->fpSet.reloadStreamStateFn) {
176!
4037
    downstream->fpSet.reloadStreamStateFn(downstream);
176✔
4038
  }
4039
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
176✔
4040

4041
_end:
176✔
4042
  if (code != TSDB_CODE_SUCCESS) {
176!
4043
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4044
  }
4045
}
176✔
4046

4047
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
905✔
4048
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4049
  QRY_PARAM_CHECK(pOptrInfo);
905!
4050

4051
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
905✔
4052
  int32_t                        numOfCols = 0;
905✔
4053
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
905✔
4054
  int32_t                        lino = 0;
905✔
4055
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
905!
4056
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
906!
4057
  if (pInfo == NULL || pOperator == NULL) {
906!
4058
    code = terrno;
×
4059
    goto _error;
×
4060
  }
4061

4062
  pOperator->pTaskInfo = pTaskInfo;
906✔
4063

4064
  initResultSizeInfo(&pOperator->resultInfo, 4096);
906✔
4065
  if (pSessionNode->window.pExprs != NULL) {
906✔
4066
    int32_t    numOfScalar = 0;
1✔
4067
    SExprInfo* pScalarExprInfo = NULL;
1✔
4068
    code = createExprInfo(pSessionNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
4069
    QUERY_CHECK_CODE(code, lino, _error);
1!
4070

4071
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
4072
    if (code != TSDB_CODE_SUCCESS) {
1!
4073
      goto _error;
×
4074
    }
4075
  }
4076
  SExprSupp* pExpSup = &pOperator->exprSupp;
906✔
4077

4078
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
906✔
4079
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
906!
4080
  pInfo->binfo.pRes = pResBlock;
906✔
4081

4082
  SExprInfo* pExprInfo = NULL;
906✔
4083
  code = createExprInfo(pSessionNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
906✔
4084
  QUERY_CHECK_CODE(code, lino, _error);
906!
4085

4086
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
906✔
4087
  QUERY_CHECK_CODE(code, lino, _error);
905!
4088

4089
  pInfo->twAggSup = (STimeWindowAggSupp){
906✔
4090
      .waterMark = pSessionNode->window.watermark,
906✔
4091
      .calTrigger = pSessionNode->window.triggerType,
905✔
4092
      .maxTs = INT64_MIN,
4093
      .minTs = INT64_MAX,
4094
      .deleteMark = getDeleteMark(&pSessionNode->window, 0),
905✔
4095
  };
4096

4097
  pInfo->primaryTsIndex = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
906✔
4098
  code =
4099
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, pSessionNode->gap, pTaskInfo->streamInfo.pState,
906✔
4100
                             0, 0, &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
906✔
4101
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
4102
  if (code != TSDB_CODE_SUCCESS) {
905!
4103
    goto _error;
×
4104
  }
4105

4106
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
905✔
4107
  QUERY_CHECK_CODE(code, lino, _error);
905!
4108

4109
  if (pSessionNode->window.pTsEnd) {
905!
4110
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
905✔
4111
  }
4112

4113
  pInfo->order = TSDB_ORDER_ASC;
905✔
4114
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
905✔
4115
  pInfo->pStDeleted = tSimpleHashInit(64, hashFn);
903✔
4116
  QUERY_CHECK_NULL(pInfo->pStDeleted, code, lino, _error, terrno);
904!
4117
  pInfo->pDelIterator = NULL;
904✔
4118
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
904✔
4119
  QUERY_CHECK_CODE(code, lino, _error);
906!
4120

4121
  pInfo->pChildren = NULL;
906✔
4122
  pInfo->pPhyNode = pPhyNode;
906✔
4123
  pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
906✔
4124
  pInfo->ignoreExpiredDataSaved = false;
906✔
4125
  pInfo->pUpdated = NULL;
906✔
4126
  pInfo->pStUpdated = NULL;
906✔
4127
  pInfo->dataVersion = 0;
906✔
4128
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
906✔
4129
  if (!pInfo->historyWins) {
905!
4130
    goto _error;
×
4131
  }
4132
  if (pHandle) {
905!
4133
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
905✔
4134
  }
4135

4136
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
905✔
4137
  QUERY_CHECK_CODE(code, lino, _error);
905!
4138

4139
  pInfo->clearState = false;
905✔
4140
  pInfo->recvGetAll = false;
905✔
4141
  pInfo->destHasPrimaryKey = pSessionNode->window.destHasPrimaryKey;
905✔
4142
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
905✔
4143
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
906!
4144
  pInfo->pOperator = pOperator;
906✔
4145
  initNonBlockAggSupptor(&pInfo->nbSup, NULL, NULL);
906✔
4146

4147
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), nodeType(pSessionNode), true,
904✔
4148
                  OP_NOT_OPENED, pInfo, pTaskInfo);
4149
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
904✔
4150
    // for stream
4151
    void*   buff = NULL;
742✔
4152
    int32_t len = 0;
742✔
4153
    int32_t res =
4154
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
742✔
4155
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4156
    if (res == TSDB_CODE_SUCCESS) {
743!
4157
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4158
      taosMemoryFree(buff);
×
4159
      QUERY_CHECK_CODE(code, lino, _error);
×
4160
    }
4161
  }
4162

4163
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
905✔
4164
  QUERY_CHECK_CODE(code, lino, _error);
906!
4165

4166
  if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
906!
4167
    if (pHandle->fillHistory == STREAM_HISTORY_OPERATOR) {
×
4168
      setFillHistoryOperatorFlag(&pInfo->basic);
×
4169
    } else if (pHandle->fillHistory == STREAM_RECALCUL_OPERATOR) {
×
4170
      setRecalculateOperatorFlag(&pInfo->basic);
×
4171
    }
4172
    pOperator->fpSet =
4173
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionNonblockAggNext, NULL, destroyStreamSessionAggOperatorInfo,
×
4174
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4175
    setOperatorStreamStateFn(pOperator, streamSessionNonblockReleaseState, streamSessionNonblockReloadState);
×
4176
  } else {
4177
    pOperator->fpSet =
4178
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionAggNext, NULL, destroyStreamSessionAggOperatorInfo,
906✔
4179
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4180
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
905✔
4181
  }
4182

4183
  if (downstream) {
905✔
4184
    pInfo->basic.primaryPkIndex = -1;
780✔
4185
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
780✔
4186
                          &pInfo->twAggSup, &pInfo->basic, pSessionNode->window.recalculateInterval);
780✔
4187
    QUERY_CHECK_CODE(code, lino, _error);
781!
4188

4189
    code = appendDownstream(pOperator, &downstream, 1);
781✔
4190
    QUERY_CHECK_CODE(code, lino, _error);
781!
4191
  }
4192

4193
  *pOptrInfo = pOperator;
906✔
4194
  return TSDB_CODE_SUCCESS;
906✔
4195

4196
_error:
×
4197
  if (pInfo != NULL) {
×
4198
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4199
  }
4200
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
4201
  pTaskInfo->code = code;
×
4202
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4203
  return code;
×
4204
}
4205

4206
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
532✔
4207
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
532✔
4208
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
534✔
4209
  pInfo->clearState = false;
535✔
4210
}
535✔
4211

4212
int32_t deleteSessionWinState(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SSHashObj* pMapUpdate,
641✔
4213
                              SSHashObj* pMapDelete, SSHashObj* pPkDelete, bool needAdd) {
4214
  int32_t code = TSDB_CODE_SUCCESS;
641✔
4215
  int32_t lino = 0;
641✔
4216
  SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
641✔
4217
  if (!pWins) {
641!
4218
    code = terrno;
×
4219
    QUERY_CHECK_CODE(code, lino, _end);
×
4220
  }
4221
  code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
641✔
4222
  QUERY_CHECK_CODE(code, lino, _end);
641!
4223

4224
  removeSessionResults(pAggSup, pMapUpdate, pWins);
641✔
4225
  code = copyDeleteWindowInfo(pWins, pMapDelete);
641✔
4226
  QUERY_CHECK_CODE(code, lino, _end);
641!
4227

4228
  if (needAdd) {
641!
4229
    code = copyDeleteWindowInfo(pWins, pPkDelete);
×
4230
    QUERY_CHECK_CODE(code, lino, _end);
×
4231
  }
4232
  taosArrayDestroy(pWins);
641✔
4233

4234
_end:
641✔
4235
  if (code != TSDB_CODE_SUCCESS) {
641!
4236
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4237
  }
4238
  return code;
641✔
4239
}
4240

4241
static int32_t doStreamSessionSemiAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
976✔
4242
  int32_t                        code = TSDB_CODE_SUCCESS;
976✔
4243
  int32_t                        lino = 0;
976✔
4244
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
976✔
4245
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
976✔
4246
  TSKEY                          maxTs = INT64_MIN;
976✔
4247
  SExprSupp*                     pSup = &pOperator->exprSupp;
976✔
4248
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
976✔
4249
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
976✔
4250

4251
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
976✔
4252
  if (pOperator->status == OP_EXEC_DONE) {
976!
4253
    (*ppRes) = NULL;
×
4254
    return code;
×
4255
  }
4256

4257
  {
4258
    SSDataBlock* opRes = NULL;
976✔
4259
    code = buildSessionResult(pOperator, &opRes);
976✔
4260
    QUERY_CHECK_CODE(code, lino, _end);
975!
4261
    if (opRes) {
975✔
4262
      (*ppRes) = opRes;
93✔
4263
      return code;
237✔
4264
    }
4265

4266
    if (pInfo->clearState) {
882✔
4267
      clearFunctionContext(&pOperator->exprSupp);
56✔
4268
      // semi session operator clear disk buffer
4269
      clearStreamSessionOperator(pInfo);
56✔
4270
    }
4271

4272
    if (pOperator->status == OP_RES_TO_RETURN) {
882✔
4273
      if (pInfo->reCkBlock) {
144!
4274
        pInfo->reCkBlock = false;
×
4275
        printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
4276
        (*ppRes) = pInfo->pCheckpointRes;
×
4277
        return code;
×
4278
      }
4279
      clearFunctionContext(&pOperator->exprSupp);
144✔
4280
      // semi session operator clear disk buffer
4281
      clearStreamSessionOperator(pInfo);
144✔
4282
      setStreamOperatorCompleted(pOperator);
144✔
4283
      (*ppRes) = NULL;
144✔
4284
      return code;
144✔
4285
    }
4286
  }
4287

4288
  SOperatorInfo* downstream = pOperator->pDownstream[0];
738✔
4289
  if (!pInfo->pUpdated) {
738✔
4290
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
535✔
4291
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
535!
4292
  }
4293
  if (!pInfo->pStUpdated) {
738✔
4294
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
535✔
4295
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
535✔
4296
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
537!
4297
  }
4298
  while (1) {
371✔
4299
    SSDataBlock* pBlock = NULL;
1,111✔
4300
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,111✔
4301
    QUERY_CHECK_CODE(code, lino, _end);
1,111!
4302

4303
    if (pBlock == NULL) {
1,111✔
4304
      pOperator->status = OP_RES_TO_RETURN;
480✔
4305
      break;
480✔
4306
    }
4307
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
631✔
4308
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
631✔
4309

4310
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
631✔
4311
        pBlock->info.type == STREAM_CLEAR) {
580✔
4312
      // gap must be 0
4313
      code = deleteSessionWinState(pAggSup, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, NULL, false);
56✔
4314
      QUERY_CHECK_CODE(code, lino, _end);
56!
4315
      pInfo->clearState = true;
56✔
4316
      break;
56✔
4317
    } else if (pBlock->info.type == STREAM_GET_ALL) {
575!
4318
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
×
4319
      QUERY_CHECK_CODE(code, lino, _end);
×
4320
      continue;
15✔
4321
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
575✔
4322
      (*ppRes) = pBlock;
204✔
4323
      return code;
204✔
4324
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
371✔
4325
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
15✔
4326
      doStreamSessionSaveCheckpoint(pOperator);
15✔
4327
      continue;
15✔
4328
    } else {
4329
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
356!
4330
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4331
        QUERY_CHECK_CODE(code, lino, _end);
×
4332
      }
4333
    }
4334

4335
    if (pInfo->scalarSupp.pExprInfo != NULL) {
356!
4336
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
4337
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
4338
      QUERY_CHECK_CODE(code, lino, _end);
×
4339
    }
4340
    // the pDataBlock are always the same one, no need to call this again
4341
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
356✔
4342
    QUERY_CHECK_CODE(code, lino, _end);
356!
4343
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
356✔
4344
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
356✔
4345
  }
4346

4347
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
536✔
4348
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
536✔
4349

4350
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
536✔
4351
  QUERY_CHECK_CODE(code, lino, _end);
536!
4352

4353
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
536✔
4354

4355
  if (pInfo->isHistoryOp) {
536✔
4356
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
15✔
4357
    QUERY_CHECK_CODE(code, lino, _end);
15!
4358
  }
4359

4360
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
536✔
4361
  pInfo->pUpdated = NULL;
536✔
4362
  code = blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
536✔
4363
  QUERY_CHECK_CODE(code, lino, _end);
536!
4364

4365
  SSDataBlock* opRes = NULL;
536✔
4366
  code = buildSessionResult(pOperator, &opRes);
536✔
4367
  QUERY_CHECK_CODE(code, lino, _end);
536!
4368
  if (opRes) {
536✔
4369
    (*ppRes) = opRes;
200✔
4370
    return code;
200✔
4371
  }
4372

4373
_end:
336✔
4374
  if (code != TSDB_CODE_SUCCESS) {
336!
4375
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4376
    pTaskInfo->code = code;
×
4377
    T_LONG_JMP(pTaskInfo->env, code);
×
4378
  }
4379

4380
  clearFunctionContext(&pOperator->exprSupp);
336✔
4381
  // semi session operator clear disk buffer
4382
  clearStreamSessionOperator(pInfo);
330✔
4383
  setStreamOperatorCompleted(pOperator);
335✔
4384
  (*ppRes) = NULL;
335✔
4385
  return code;
335✔
4386
}
4387

4388
static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
×
4389
  SSDataBlock* pRes = NULL;
×
4390
  int32_t      code = doStreamSessionSemiAggNext(pOperator, &pRes);
×
4391
  return pRes;
×
4392
}
4393

4394
int32_t createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
288✔
4395
                                                SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle,
4396
                                                SOperatorInfo** pOptrInfo) {
4397
  QRY_PARAM_CHECK(pOptrInfo);
288!
4398

4399
  int32_t        code = TSDB_CODE_SUCCESS;
288✔
4400
  int32_t        lino = 0;
288✔
4401
  SOperatorInfo* pOperator = NULL;
288✔
4402
  code = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, &pOperator);
288✔
4403
  if (pOperator == NULL || code != 0) {
288!
4404
    downstream = NULL;
×
4405
    QUERY_CHECK_CODE(code, lino, _error);
×
4406
  }
4407

4408
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
288✔
4409
  pInfo->pOperator = pOperator;
288✔
4410

4411
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
288✔
4412
    pOperator->fpSet =
125✔
4413
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAggNext, NULL, destroyStreamSessionAggOperatorInfo,
125✔
4414
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4415
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionSemiReloadState);
125✔
4416
  }
4417

4418
  if (numOfChild > 0) {
288✔
4419
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
38✔
4420
    QUERY_CHECK_NULL(pInfo->pChildren, code, lino, _error, terrno);
38!
4421
    for (int32_t i = 0; i < numOfChild; i++) {
163✔
4422
      SOperatorInfo* pChildOp = NULL;
125✔
4423
      code = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0, pHandle, &pChildOp);
125✔
4424
      if (pChildOp == NULL || code != 0) {
125!
4425
        QUERY_CHECK_CODE(code, lino, _error);
×
4426
      }
4427

4428
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
125✔
4429
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
125✔
4430
      pTaskInfo->storageAPI.stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i, pInfo->primaryTsIndex);
125✔
4431
      void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
125✔
4432
      if (!tmp) {
125!
4433
        code = terrno;
×
4434
        QUERY_CHECK_CODE(code, lino, _error);
×
4435
      }
4436
    }
4437

4438
    void*   buff = NULL;
38✔
4439
    int32_t len = 0;
38✔
4440
    int32_t res =
4441
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
38✔
4442
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4443
    if (res == TSDB_CODE_SUCCESS) {
38!
4444
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4445
      taosMemoryFree(buff);
×
4446
      QUERY_CHECK_CODE(code, lino, _error);
×
4447
    }
4448
  }
4449

4450
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
288✔
4451
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
250✔
4452
  }
4453

4454
  *pOptrInfo = pOperator;
288✔
4455
  return code;
288✔
4456

4457
_error:
×
4458
  if (pInfo != NULL) {
×
4459
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4460
  }
4461
  if (pOperator != NULL) {
×
4462
    pOperator->info = NULL;
×
4463
    destroyOperator(pOperator);
×
4464
  }
4465
  pTaskInfo->code = code;
×
4466
  if (code != TSDB_CODE_SUCCESS) {
×
4467
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4468
  }
4469
  return code;
×
4470
}
4471

4472
void destroyStreamStateOperatorInfo(void* param) {
352✔
4473
  if (param == NULL) {
352!
4474
    return;
×
4475
  }
4476
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
352✔
4477
  cleanupBasicInfo(&pInfo->binfo);
352✔
4478
  if (pInfo->pOperator) {
352!
4479
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
352✔
4480
                              &pInfo->groupResInfo);
4481
    pInfo->pOperator = NULL;
352✔
4482
  }
4483

4484
  destroyStreamBasicInfo(&pInfo->basic);
352✔
4485
  clearSessionGroupResInfo(&pInfo->groupResInfo);
352✔
4486
  taosArrayDestroyEx(pInfo->pUpdated, destroyResultWinInfo);
352✔
4487
  pInfo->pUpdated = NULL;
352✔
4488
  destroyStreamAggSupporter(&pInfo->streamAggSup);
352✔
4489

4490
  cleanupExprSupp(&pInfo->scalarSupp);
352✔
4491
  if (pInfo->pChildren != NULL) {
352!
4492
    int32_t size = taosArrayGetSize(pInfo->pChildren);
×
4493
    for (int32_t i = 0; i < size; i++) {
×
4494
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
×
4495
      destroyOperator(pChild);
×
4496
    }
4497
    taosArrayDestroy(pInfo->pChildren);
×
4498
  }
4499
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
352✔
4500
  blockDataDestroy(pInfo->pDelRes);
352✔
4501
  tSimpleHashCleanup(pInfo->pSeUpdated);
352✔
4502
  tSimpleHashCleanup(pInfo->pSeDeleted);
352✔
4503
  cleanupGroupResInfo(&pInfo->groupResInfo);
352✔
4504

4505
  taosArrayDestroy(pInfo->historyWins);
352✔
4506
  blockDataDestroy(pInfo->pCheckpointRes);
352✔
4507
  tSimpleHashCleanup(pInfo->pPkDeleted);
352✔
4508
  destroyNonBlockAggSupptor(&pInfo->nbSup);
352✔
4509

4510
  taosMemoryFreeClear(param);
352!
4511
}
4512

4513
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
3,981✔
4514
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
3,981✔
4515
    return true;
1,292✔
4516
  }
4517
  return false;
2,689✔
4518
}
4519

4520
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
6,561✔
4521
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
6,561!
4522
}
4523

4524
bool compareStateKey(void* data, void* key) {
2,648✔
4525
  if (!data || !key) {
2,648!
4526
    return true;
×
4527
  }
4528
  SStateKeys* stateKey = (SStateKeys*)key;
2,648✔
4529
  stateKey->pData = (char*)key + sizeof(SStateKeys);
2,648✔
4530
  return compareVal(data, stateKey);
2,648✔
4531
}
4532

4533
bool compareWinStateKey(SStateKeys* left, SStateKeys* right) {
129✔
4534
  if (!left || !right) {
129!
4535
    return false;
129✔
4536
  }
4537
  return compareVal(left->pData, right);
×
4538
}
4539

4540
void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
3,392✔
4541
  SStreamStateCur* pCur = NULL;
3,392✔
4542

4543
  if (pAggSup == NULL || pNextWin == NULL) {
3,392!
4544
    return;
×
4545
  }
4546

4547
  if (asc)
3,392!
4548
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
3,392✔
4549
  else
4550
    pCur = pAggSup->stateStore.streamStateSessionSeekKeyPrev(pAggSup->pState, &pNextWin->winInfo.sessionWin);
×
4551
  int32_t nextSize = pAggSup->resultRowSize;
3,392✔
4552
  int32_t winCode = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin,
3,392✔
4553
                                                                     (void**)&pNextWin->winInfo.pStatePos, &nextSize);
3,392✔
4554
  if (winCode != TSDB_CODE_SUCCESS) {
3,392✔
4555
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
3,236✔
4556
  } else {
4557
    pNextWin->pStateKey =
156✔
4558
        (SStateKeys*)((char*)pNextWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
156✔
4559
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
156✔
4560
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
156✔
4561
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
156✔
4562
    pNextWin->pStateKey->isNull = false;
156✔
4563
    pNextWin->winInfo.isOutput = true;
156✔
4564
  }
4565
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,392✔
4566
}
4567

4568
int32_t getStateWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SStateWindowInfo* pCurWin,
129✔
4569
                                SStateWindowInfo* pNextWin) {
4570
  int32_t code = TSDB_CODE_SUCCESS;
129✔
4571
  int32_t lino = 0;
129✔
4572
  int32_t size = pAggSup->resultRowSize;
129✔
4573
  pCurWin->winInfo.sessionWin.groupId = pKey->groupId;
129✔
4574
  pCurWin->winInfo.sessionWin.win.skey = pKey->win.skey;
129✔
4575
  pCurWin->winInfo.sessionWin.win.ekey = pKey->win.ekey;
129✔
4576
  code = getSessionWindowInfoByKey(pAggSup, pKey, &pCurWin->winInfo);
129✔
4577
  QUERY_CHECK_CODE(code, lino, _end);
129!
4578
  QUERY_CHECK_CONDITION((IS_VALID_SESSION_WIN(pCurWin->winInfo)), code, lino, _end,
129!
4579
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4580

4581
  pCurWin->pStateKey =
129✔
4582
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
129✔
4583
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
129✔
4584
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
129✔
4585
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
129✔
4586
  pCurWin->pStateKey->isNull = false;
129✔
4587
  pCurWin->winInfo.isOutput = true;
129✔
4588
  if (pCurWin->winInfo.pStatePos->needFree) {
129!
4589
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
129✔
4590
  }
4591

4592
  qDebug("===stream===get state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
129✔
4593
         pCurWin->winInfo.sessionWin.win.ekey);
4594

4595
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
129✔
4596
  getNextStateWin(pAggSup, pNextWin, true);
129✔
4597

4598
_end:
129✔
4599
  qDebug("===stream===get state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
129✔
4600
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4601
  if (code != TSDB_CODE_SUCCESS) {
129!
4602
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4603
  }
4604
  return code;
129✔
4605
}
4606

4607
int32_t setStateOutputBuf(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
3,263✔
4608
                          SStateWindowInfo* pCurWin, SStateWindowInfo* pNextWin, int32_t* pWinCode) {
4609
  int32_t size = pAggSup->resultRowSize;
3,263✔
4610
  pCurWin->winInfo.sessionWin.groupId = groupId;
3,263✔
4611
  pCurWin->winInfo.sessionWin.win.skey = ts;
3,263✔
4612
  pCurWin->winInfo.sessionWin.win.ekey = ts;
3,263✔
4613
  int32_t code = TSDB_CODE_SUCCESS;
3,263✔
4614
  int32_t lino = 0;
3,263✔
4615
  int32_t winCode = TSDB_CODE_SUCCESS;
3,263✔
4616
  code = pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData,
3,263✔
4617
                                                           pAggSup->stateKeySize, compareStateKey,
4618
                                                           (void**)&pCurWin->winInfo.pStatePos, &size, &winCode);
3,263✔
4619
  QUERY_CHECK_CODE(code, lino, _end);
3,262!
4620

4621
  pCurWin->pStateKey =
3,262✔
4622
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
3,262✔
4623
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
3,262✔
4624
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
3,262✔
4625
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
3,262✔
4626
  pCurWin->pStateKey->isNull = false;
3,262✔
4627

4628
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->winInfo.sessionWin.win)) {
3,262!
4629
    winCode = TSDB_CODE_FAILED;
×
4630
    clearOutputBuf(pAggSup->pState, pCurWin->winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
4631
    pCurWin->pStateKey =
×
4632
        (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
×
4633
    pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
×
4634
    pCurWin->pStateKey->type = pAggSup->stateKeyType;
×
4635
    pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
×
4636
    pCurWin->pStateKey->isNull = false;
×
4637
    pCurWin->winInfo.sessionWin.groupId = groupId;
×
4638
    pCurWin->winInfo.sessionWin.win.skey = ts;
×
4639
    pCurWin->winInfo.sessionWin.win.ekey = ts;
×
4640
    qDebug("===stream===reset state win key. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
×
4641
           pCurWin->winInfo.sessionWin.win.ekey);
4642
  }
4643

4644
  if (winCode == TSDB_CODE_SUCCESS) {
3,262✔
4645
    pCurWin->winInfo.isOutput = true;
2,017✔
4646
    if (pCurWin->winInfo.pStatePos->needFree) {
2,017✔
4647
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
59✔
4648
    }
4649
  } else if (pKeyData) {
1,245!
4650
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,245!
4651
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4652
    } else {
4653
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,241✔
4654
    }
4655
  }
4656

4657
  *pWinCode = winCode;
3,262✔
4658

4659
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
3,262✔
4660
         pCurWin->winInfo.sessionWin.win.ekey);
4661

4662
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
3,263✔
4663
  getNextStateWin(pAggSup, pNextWin, true);
3,263✔
4664
  qDebug("===stream===set state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
3,263✔
4665
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4666
_end:
1,539✔
4667
  if (code != TSDB_CODE_SUCCESS) {
3,263!
4668
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4669
  }
4670
  return code;
3,263✔
4671
}
4672

4673
int32_t updateStateWindowInfo(SStreamAggSupporter* pAggSup, SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin,
3,263✔
4674
                              TSKEY* pTs, uint64_t groupId, SColumnInfoData* pKeyCol, int32_t rows, int32_t start,
4675
                              bool* allEqual, SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted,
4676
                              int32_t* pWinRows) {
4677
  int32_t code = TSDB_CODE_SUCCESS;
3,263✔
4678
  int32_t lino = 0;
3,263✔
4679
  *allEqual = true;
3,263✔
4680
  for (int32_t i = start; i < rows; ++i) {
7,135✔
4681
    char* pKeyData = colDataGetData(pKeyCol, i);
3,981!
4682
    if (!isTsInWindow(pWinInfo, pTs[i])) {
3,981✔
4683
      if (isEqualStateKey(pWinInfo, pKeyData)) {
2,689✔
4684
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
2,580✔
4685
          // ts belongs to the next window
4686
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
131!
4687
            (*pWinRows) = i - start;
×
4688
            goto _end;
×
4689
          }
4690
        }
4691
      } else {
4692
        (*pWinRows) = i - start;
109✔
4693
        goto _end;
109✔
4694
      }
4695
    }
4696

4697
    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
3,872✔
4698
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
6!
4699
        code = saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
6✔
4700
        QUERY_CHECK_CODE(code, lino, _end);
6!
4701
      }
4702
      removeSessionResult(pAggSup, pSeUpdated, pResultRows, &pWinInfo->winInfo.sessionWin);
6✔
4703
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
6✔
4704
    }
4705
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
3,872✔
4706
    memcpy(pWinInfo->winInfo.pStatePos->pKey, &pWinInfo->winInfo.sessionWin, sizeof(SSessionKey));
3,872✔
4707
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
3,872✔
4708
      *allEqual = false;
24✔
4709
    }
4710
  }
4711
  (*pWinRows) = rows - start;
3,154✔
4712

4713
_end:
3,263✔
4714
  if (code != TSDB_CODE_SUCCESS) {
3,263!
4715
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4716
  }
4717
  return code;
3,263✔
4718
}
4719

4720
static bool isWinResult(SSessionKey* pKey, SSHashObj* pSeUpdate, SSHashObj* pResults) {
3,263✔
4721
  SSessionKey checkKey = {0};
3,263✔
4722
  getSessionHashKey(pKey, &checkKey);
3,263✔
4723
  if (tSimpleHashGet(pSeUpdate, &checkKey, sizeof(SSessionKey)) != NULL) {
3,263✔
4724
    return true;
30✔
4725
  }
4726

4727
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
3,233✔
4728
    return true;
17✔
4729
  }
4730
  return false;
3,216✔
4731
}
4732

4733
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
3,166✔
4734
                                 SSHashObj* pStDeleted) {
4735
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3,166✔
4736
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
3,166✔
4737

4738
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,166✔
4739
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
3,166✔
4740
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
3,166✔
4741
  int32_t                      code = TSDB_CODE_SUCCESS;
3,166✔
4742
  int32_t                      lino = 0;
3,166✔
4743
  TSKEY*                       tsCols = NULL;
3,166✔
4744
  SResultRow*                  pResult = NULL;
3,166✔
4745
  int32_t                      winRows = 0;
3,166✔
4746
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
3,166✔
4747
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
3,166✔
4748
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
3,166✔
4749

4750
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,166✔
4751
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,166✔
4752
  if (pAggSup->winRange.ekey <= 0) {
3,166!
4753
    pAggSup->winRange.ekey = INT64_MAX;
×
4754
  }
4755

4756
  if (pSDataBlock->pDataBlock != NULL) {
3,166!
4757
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,166✔
4758
    if (!pColDataInfo) {
3,166!
4759
      code = TSDB_CODE_FAILED;
×
4760
      QUERY_CHECK_CODE(code, lino, _end);
×
4761
    }
4762
    tsCols = (int64_t*)pColDataInfo->pData;
3,166✔
4763
  } else {
4764
    return;
×
4765
  }
4766

4767
  int32_t rows = pSDataBlock->info.rows;
3,166✔
4768
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
3,166✔
4769
  QUERY_CHECK_CODE(code, lino, _end);
3,165!
4770

4771
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
3,165✔
4772
  for (int32_t i = 0; i < rows; i += winRows) {
6,449✔
4773
    if (pInfo->ignoreExpiredData && checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo,
3,347✔
4774
                                                     &pInfo->twAggSup, pSDataBlock->info.id.uid, tsCols[i], NULL, 0) ||
64✔
4775
        colDataIsNull_s(pKeyColInfo, i)) {
6,540✔
4776
      i++;
21✔
4777
      continue;
42✔
4778
    }
4779
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
3,262!
4780
    int32_t          winIndex = 0;
3,262✔
4781
    bool             allEqual = true;
3,262✔
4782
    SStateWindowInfo curWin = {0};
3,262✔
4783
    SStateWindowInfo nextWin = {0};
3,262✔
4784
    int32_t          winCode = TSDB_CODE_SUCCESS;
3,262✔
4785
    code = setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin, &winCode);
3,262✔
4786
    QUERY_CHECK_CODE(code, lino, _end);
3,263!
4787

4788
    if (winCode != TSDB_CODE_SUCCESS && pTaskInfo->streamInfo.eventTypes) {
3,263!
4789
      SStateWindowInfo prevWin = {.winInfo.sessionWin = curWin.winInfo.sessionWin};
×
4790
      getNextStateWin(pAggSup, &prevWin, false);
×
4791
      qDebug("===stream===get state prev win buff. skey:%" PRId64 ", endkey:%" PRId64,
×
4792
             prevWin.winInfo.sessionWin.win.skey, prevWin.winInfo.sessionWin.win.ekey);
4793
      releaseOutputBuf(pAggSup->pState, prevWin.winInfo.pStatePos, &pAPI->stateStore);
×
4794
      // For ordered data, the previous window's closure did not record the corresponding state values, so they need to
4795
      // be added here.
4796
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE) &&
×
4797
          IS_VALID_SESSION_WIN(prevWin.winInfo)) {
×
4798
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &prevWin.winInfo.sessionWin, prevWin.pStateKey,
×
4799
                                      curWin.pStateKey, true, pNotifySup, pNotifyEventStat);
×
4800
        QUERY_CHECK_CODE(code, lino, _end);
×
4801
      }
4802
      if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
×
4803
        code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4804
                                      prevWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4805
        QUERY_CHECK_CODE(code, lino, _end);
×
4806
      }
4807
    }
4808

4809
    if (isWinResult(&nextWin.winInfo.sessionWin, pSeUpdated, pAggSup->pResultRows) == false) {
3,263✔
4810
      releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,216✔
4811
    }
4812

4813
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
3,263✔
4814
    code = updateStateWindowInfo(pAggSup, &curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
3,263✔
4815
                                 pAggSup->pResultRows, pSeUpdated, pStDeleted, &winRows);
4816
    QUERY_CHECK_CODE(code, lino, _end);
3,263!
4817

4818
    if (!allEqual) {
3,263✔
4819
      uint64_t uid = 0;
21✔
4820
      code = appendDataToSpecialBlock(pAggSup->pScanBlock, &curWin.winInfo.sessionWin.win.skey,
21✔
4821
                                      &curWin.winInfo.sessionWin.win.ekey, &uid, &groupId, NULL);
4822
      QUERY_CHECK_CODE(code, lino, _end);
21!
4823
      int32_t tmpRes = tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
21✔
4824
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
21!
4825

4826
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
21✔
4827
      releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
21✔
4828
      continue;
21✔
4829
    }
4830

4831
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
3,242✔
4832
                              pOperator, 0);
4833
    QUERY_CHECK_CODE(code, lino, _end);
3,242!
4834

4835
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,242✔
4836
    QUERY_CHECK_CODE(code, lino, _end);
3,242!
4837

4838
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
3,242!
4839
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
1✔
4840
      QUERY_CHECK_CODE(code, lino, _end);
1!
4841
    }
4842

4843
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,242✔
4844
      code = saveResult(curWin.winInfo, pSeUpdated);
2,929✔
4845
      QUERY_CHECK_CODE(code, lino, _end);
2,929!
4846
    }
4847

4848
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,242✔
4849
      curWin.winInfo.pStatePos->beUpdated = true;
313✔
4850
      SSessionKey key = {0};
313✔
4851
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
313✔
4852
      code =
4853
          tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
313✔
4854
      QUERY_CHECK_CODE(code, lino, _end);
313!
4855
    }
4856

4857
    // If this is a windown recalculation, add the corresponding state values here since the next window may not require
4858
    // recalculation.
4859
    if (BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE)) {
3,242!
4860
      code = addStateAggNotifyEvent(SNOTIFY_EVENT_WINDOW_CLOSE, &curWin.winInfo.sessionWin, curWin.pStateKey,
×
4861
                                    nextWin.pStateKey, false, pNotifySup, pNotifyEventStat);
×
4862
      QUERY_CHECK_CODE(code, lino, _end);
×
4863
    }
4864
  }
4865

4866
_end:
3,166✔
4867
  if (code != TSDB_CODE_SUCCESS) {
3,166!
4868
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4869
  }
4870
}
4871

4872
int32_t doStreamStateEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
2✔
4873
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
2✔
4874
  if (!pInfo) {
2!
4875
    return 0;
×
4876
  }
4877

4878
  void* pData = (buf == NULL) ? NULL : *buf;
2✔
4879

4880
  // 1.streamAggSup.pResultRows
4881
  int32_t tlen = 0;
2✔
4882
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
2✔
4883
  tlen += taosEncodeFixedI32(buf, mapSize);
2✔
4884
  void*   pIte = NULL;
2✔
4885
  size_t  keyLen = 0;
2✔
4886
  int32_t iter = 0;
2✔
4887
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
4✔
4888
    void* key = tSimpleHashGetKey(pIte, &keyLen);
2✔
4889
    tlen += encodeSSessionKey(buf, key);
2✔
4890
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
2✔
4891
  }
4892

4893
  // 2.twAggSup
4894
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
2✔
4895

4896
  // 3.pChildren
4897
  int32_t size = taosArrayGetSize(pInfo->pChildren);
2✔
4898
  tlen += taosEncodeFixedI32(buf, size);
2✔
4899
  for (int32_t i = 0; i < size; i++) {
2!
4900
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4901
    tlen += doStreamStateEncodeOpState(buf, 0, pChOp, false);
×
4902
  }
4903

4904
  // 4.dataVersion
4905
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
2✔
4906

4907
  // 5.basicInfo
4908
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
2✔
4909

4910
  // 6.checksum
4911
  if (isParent) {
2!
4912
    if (buf) {
2✔
4913
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
2!
4914
      tlen += taosEncodeFixedU32(buf, cksum);
1✔
4915
    } else {
4916
      tlen += sizeof(uint32_t);
1✔
4917
    }
4918
  }
4919

4920
  return tlen;
2✔
4921
}
4922

4923
int32_t doStreamStateDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
1✔
4924
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
1✔
4925
  int32_t                      code = TSDB_CODE_SUCCESS;
1✔
4926
  int32_t                      lino = 0;
1✔
4927
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
1✔
4928
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1✔
4929
  void*                        pDataEnd = POINTER_SHIFT(buf, len);
1✔
4930
  if (!pInfo) {
1!
4931
    code = TSDB_CODE_FAILED;
×
4932
    QUERY_CHECK_CODE(code, lino, _end);
×
4933
  }
4934

4935
  // 6.checksum
4936
  if (isParent) {
1!
4937
    int32_t dataLen = len - sizeof(uint32_t);
1✔
4938
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
1✔
4939
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
2!
4940
      qError("stream state_window state is invalid");
×
4941
      code = TSDB_CODE_FAILED;
×
4942
      QUERY_CHECK_CODE(code, lino, _end);
×
4943
    }
4944
    pDataEnd = pCksum;
1✔
4945
  }
4946

4947
  // 1.streamAggSup.pResultRows
4948
  int32_t mapSize = 0;
1✔
4949
  buf = taosDecodeFixedI32(buf, &mapSize);
1!
4950
  for (int32_t i = 0; i < mapSize; i++) {
2✔
4951
    SResultWindowInfo winfo = {0};
1✔
4952
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
1✔
4953
    int32_t winCode = TSDB_CODE_SUCCESS;
1✔
4954
    code = pAggSup->stateStore.streamStateStateAddIfNotExist(
1✔
4955
        pAggSup->pState, &winfo.sessionWin, NULL, pAggSup->stateKeySize, compareStateKey, (void**)&winfo.pStatePos,
4956
        &pAggSup->resultRowSize, &winCode);
4957
    QUERY_CHECK_CODE(code, lino, _end);
1!
4958

4959
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
1✔
4960
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
1✔
4961
                          sizeof(SResultWindowInfo));
4962
    QUERY_CHECK_CODE(code, lino, _end);
1!
4963
  }
4964

4965
  // 2.twAggSup
4966
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
1✔
4967

4968
  // 3.pChildren
4969
  int32_t size = 0;
1✔
4970
  buf = taosDecodeFixedI32(buf, &size);
1!
4971
  for (int32_t i = 0; i < size; i++) {
1!
4972
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4973
    code = doStreamStateDecodeOpState(buf, 0, pChOp, false, &buf);
×
4974
    QUERY_CHECK_CODE(code, lino, _end);
×
4975
  }
4976

4977
  // 4.dataVersion
4978
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
1!
4979

4980
  if (ppBuf) {
1!
4981
    (*ppBuf) = buf;
×
4982
  }
4983

4984
  // 5.basicInfo
4985
  if (buf < pDataEnd) {
1!
4986
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
1✔
4987
    QUERY_CHECK_CODE(code, lino, _end);
1!
4988
  }
4989

4990
_end:
1✔
4991
  if (code != TSDB_CODE_SUCCESS) {
1!
4992
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4993
  }
4994
  return code;
1✔
4995
}
4996

4997
void doStreamStateSaveCheckpoint(SOperatorInfo* pOperator) {
101✔
4998
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
101✔
4999
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
101✔
5000
    int32_t len = doStreamStateEncodeOpState(NULL, 0, pOperator, true);
1✔
5001
    void*   buf = taosMemoryCalloc(1, len);
1!
5002
    if (!buf) {
1!
5003
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
5004
      return;
×
5005
    }
5006
    void* pBuf = buf;
1✔
5007
    len = doStreamStateEncodeOpState(&pBuf, len, pOperator, true);
1✔
5008
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
1✔
5009
                                                       strlen(STREAM_STATE_OP_CHECKPOINT_NAME), buf, len);
5010
    taosMemoryFree(buf);
1!
5011
    saveStreamOperatorStateComplete(&pInfo->basic);
1✔
5012
  }
5013
}
5014

5015
static int32_t buildStateResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
3,849✔
5016
  int32_t                      code = TSDB_CODE_SUCCESS;
3,849✔
5017
  int32_t                      lino = 0;
3,849✔
5018
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3,849✔
5019
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
3,849✔
5020
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
3,849✔
5021
  SStreamNotifyEventSupp*      pNotifySup = &pInfo->basic.notifyEventSup;
3,849✔
5022
  STaskNotifyEventStat*        pNotifyEventStat = pTaskInfo->streamInfo.pNotifyEventStat;
3,849✔
5023
  bool                         addNotifyEvent = false;
3,849✔
5024
  addNotifyEvent = BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
3,849✔
5025
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator, &pInfo->groupResInfo);
3,849✔
5026
  if (pInfo->pDelRes->info.rows > 0) {
3,849✔
5027
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
203✔
5028
    if (addNotifyEvent) {
203!
5029
      code = addAggDeleteNotifyEvent(pInfo->pDelRes, pNotifySup, pNotifyEventStat);
×
5030
      QUERY_CHECK_CODE(code, lino, _end);
×
5031
    }
5032
    (*ppRes) = pInfo->pDelRes;
203✔
5033
    return code;
203✔
5034
  }
5035

5036
  doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes,
3,646!
5037
                       addNotifyEvent ? pNotifySup->pSessionKeys : NULL);
5038
  if (pBInfo->pRes->info.rows > 0) {
3,647✔
5039
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,291✔
5040
    if (addNotifyEvent) {
1,291!
5041
      code = addAggResultNotifyEvent(pBInfo->pRes, pNotifySup->pSessionKeys, pTaskInfo->streamInfo.notifyResultSchema,
×
5042
                                     pNotifySup, pNotifyEventStat);
5043
      QUERY_CHECK_CODE(code, lino, _end);
×
5044
    }
5045
    (*ppRes) = pBInfo->pRes;
1,291✔
5046
    return code;
1,291✔
5047
  }
5048

5049
  code = buildNotifyEventBlock(pTaskInfo, pNotifySup, pNotifyEventStat);
2,356✔
5050
  QUERY_CHECK_CODE(code, lino, _end);
2,356!
5051
  if (pNotifySup->pEventBlock && pNotifySup->pEventBlock->info.rows > 0) {
2,356!
5052
    printDataBlock(pNotifySup->pEventBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5053
    (*ppRes) = pNotifySup->pEventBlock;
×
5054
    return code;
×
5055
  }
5056

5057
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
2,356✔
5058
  QUERY_CHECK_CODE(code, lino, _end);
2,356!
5059

5060
_end:
2,356✔
5061
  if (code != TSDB_CODE_SUCCESS) {
2,356!
5062
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5063
  }
5064
  (*ppRes) = NULL;
2,356✔
5065
  return code;
2,356✔
5066
}
5067

5068
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,250✔
5069
  if (pOperator->status == OP_EXEC_DONE) {
4,250!
5070
    (*ppRes) = NULL;
×
5071
    return TSDB_CODE_SUCCESS;
×
5072
  }
5073

5074
  int32_t                      code = TSDB_CODE_SUCCESS;
4,250✔
5075
  int32_t                      lino = 0;
4,250✔
5076
  SExprSupp*                   pSup = &pOperator->exprSupp;
4,250✔
5077
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4,250✔
5078
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
4,250✔
5079
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4,250✔
5080
  qDebug("===stream=== stream state agg");
4,250✔
5081
  if (pOperator->status == OP_RES_TO_RETURN) {
4,250✔
5082
    SSDataBlock* resBlock = NULL;
1,494✔
5083
    code = buildStateResult(pOperator, &resBlock);
1,494✔
5084
    QUERY_CHECK_CODE(code, lino, _end);
1,494!
5085
    if (resBlock != NULL) {
1,494✔
5086
      (*ppRes) = resBlock;
361✔
5087
      return code;
1,494✔
5088
    }
5089

5090
    if (pInfo->recvGetAll) {
1,133✔
5091
      pInfo->recvGetAll = false;
2✔
5092
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
2✔
5093
    }
5094

5095
    if (pInfo->reCkBlock) {
1,133!
5096
      pInfo->reCkBlock = false;
×
5097
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5098
      (*ppRes) = pInfo->pCheckpointRes;
×
5099
      return code;
×
5100
    }
5101

5102
    setStreamOperatorCompleted(pOperator);
1,133✔
5103
    (*ppRes) = NULL;
1,133✔
5104
    return code;
1,133✔
5105
  }
5106

5107
  SOperatorInfo* downstream = pOperator->pDownstream[0];
2,756✔
5108
  if (!pInfo->pUpdated) {
2,756✔
5109
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,355✔
5110
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,356!
5111
  }
5112
  if (!pInfo->pSeUpdated) {
2,757✔
5113
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,323✔
5114
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,323✔
5115
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,323!
5116
  }
5117
  while (1) {
3,804✔
5118
    SSDataBlock* pBlock = NULL;
6,561✔
5119
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
6,561✔
5120
    QUERY_CHECK_CODE(code, lino, _end);
6,559!
5121

5122
    if (pBlock == NULL) {
6,559✔
5123
      break;
2,354✔
5124
    }
5125
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,205✔
5126
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,205✔
5127

5128
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,205✔
5129
        pBlock->info.type == STREAM_CLEAR) {
3,728✔
5130
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
530!
5131
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
530✔
5132
                                   pInfo->pPkDeleted, add);
5133
      QUERY_CHECK_CODE(code, lino, _end);
530!
5134
      continue;
638✔
5135
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,675✔
5136
      pInfo->recvGetAll = true;
7✔
5137
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
7✔
5138
      QUERY_CHECK_CODE(code, lino, _end);
7!
5139
      continue;
7✔
5140
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,668✔
5141
      (*ppRes) = pBlock;
401✔
5142
      return code;
401✔
5143
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,267✔
5144
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
101✔
5145
      doStreamStateSaveCheckpoint(pOperator);
101✔
5146
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
101✔
5147
      QUERY_CHECK_CODE(code, lino, _end);
101!
5148

5149
      continue;
101✔
5150
    } else {
5151
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
3,166!
5152
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5153
        QUERY_CHECK_CODE(code, lino, _end);
×
5154
      }
5155
    }
5156

5157
    if (pInfo->scalarSupp.pExprInfo != NULL) {
3,166✔
5158
      SExprSupp* pExprSup = &pInfo->scalarSupp;
256✔
5159
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
256✔
5160
      QUERY_CHECK_CODE(code, lino, _end);
254!
5161
    }
5162
    // the pDataBlock are always the same one, no need to call this again
5163
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3,164✔
5164
    QUERY_CHECK_CODE(code, lino, _end);
3,166!
5165
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
3,166✔
5166
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
3,166✔
5167
  }
5168
  // restore the value
5169
  pOperator->status = OP_RES_TO_RETURN;
2,354✔
5170

5171
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,354✔
5172
  QUERY_CHECK_CODE(code, lino, _end);
2,355!
5173

5174
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,355✔
5175
  QUERY_CHECK_CODE(code, lino, _end);
2,356!
5176

5177
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,356✔
5178

5179
  if (pInfo->isHistoryOp) {
2,356✔
5180
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
88✔
5181
    QUERY_CHECK_CODE(code, lino, _end);
88!
5182
  }
5183
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,356!
5184
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
4✔
5185
    QUERY_CHECK_CODE(code, lino, _end);
4!
5186
  }
5187

5188
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,356✔
5189
  pInfo->pUpdated = NULL;
2,355✔
5190
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,355✔
5191
  QUERY_CHECK_CODE(code, lino, _end);
2,355!
5192

5193
  SSDataBlock* resBlock = NULL;
2,355✔
5194
  code = buildStateResult(pOperator, &resBlock);
2,355✔
5195
  QUERY_CHECK_CODE(code, lino, _end);
2,356!
5196
  if (resBlock != NULL) {
2,356✔
5197
    (*ppRes) = resBlock;
1,133✔
5198
    return code;
1,133✔
5199
  }
5200

5201
_end:
1,223✔
5202
  if (code != TSDB_CODE_SUCCESS) {
1,223!
5203
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5204
    pTaskInfo->code = code;
×
5205
    T_LONG_JMP(pTaskInfo->env, code);
×
5206
  }
5207
  setStreamOperatorCompleted(pOperator);
1,223✔
5208
  (*ppRes) = NULL;
1,223✔
5209
  return code;
1,223✔
5210
}
5211

5212
static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
×
5213
  SSDataBlock* pRes = NULL;
×
5214
  int32_t      code = doStreamStateAggNext(pOperator, &pRes);
×
5215
  return pRes;
×
5216
}
5217

5218
void streamStateReleaseState(SOperatorInfo* pOperator) {
85✔
5219
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
85✔
5220
  int32_t                      winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
85✔
5221
  int32_t                      resSize = winSize + sizeof(TSKEY);
85✔
5222
  char*                        pBuff = taosMemoryCalloc(1, resSize);
85!
5223
  if (!pBuff) {
85!
5224
    return;
×
5225
  }
5226
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
85✔
5227
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
85✔
5228
  qDebug("===stream=== relase state. save result count:%d", (int32_t)taosArrayGetSize(pInfo->historyWins));
85✔
5229
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_STATE_NAME,
85✔
5230
                                                     strlen(STREAM_STATE_OP_STATE_NAME), pBuff, resSize);
5231
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
85✔
5232
  taosMemoryFreeClear(pBuff);
85!
5233

5234
  SOperatorInfo* downstream = pOperator->pDownstream[0];
85✔
5235
  if (downstream->fpSet.releaseStreamStateFn) {
85!
5236
    downstream->fpSet.releaseStreamStateFn(downstream);
85✔
5237
  }
5238
}
5239

5240
int32_t compactStateWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
×
5241
                           SSHashObj* pStUpdated, SSHashObj* pStDeleted) {
5242
  SExprSupp*                   pSup = &pOperator->exprSupp;
×
5243
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
5244
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
5245
  return compactTimeWindow(pSup, &pInfo->streamAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, pNextWin, pStUpdated,
×
5246
                           pStDeleted, false);
5247
}
5248

5249
void streamStateReloadState(SOperatorInfo* pOperator) {
85✔
5250
  int32_t                      code = TSDB_CODE_SUCCESS;
85✔
5251
  int32_t                      lino = 0;
85✔
5252
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
85✔
5253
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
85✔
5254
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
85✔
5255
  resetWinRange(&pAggSup->winRange);
85✔
5256

5257
  SSessionKey seKey = {.win.skey = INT64_MIN, .win.ekey = INT64_MIN, .groupId = 0};
85✔
5258
  int32_t     size = 0;
85✔
5259
  void*       pBuf = NULL;
85✔
5260
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_STATE_OP_STATE_NAME,
85✔
5261
                                                strlen(STREAM_STATE_OP_STATE_NAME), &pBuf, &size);
5262
  QUERY_CHECK_CODE(code, lino, _end);
85!
5263

5264
  int32_t num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
85✔
5265
  qDebug("===stream=== reload state. get result count:%d", num);
85✔
5266
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
85✔
5267

5268
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
85✔
5269
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
85✔
5270
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
85✔
5271

5272
  if (!pInfo->pSeUpdated && num > 0) {
85!
5273
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
33✔
5274
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
33✔
5275
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
33!
5276
  }
5277
  if (!pInfo->pSeDeleted && num > 0) {
85!
5278
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
5279
    pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
×
5280
    QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _end, terrno);
×
5281
  }
5282
  for (int32_t i = 0; i < num; i++) {
214✔
5283
    SStateWindowInfo curInfo = {0};
129✔
5284
    SStateWindowInfo nextInfo = {0};
129✔
5285
    qDebug("===stream=== reload state. try process result %" PRId64 ", %" PRIu64 ", index:%d", pSeKeyBuf[i].win.skey,
129✔
5286
           pSeKeyBuf[i].groupId, i);
5287
    code = getStateWindowInfoByKey(pAggSup, pSeKeyBuf + i, &curInfo, &nextInfo);
129✔
5288
    QUERY_CHECK_CODE(code, lino, _end);
129!
5289

5290
    bool cpRes = compareWinStateKey(curInfo.pStateKey, nextInfo.pStateKey);
129✔
5291
    qDebug("===stream=== reload state. next window info %" PRId64 ", %" PRIu64 ", compare:%d",
129✔
5292
           nextInfo.winInfo.sessionWin.win.skey, nextInfo.winInfo.sessionWin.groupId, cpRes);
5293
    if (cpRes) {
129!
5294
      code = compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pSeUpdated, pInfo->pSeDeleted);
×
5295
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, curInfo.winInfo.sessionWin.win.skey,
×
5296
             curInfo.winInfo.sessionWin.groupId);
5297
      QUERY_CHECK_CODE(code, lino, _end);
×
5298

5299
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
5300
        code = saveResult(curInfo.winInfo, pInfo->pSeUpdated);
×
5301
        QUERY_CHECK_CODE(code, lino, _end);
×
5302
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
5303
        if (!isCloseWindow(&curInfo.winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
5304
          code = saveDeleteRes(pInfo->pSeDeleted, curInfo.winInfo.sessionWin);
×
5305
          QUERY_CHECK_CODE(code, lino, _end);
×
5306
        }
5307
        SSessionKey key = {0};
×
5308
        getSessionHashKey(&curInfo.winInfo.sessionWin, &key);
×
5309
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curInfo.winInfo,
×
5310
                              sizeof(SResultWindowInfo));
5311
        QUERY_CHECK_CODE(code, lino, _end);
×
5312
      }
5313
    } else if (IS_VALID_SESSION_WIN(nextInfo.winInfo)) {
129!
5314
      releaseOutputBuf(pAggSup->pState, nextInfo.winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
5315
    }
5316

5317
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
129!
5318
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
129✔
5319
      QUERY_CHECK_CODE(code, lino, _end);
129!
5320
    }
5321
  }
5322
  taosMemoryFreeClear(pBuf);
85!
5323

5324
  SOperatorInfo* downstream = pOperator->pDownstream[0];
85✔
5325
  if (downstream->fpSet.reloadStreamStateFn) {
85!
5326
    downstream->fpSet.reloadStreamStateFn(downstream);
85✔
5327
  }
5328
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
85✔
5329

5330
_end:
85✔
5331
  taosMemoryFreeClear(pBuf);
85!
5332
  if (code != TSDB_CODE_SUCCESS) {
85!
5333
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5334
  }
5335
}
85✔
5336

5337
int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
350✔
5338
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5339
  QRY_PARAM_CHECK(pOptrInfo);
350!
5340
  int32_t code = 0;
350✔
5341
  int32_t lino = 0;
350✔
5342

5343
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
350✔
5344
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
350✔
5345
  SColumnNode*                 pColNode = (SColumnNode*)(pStateNode->pStateKey);
350✔
5346
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
350!
5347
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
352!
5348
  if (pInfo == NULL || pOperator == NULL) {
352!
5349
    code = terrno;
×
5350
    QUERY_CHECK_CODE(code, lino, _error);
×
5351
  }
5352

5353
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
352✔
5354
  initResultSizeInfo(&pOperator->resultInfo, 4096);
352✔
5355
  if (pStateNode->window.pExprs != NULL) {
352✔
5356
    int32_t    numOfScalar = 0;
25✔
5357
    SExprInfo* pScalarExprInfo = NULL;
25✔
5358
    code = createExprInfo(pStateNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
25✔
5359
    QUERY_CHECK_CODE(code, lino, _error);
25!
5360

5361
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
25✔
5362
    QUERY_CHECK_CODE(code, lino, _error);
25!
5363
  }
5364

5365
  pInfo->twAggSup = (STimeWindowAggSupp){
352✔
5366
      .waterMark = pStateNode->window.watermark,
352✔
5367
      .calTrigger = pStateNode->window.triggerType,
352✔
5368
      .maxTs = INT64_MIN,
5369
      .minTs = INT64_MAX,
5370
      .deleteMark = getDeleteMark(&pStateNode->window, 0),
352✔
5371
  };
5372

5373
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
352✔
5374
  QUERY_CHECK_CODE(code, lino, _error);
352!
5375

5376
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
352✔
5377
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
352!
5378
  pInfo->binfo.pRes = pResBlock;
352✔
5379

5380
  SExprSupp* pExpSup = &pOperator->exprSupp;
352✔
5381
  int32_t    numOfCols = 0;
352✔
5382
  SExprInfo* pExprInfo = NULL;
352✔
5383
  code = createExprInfo(pStateNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
352✔
5384
  QUERY_CHECK_CODE(code, lino, _error);
352!
5385

5386
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
352✔
5387
  if (code != TSDB_CODE_SUCCESS) {
352!
5388
    goto _error;
×
5389
  }
5390
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
352✔
5391
  int16_t type = pColNode->node.resType.type;
352✔
5392
  pInfo->primaryTsIndex = tsSlotId;
352✔
5393
  code =
5394
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize, type,
352✔
5395
                             &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
352✔
5396
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
5397
  QUERY_CHECK_CODE(code, lino, _error);
349!
5398

5399
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
349✔
5400
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
349✔
5401
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
351!
5402
  pInfo->pDelIterator = NULL;
351✔
5403

5404
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
351✔
5405
  QUERY_CHECK_CODE(code, lino, _error);
352!
5406

5407
  pInfo->pChildren = NULL;
352✔
5408
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
352✔
5409
  pInfo->ignoreExpiredDataSaved = false;
352✔
5410
  pInfo->pUpdated = NULL;
352✔
5411
  pInfo->pSeUpdated = NULL;
352✔
5412
  pInfo->dataVersion = 0;
352✔
5413
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
352✔
5414
  if (!pInfo->historyWins) {
352!
5415
    code = terrno;
×
5416
    QUERY_CHECK_CODE(code, lino, _error);
×
5417
  }
5418

5419
  if (pHandle) {
352✔
5420
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
351✔
5421
  }
5422

5423
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
352✔
5424
  QUERY_CHECK_CODE(code, lino, _error);
352!
5425

5426
  pInfo->recvGetAll = false;
352✔
5427
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
352✔
5428
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
351!
5429
  pInfo->destHasPrimaryKey = pStateNode->window.destHasPrimaryKey;
351✔
5430
  pInfo->pOperator = pOperator;
351✔
5431

5432
  setOperatorInfo(pOperator, "StreamStateAggOperator", nodeType(pPhyNode), true, OP_NOT_OPENED,
351✔
5433
                  pInfo, pTaskInfo);
5434
  // for stream
5435
  void*   buff = NULL;
350✔
5436
  int32_t len = 0;
350✔
5437
  int32_t res =
5438
      pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
350✔
5439
                                                        strlen(STREAM_STATE_OP_CHECKPOINT_NAME), &buff, &len);
5440
  if (res == TSDB_CODE_SUCCESS) {
352✔
5441
    code = doStreamStateDecodeOpState(buff, len, pOperator, true, NULL);
1✔
5442
    taosMemoryFree(buff);
1!
5443
    QUERY_CHECK_CODE(code, lino, _error);
1!
5444
  }
5445
  initNonBlockAggSupptor(&pInfo->nbSup, NULL, NULL);
352✔
5446
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
352✔
5447
  QUERY_CHECK_CODE(code, lino, _error);
352!
5448

5449
  if (pStateNode->window.triggerType == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
352!
5450
    if (pHandle->fillHistory == STREAM_HISTORY_OPERATOR) {
×
5451
      setFillHistoryOperatorFlag(&pInfo->basic);
×
5452
    } else if (pHandle->fillHistory == STREAM_RECALCUL_OPERATOR) {
×
5453
      setRecalculateOperatorFlag(&pInfo->basic);
×
5454
    }
5455

5456
    pOperator->fpSet =
5457
        createOperatorFpSet(optrDummyOpenFn, doStreamStateNonblockAggNext, NULL, destroyStreamStateOperatorInfo,
×
5458
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5459
    setOperatorStreamStateFn(pOperator, streamStateNonblockReleaseState, streamStateNonblockReloadState);
×
5460
  } else {
5461
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAggNext, NULL, destroyStreamStateOperatorInfo,
352✔
5462
                                           optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5463
    setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
352✔
5464
  }
5465

5466
  code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
352✔
5467
                        &pInfo->twAggSup, &pInfo->basic, 0);
352✔
5468
  QUERY_CHECK_CODE(code, lino, _error);
352!
5469

5470
  code = appendDownstream(pOperator, &downstream, 1);
352✔
5471
  QUERY_CHECK_CODE(code, lino, _error);
352!
5472

5473
  pInfo->trueForLimit = pStateNode->trueForLimit;
352✔
5474

5475
  *pOptrInfo = pOperator;
352✔
5476
  return TSDB_CODE_SUCCESS;
352✔
5477

5478
_error:
×
5479
  if (pInfo != NULL) destroyStreamStateOperatorInfo(pInfo);
×
5480
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5481
  pTaskInfo->code = code;
×
5482
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5483
  return code;
×
5484
}
5485

5486
#ifdef BUILD_NO_CALL
5487
static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type) {
5488
  for (int i = 0; i < num; i++) {
5489
    if (type == STREAM_INVERT) {
5490
      fmSetInvertFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5491
    } else if (type == STREAM_NORMAL) {
5492
      fmSetNormalFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5493
    }
5494
  }
5495
}
5496
#endif
5497

5498
static int32_t doStreamIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
145,675✔
5499
  int32_t                      code = TSDB_CODE_SUCCESS;
145,675✔
5500
  int32_t                      lino = 0;
145,675✔
5501
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
145,675✔
5502
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
145,675✔
5503
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
145,675✔
5504
  SExprSupp*                   pSup = &pOperator->exprSupp;
145,675✔
5505

5506
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
145,675✔
5507

5508
  if (pOperator->status == OP_EXEC_DONE) {
145,677✔
5509
    (*ppRes) = NULL;
668✔
5510
    return code;
668✔
5511
  }
5512

5513
  if (pOperator->status == OP_RES_TO_RETURN) {
145,009✔
5514
    SSDataBlock* resBlock = NULL;
113,005✔
5515
    code = buildIntervalResult(pOperator, &resBlock);
113,005✔
5516
    QUERY_CHECK_CODE(code, lino, _end);
113,006!
5517
    if (resBlock != NULL) {
113,006✔
5518
      (*ppRes) = resBlock;
97,105✔
5519
      return code;
113,006✔
5520
    }
5521

5522
    if (pInfo->recvGetAll) {
15,901✔
5523
      pInfo->recvGetAll = false;
181✔
5524
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
181✔
5525
    }
5526

5527
    if (pInfo->reCkBlock) {
15,901✔
5528
      pInfo->reCkBlock = false;
116✔
5529
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
116✔
5530
      (*ppRes) = pInfo->pCheckpointRes;
116✔
5531
      return code;
116✔
5532
    }
5533

5534
    setStreamOperatorCompleted(pOperator);
15,785✔
5535
    (*ppRes) = NULL;
15,785✔
5536
    return code;
15,785✔
5537
  }
5538

5539
  SOperatorInfo* downstream = pOperator->pDownstream[0];
32,004✔
5540

5541
  if (!pInfo->pUpdated) {
32,004✔
5542
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
29,110✔
5543
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
29,112!
5544
  }
5545

5546
  if (!pInfo->pUpdatedMap) {
32,006✔
5547
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
29,112✔
5548
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
29,111✔
5549
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
29,115!
5550
  }
5551

5552
  while (1) {
527,189✔
5553
    SSDataBlock* pBlock = NULL;
559,198✔
5554
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
559,198✔
5555
    QUERY_CHECK_CODE(code, lino, _end);
559,203✔
5556

5557
    if (pBlock == NULL) {
559,183✔
5558
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
29,116✔
5559
             pInfo->numOfDatapack);
5560
      pInfo->numOfDatapack = 0;
29,115✔
5561
      break;
29,115✔
5562
    }
5563

5564
    pInfo->numOfDatapack++;
530,067✔
5565
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
530,067✔
5566
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
530,068✔
5567

5568
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
530,067✔
5569
        pBlock->info.type == STREAM_CLEAR) {
529,569✔
5570
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,441✔
5571
      QUERY_CHECK_CODE(code, lino, _end);
1,441!
5572
      continue;
4,095✔
5573
    } else if (pBlock->info.type == STREAM_GET_ALL) {
528,626✔
5574
      pInfo->recvGetAll = true;
973✔
5575
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
973✔
5576
      QUERY_CHECK_CODE(code, lino, _end);
973!
5577
      continue;
973✔
5578
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
527,653✔
5579
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,821✔
5580
      (*ppRes) = pBlock;
2,821✔
5581
      return code;
2,876✔
5582
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
524,832✔
5583
      doDeleteWindowByGroupId(pOperator, pBlock);
55✔
5584
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
55✔
5585
      (*ppRes) = pBlock;
55✔
5586
      return code;
55✔
5587
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
524,777✔
5588
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,681✔
5589
      doStreamIntervalSaveCheckpoint(pOperator);
1,681✔
5590
      pInfo->reCkBlock = true;
1,681✔
5591
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,681✔
5592
      QUERY_CHECK_CODE(code, lino, _end);
1,681!
5593

5594
      continue;
1,681✔
5595
    } else {
5596
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
523,096!
5597
        qDebug("===stream===%s ignore recv block. type:%d", GET_TASKID(pTaskInfo), pBlock->info.type);
×
5598
        continue;
×
5599
      }
5600
    }
5601

5602
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
523,096✔
5603
      // set input version
5604
      pTaskInfo->version = pBlock->info.version;
383,390✔
5605
    }
5606

5607
    if (pInfo->scalarSupp.pExprInfo != NULL) {
523,096✔
5608
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5609
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5610
      QUERY_CHECK_CODE(code, lino, _end);
13!
5611
    }
5612

5613
    // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
5614
    // caller. Note that all the time window are not close till now.
5615
    // the pDataBlock are always the same one, no need to call this again
5616
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
523,096✔
5617
    QUERY_CHECK_CODE(code, lino, _end);
523,092!
5618
#ifdef BUILD_NO_CALL
5619
    if (pInfo->invertible) {
5620
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
5621
    }
5622
#endif
5623

5624
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
523,092✔
5625
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
523,094!
5626
      pOperator->status = OP_RES_TO_RETURN;
×
5627
      code = TSDB_CODE_SUCCESS;
×
5628
      break;
×
5629
    }
5630
    QUERY_CHECK_CODE(code, lino, _end);
523,094!
5631
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
523,094✔
5632
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
523,094✔
5633
  }
5634
  pOperator->status = OP_RES_TO_RETURN;
29,115✔
5635
  if (!pInfo->destHasPrimaryKey) {
29,115✔
5636
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
29,099✔
5637
  }
5638
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
29,114✔
5639
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5640
  QUERY_CHECK_CODE(code, lino, _end);
29,115!
5641

5642
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
29,115!
5643
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
16✔
5644
    QUERY_CHECK_CODE(code, lino, _end);
16!
5645
  }
5646

5647
  void*   pIte = NULL;
29,115✔
5648
  int32_t iter = 0;
29,115✔
5649
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
9,019,997✔
5650
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
8,990,825✔
5651
    if (!tmp) {
8,990,882!
5652
      code = terrno;
×
5653
      QUERY_CHECK_CODE(code, lino, _end);
×
5654
    }
5655
  }
5656
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
29,103✔
5657

5658
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
29,116✔
5659
  pInfo->pUpdated = NULL;
29,116✔
5660
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
29,116✔
5661
  QUERY_CHECK_CODE(code, lino, _end);
29,117!
5662

5663
  tSimpleHashCleanup(pInfo->pUpdatedMap);
29,117✔
5664
  pInfo->pUpdatedMap = NULL;
29,117✔
5665

5666
  code = buildIntervalResult(pOperator, ppRes);
29,117✔
5667
  QUERY_CHECK_CODE(code, lino, _end);
29,115!
5668

5669
  return code;
29,115✔
5670

5671
_end:
20✔
5672
  if (code != TSDB_CODE_SUCCESS) {
20!
5673
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
20!
5674
    pTaskInfo->code = code;
20✔
5675
    T_LONG_JMP(pTaskInfo->env, code);
20!
5676
  }
5677
  setStreamOperatorCompleted(pOperator);
×
5678
  (*ppRes) = NULL;
×
5679
  return code;
×
5680
}
5681

5682
int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
3,071✔
5683
                                               SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
5684
                                               SOperatorInfo** pOptrInfo) {
5685
  QRY_PARAM_CHECK(pOptrInfo);
3,071!
5686

5687
  int32_t code = TSDB_CODE_SUCCESS;
3,071✔
5688
  int32_t lino = 0;
3,071✔
5689
  int32_t numOfCols = 0;
3,071✔
5690

5691
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
3,071!
5692
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3,073!
5693
  if (pInfo == NULL || pOperator == NULL) {
3,075!
5694
    code = terrno;
×
5695
    QUERY_CHECK_CODE(code, lino, _error);
×
5696
  }
5697

5698
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3,075✔
5699

5700
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3,075✔
5701
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
3,074!
5702
  initBasicInfo(&pInfo->binfo, pResBlock);
3,074✔
5703

5704
  pInfo->interval = (SInterval){
3,074✔
5705
      .interval = pIntervalPhyNode->interval,
3,074✔
5706
      .sliding = pIntervalPhyNode->sliding,
3,074✔
5707
      .intervalUnit = pIntervalPhyNode->intervalUnit,
3,074✔
5708
      .slidingUnit = pIntervalPhyNode->slidingUnit,
3,074✔
5709
      .offset = pIntervalPhyNode->offset,
3,074✔
5710
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
3,074✔
5711
      .timeRange = pIntervalPhyNode->timeRange,
3,074✔
5712
  };
5713
  calcIntervalAutoOffset(&pInfo->interval);
3,074✔
5714

5715
  pInfo->twAggSup =
3,075✔
5716
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
3,075✔
5717
                           .calTrigger = pIntervalPhyNode->window.triggerType,
3,074✔
5718
                           .maxTs = INT64_MIN,
5719
                           .minTs = INT64_MAX,
5720
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
3,074✔
5721

5722
  pOperator->pTaskInfo = pTaskInfo;
3,075✔
5723
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,075✔
5724

5725
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
3,075✔
5726
  pInfo->ignoreExpiredDataSaved = false;
3,075✔
5727

5728
  SExprSupp* pSup = &pOperator->exprSupp;
3,075✔
5729
  pSup->hasWindowOrGroup = true;
3,075✔
5730

5731
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
3,075✔
5732
  QUERY_CHECK_CODE(code, lino, _error);
3,074!
5733

5734
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
3,074✔
5735
  initResultSizeInfo(&pOperator->resultInfo, 4096);
3,074✔
5736

5737
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
3,075!
5738
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
3,074!
5739
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
3,074✔
5740
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
3,074✔
5741

5742
  size_t     keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
3,074✔
5743
  SExprInfo* pExprInfo = NULL;
3,074✔
5744
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
3,074✔
5745
  QUERY_CHECK_CODE(code, lino, _error);
3,074!
5746
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str, pInfo->pState,
3,074✔
5747
                    &pTaskInfo->storageAPI.functionStore);
5748
  QUERY_CHECK_CODE(code, lino, _error);
3,075!
5749

5750
  if (pIntervalPhyNode->window.pExprs != NULL) {
3,075✔
5751
    int32_t    numOfScalar = 0;
1✔
5752
    SExprInfo* pScalarExprInfo = NULL;
1✔
5753

5754
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5755
    QUERY_CHECK_CODE(code, lino, _error);
1!
5756

5757
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
5758
    QUERY_CHECK_CODE(code, lino, _error);
1!
5759
  }
5760

5761
  pInfo->invertible = false;
3,075✔
5762
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
3,075✔
5763
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
3,074!
5764
  pInfo->delIndex = 0;
3,074✔
5765

5766
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
3,074✔
5767
  QUERY_CHECK_CODE(code, lino, _error);
3,075!
5768

5769
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
3,075✔
5770

5771
  pInfo->pPhyNode = NULL;  // create new child
3,075✔
5772
  pInfo->pPullDataMap = NULL;
3,075✔
5773
  pInfo->pFinalPullDataMap = NULL;
3,075✔
5774
  pInfo->pPullWins = NULL;  // SPullWindowInfo
3,075✔
5775
  pInfo->pullIndex = 0;
3,075✔
5776
  pInfo->pPullDataRes = NULL;
3,075✔
5777
  pInfo->numOfChild = 0;
3,075✔
5778
  pInfo->delKey.ts = INT64_MAX;
3,075✔
5779
  pInfo->delKey.groupId = 0;
3,075✔
5780
  pInfo->numOfDatapack = 0;
3,075✔
5781
  pInfo->pUpdated = NULL;
3,075✔
5782
  pInfo->pUpdatedMap = NULL;
3,075✔
5783
  int32_t funResSize = getMaxFunResSize(pSup, numOfCols);
3,075✔
5784

5785
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
3,075✔
5786
  pInfo->pState->pFileState = NULL;
3,075✔
5787

5788
  // used for backward compatibility of function's result info
5789
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
3,075✔
5790
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
3,075✔
5791
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
3,075✔
5792

5793
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
3,075✔
5794
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
3,075✔
5795
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
3,075✔
5796
      &pInfo->pState->pFileState);
3,075✔
5797
  QUERY_CHECK_CODE(code, lino, _error);
3,073!
5798

5799
  pInfo->pOperator = pOperator;
3,073✔
5800
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
3,073✔
5801
                  pInfo, pTaskInfo);
5802
  pOperator->fpSet =
5803
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
3,074✔
5804
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5805
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
3,075✔
5806

5807
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
3,075✔
5808
  QUERY_CHECK_CODE(code, lino, _error);
3,075!
5809

5810
  pInfo->recvGetAll = false;
3,075✔
5811

5812
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
3,075✔
5813
  QUERY_CHECK_CODE(code, lino, _error);
3,074!
5814

5815
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,074✔
5816
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
3,075✔
5817
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
3,075!
5818
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
3,075✔
5819

5820
  // for stream
5821
  void*   buff = NULL;
3,075✔
5822
  int32_t len = 0;
3,075✔
5823
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
3,075✔
5824
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
5825
  if (res == TSDB_CODE_SUCCESS) {
3,075✔
5826
    doStreamIntervalDecodeOpState(buff, len, pOperator);
3✔
5827
    taosMemoryFree(buff);
3!
5828
  }
5829

5830
  pInfo->basic.primaryPkIndex = -1;
3,075✔
5831
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
3,075✔
5832
  QUERY_CHECK_CODE(code, lino, _error);
3,075!
5833

5834
  code = appendDownstream(pOperator, &downstream, 1);
3,075✔
5835
  QUERY_CHECK_CODE(code, lino, _error);
3,075!
5836

5837
  *pOptrInfo = pOperator;
3,075✔
5838
  return TSDB_CODE_SUCCESS;
3,075✔
5839

5840
_error:
×
5841
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
5842
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5843
  pTaskInfo->code = code;
×
5844
  return code;
×
5845
}
5846

5847
static void doStreamMidIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pUpdatedMap) {
40✔
5848
  int32_t                      code = TSDB_CODE_SUCCESS;
40✔
5849
  int32_t                      lino = 0;
40✔
5850
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
40✔
5851
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
40✔
5852

5853
  SResultRowInfo*  pResultRowInfo = &(pInfo->binfo.resultRowInfo);
40✔
5854
  SExecTaskInfo*   pTaskInfo = pOperator->pTaskInfo;
40✔
5855
  SExprSupp*       pSup = &pOperator->exprSupp;
40✔
5856
  int32_t          numOfOutput = pSup->numOfExprs;
40✔
5857
  int32_t          step = 1;
40✔
5858
  SRowBuffPos*     pResPos = NULL;
40✔
5859
  SResultRow*      pResult = NULL;
40✔
5860
  int32_t          forwardRows = 1;
40✔
5861
  uint64_t         groupId = pSDataBlock->info.id.groupId;
40✔
5862
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
40✔
5863
  TSKEY*           tsCol = (int64_t*)pColDataInfo->pData;
40✔
5864

5865
  int32_t     startPos = 0;
40✔
5866
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
40✔
5867
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
40✔
5868

5869
  while (1) {
1,274✔
5870
    SWinKey key = {
1,314✔
5871
        .ts = nextWin.skey,
1,314✔
5872
        .groupId = groupId,
5873
    };
5874
    void*   chIds = taosHashGet(pInfo->pPullDataMap, &key, sizeof(SWinKey));
1,314✔
5875
    int32_t index = -1;
1,314✔
5876
    SArray* chArray = NULL;
1,314✔
5877
    int32_t chId = 0;
1,314✔
5878
    if (chIds) {
1,314✔
5879
      chArray = *(void**)chIds;
4✔
5880
      chId = getChildIndex(pSDataBlock);
4✔
5881
      index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
4✔
5882
    }
5883
    if (!(index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA)) {
1,314!
5884
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, startPos);
×
5885
      if (startPos < 0) {
×
5886
        break;
40✔
5887
      }
5888
      continue;
×
5889
    }
5890

5891
    if (!inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,314!
5892
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCol, startPos, nextWin.ekey, &nextWin);
×
5893
      if (startPos < 0) {
×
5894
        break;
×
5895
      }
5896
      continue;
×
5897
    }
5898

5899
    int32_t winCode = TSDB_CODE_SUCCESS;
1,314✔
5900
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
1,314✔
5901
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
5902
    QUERY_CHECK_CODE(code, lino, _end);
1,314!
5903

5904
    pResult = (SResultRow*)pResPos->pRowBuff;
1,314✔
5905

5906
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,314!
5907
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,314✔
5908
      QUERY_CHECK_CODE(code, lino, _end);
1,314!
5909
    }
5910

5911
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,314!
5912
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
×
5913
      QUERY_CHECK_CODE(code, lino, _end);
×
5914
    }
5915

5916
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
1,314✔
5917
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
1,314✔
5918
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
1,314✔
5919
    QUERY_CHECK_CODE(code, lino, _end);
1,314!
5920
    key.ts = nextWin.skey;
1,314✔
5921

5922
    if (pInfo->delKey.ts > key.ts) {
1,314✔
5923
      pInfo->delKey = key;
10✔
5924
    }
5925
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
1,314✔
5926
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
1,314!
5927
      qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64
×
5928
             ",maxKey %" PRId64,
5929
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5930
      code = blockDataUpdateTsWindow(pSDataBlock, 0);
×
5931
      QUERY_CHECK_CODE(code, lino, _end);
×
5932

5933
      // timestamp of the data is incorrect
5934
      if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
5935
        qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
5936
               pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5937
      }
5938
    }
5939
    startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, prevEndPos);
1,314✔
5940
    if (startPos < 0) {
1,314✔
5941
      break;
40✔
5942
    }
5943
  }
5944

5945
_end:
40✔
5946
  if (code != TSDB_CODE_SUCCESS) {
40!
5947
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5948
  }
5949
}
40✔
5950

5951
static int32_t addMidRetriveWindow(SArray* wins, SHashObj* pMidPullMap, int32_t numOfChild) {
12✔
5952
  int32_t code = TSDB_CODE_SUCCESS;
12✔
5953
  int32_t lino = 0;
12✔
5954
  int32_t size = taosArrayGetSize(wins);
12✔
5955
  for (int32_t i = 0; i < size; i++) {
18✔
5956
    SWinKey* winKey = taosArrayGet(wins, i);
6✔
5957
    void*    chIds = taosHashGet(pMidPullMap, winKey, sizeof(SWinKey));
6✔
5958
    if (!chIds) {
6!
5959
      code = addPullWindow(pMidPullMap, winKey, numOfChild);
6✔
5960
      qDebug("===stream===prepare mid operator retrive for delete %" PRId64 ", size:%d", winKey->ts, numOfChild);
6!
5961
      QUERY_CHECK_CODE(code, lino, _end);
6!
5962
    }
5963
  }
5964
_end:
12✔
5965
  if (code != TSDB_CODE_SUCCESS) {
12!
5966
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5967
  }
5968
  return code;
12✔
5969
}
5970

5971
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
102✔
5972
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
102✔
5973
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
102✔
5974
  uint16_t                     opType = pOperator->operatorType;
102✔
5975

5976
  if (pInfo->recvPullover) {
102✔
5977
    pInfo->recvPullover = false;
6✔
5978
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5979
    return pInfo->pMidPulloverRes;
6✔
5980
  }
5981

5982
  qDebug("===stream=== build mid interval result");
96!
5983
  doBuildDeleteResult(pTaskInfo, pInfo->pMidPullDatas, &pInfo->midDelIndex, pInfo->pDelRes);
96✔
5984
  if (pInfo->pDelRes->info.rows != 0) {
96!
5985
    // process the rest of the data
5986
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
×
5987
    return pInfo->pDelRes;
×
5988
  }
5989

5990
  if (pInfo->recvRetrive) {
96✔
5991
    pInfo->recvRetrive = false;
12✔
5992
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5993
    return pInfo->pMidRetriveRes;
12✔
5994
  }
5995

5996
  return NULL;
84✔
5997
}
5998

5999
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
102✔
6000
  int32_t                      code = TSDB_CODE_SUCCESS;
102✔
6001
  int32_t                      lino = 0;
102✔
6002
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
102✔
6003
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
102✔
6004
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
102✔
6005
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
102✔
6006
  SExprSupp*                   pSup = &pOperator->exprSupp;
102✔
6007

6008
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
102!
6009

6010
  if (pOperator->status == OP_EXEC_DONE) {
102!
6011
    (*ppRes) = NULL;
×
6012
    return code;
×
6013
  } else if (pOperator->status == OP_RES_TO_RETURN) {
102✔
6014
    SSDataBlock* resBlock = NULL;
36✔
6015
    code = buildIntervalResult(pOperator, &resBlock);
36✔
6016
    QUERY_CHECK_CODE(code, lino, _end);
36!
6017
    if (resBlock != NULL) {
36✔
6018
      (*ppRes) = resBlock;
13✔
6019
      return code;
36✔
6020
    }
6021

6022
    setOperatorCompleted(pOperator);
23✔
6023
    clearFunctionContext(&pOperator->exprSupp);
23✔
6024
    clearStreamIntervalOperator(pInfo);
23✔
6025
    qDebug("stask:%s  ===stream===%s clear", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType));
23!
6026
    (*ppRes) = NULL;
23✔
6027
    return code;
23✔
6028
  } else {
6029
    SSDataBlock* resBlock = NULL;
66✔
6030
    code = buildIntervalResult(pOperator, &resBlock);
66✔
6031
    QUERY_CHECK_CODE(code, lino, _end);
66!
6032
    if (resBlock != NULL) {
66!
6033
      (*ppRes) = resBlock;
×
6034
      return code;
2✔
6035
    }
6036

6037
    resBlock = buildMidIntervalResult(pOperator);
66✔
6038
    if (resBlock != NULL) {
66✔
6039
      (*ppRes) = resBlock;
2✔
6040
      return code;
2✔
6041
    }
6042

6043
    if (pInfo->clearState) {
64✔
6044
      pInfo->clearState = false;
18✔
6045
      clearFunctionContext(&pOperator->exprSupp);
18✔
6046
      clearStreamIntervalOperator(pInfo);
18✔
6047
    }
6048
  }
6049

6050
  if (!pInfo->pUpdated) {
64✔
6051
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
61✔
6052
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
61!
6053
  }
6054
  if (!pInfo->pUpdatedMap) {
64✔
6055
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
61✔
6056
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
61✔
6057
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
61!
6058
  }
6059

6060
  while (1) {
56✔
6061
    if (isTaskKilled(pTaskInfo)) {
120!
6062
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
6063
      (*ppRes) = NULL;
×
6064
      return code;
3✔
6065
    }
6066

6067
    SSDataBlock* pBlock = NULL;
120✔
6068
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
120✔
6069
    QUERY_CHECK_CODE(code, lino, _end);
120!
6070

6071
    if (pBlock == NULL) {
120✔
6072
      pOperator->status = OP_RES_TO_RETURN;
43✔
6073
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
43!
6074
             pInfo->numOfDatapack);
6075
      pInfo->numOfDatapack = 0;
43✔
6076
      break;
43✔
6077
    }
6078
    pInfo->numOfDatapack++;
77✔
6079
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
77✔
6080
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
77✔
6081

6082
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
77✔
6083
      pInfo->binfo.pRes->info.type = pBlock->info.type;
8✔
6084
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
69!
6085
               pBlock->info.type == STREAM_CLEAR) {
67✔
6086
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
3✔
6087
      if (!delWins) {
3!
6088
        code = terrno;
×
6089
        QUERY_CHECK_CODE(code, lino, _end);
×
6090
      }
6091
      code =
6092
          doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, pInfo->pFinalPullDataMap);
3✔
6093
      QUERY_CHECK_CODE(code, lino, _end);
3!
6094

6095
      removeResults(delWins, pInfo->pUpdatedMap);
3✔
6096
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
3✔
6097
      if (!tmp && taosArrayGetSize(delWins) > 0) {
3!
6098
        code = TSDB_CODE_OUT_OF_MEMORY;
×
6099
        QUERY_CHECK_CODE(code, lino, _end);
×
6100
      }
6101
      taosArrayDestroy(delWins);
3✔
6102

6103
      doBuildDeleteResult(pTaskInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
3✔
6104
      if (pInfo->pDelRes->info.rows != 0) {
3!
6105
        // process the rest of the data
6106
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
3✔
6107
        if (pBlock->info.type == STREAM_CLEAR) {
3✔
6108
          pInfo->pDelRes->info.type = STREAM_CLEAR;
1✔
6109
        } else {
6110
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
2✔
6111
        }
6112
        (*ppRes) = pInfo->pDelRes;
3✔
6113
        return code;
3✔
6114
      }
6115
      continue;
16✔
6116
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
66!
6117
      (*ppRes) = pBlock;
×
6118
      return code;
×
6119
    } else if (pBlock->info.type == STREAM_PULL_OVER) {
66✔
6120
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
12✔
6121
                             pInfo->numOfChild, pOperator, &pInfo->recvPullover);
6122
      QUERY_CHECK_CODE(code, lino, _end);
12!
6123

6124
      if (pInfo->recvPullover) {
12✔
6125
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
6126
        QUERY_CHECK_CODE(code, lino, _end);
6!
6127

6128
        pInfo->clearState = true;
6✔
6129
        break;
6✔
6130
      }
6131
      continue;
6✔
6132
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
54✔
6133
      pAPI->stateStore.streamStateCommit(pInfo->pState);
10✔
6134
      doStreamIntervalSaveCheckpoint(pOperator);
10✔
6135
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
10✔
6136
      QUERY_CHECK_CODE(code, lino, _end);
10!
6137

6138
      continue;
10✔
6139
    } else if (pBlock->info.type == STREAM_MID_RETRIEVE) {
44✔
6140
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
12✔
6141
      if (!delWins) {
12!
6142
        code = terrno;
×
6143
        QUERY_CHECK_CODE(code, lino, _end);
×
6144
      }
6145
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, NULL);
12✔
6146
      QUERY_CHECK_CODE(code, lino, _end);
12!
6147

6148
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
6149
      QUERY_CHECK_CODE(code, lino, _end);
12!
6150

6151
      taosArrayDestroy(delWins);
12✔
6152
      pInfo->recvRetrive = true;
12✔
6153
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
12✔
6154
      QUERY_CHECK_CODE(code, lino, _end);
12!
6155

6156
      pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
12✔
6157
      pInfo->clearState = true;
12✔
6158
      break;
12✔
6159
    } else {
6160
      if (pBlock->info.type != STREAM_INVALID) {
32!
6161
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
6162
        QUERY_CHECK_CODE(code, lino, _end);
×
6163
      }
6164
    }
6165

6166
    if (pInfo->scalarSupp.pExprInfo != NULL) {
40!
6167
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
6168
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
6169
      QUERY_CHECK_CODE(code, lino, _end);
×
6170
    }
6171
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
40✔
6172
    QUERY_CHECK_CODE(code, lino, _end);
40!
6173
    doStreamMidIntervalAggImpl(pOperator, pBlock, pInfo->pUpdatedMap);
40✔
6174
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
40✔
6175
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
40✔
6176
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
40✔
6177
  }
6178

6179
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
61✔
6180
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
61✔
6181

6182
  void*   pIte = NULL;
61✔
6183
  int32_t iter = 0;
61✔
6184
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,175✔
6185
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,114✔
6186
    if (!tmp) {
1,114!
6187
      code = terrno;
×
6188
      QUERY_CHECK_CODE(code, lino, _end);
×
6189
    }
6190
  }
6191

6192
  tSimpleHashCleanup(pInfo->pUpdatedMap);
61✔
6193
  pInfo->pUpdatedMap = NULL;
61✔
6194
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
61✔
6195

6196
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
61✔
6197
  pInfo->pUpdated = NULL;
61✔
6198
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
61✔
6199
  QUERY_CHECK_CODE(code, lino, _end);
61!
6200

6201
  SSDataBlock* resBlock = NULL;
61✔
6202
  code = buildIntervalResult(pOperator, &resBlock);
61✔
6203
  QUERY_CHECK_CODE(code, lino, _end);
61!
6204
  if (resBlock != NULL) {
61✔
6205
    (*ppRes) = resBlock;
25✔
6206
    return code;
25✔
6207
  }
6208

6209
  resBlock = buildMidIntervalResult(pOperator);
36✔
6210
  if (resBlock != NULL) {
36✔
6211
    (*ppRes) = resBlock;
16✔
6212
    return code;
16✔
6213
  }
6214

6215
  if (pInfo->clearState) {
20!
6216
    pInfo->clearState = false;
×
6217
    clearFunctionContext(&pOperator->exprSupp);
×
6218
    clearStreamIntervalOperator(pInfo);
×
6219
  }
6220

6221
_end:
20✔
6222
  if (code != TSDB_CODE_SUCCESS) {
20!
6223
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
6224
    pTaskInfo->code = code;
×
6225
    T_LONG_JMP(pTaskInfo->env, code);
×
6226
  }
6227
  (*ppRes) = NULL;
20✔
6228
  return code;
20✔
6229
}
6230

6231
static SSDataBlock* doStreamMidIntervalAgg(SOperatorInfo* pOperator) {
×
6232
  SSDataBlock* pRes = NULL;
×
6233
  int32_t      code = doStreamMidIntervalAggNext(pOperator, &pRes);
×
6234
  return pRes;
×
6235
}
6236

6237
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
37,356✔
6238
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
37,356✔
6239
         getStreamOpName(pOperator->operatorType), pOperator->status);
6240
  setOperatorCompleted(pOperator);
37,356✔
6241
}
37,356✔
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