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

taosdata / TDengine / #3858

17 Apr 2025 01:40PM UTC coverage: 62.968% (+0.5%) from 62.513%
#3858

push

travis-ci

web-flow
docs(opc): add perssit data support (#30783)

156194 of 316378 branches covered (49.37%)

Branch coverage included in aggregate %.

242021 of 316027 relevant lines covered (76.58%)

19473613.85 hits per line

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

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

54
  if (num <= 0) return -1;
1,294✔
55
  if (order == TSDB_ORDER_DESC) {
1,072!
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,183✔
59
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
346✔
60
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
216✔
61

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

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

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

114
  if (pData->window.skey > pos->window.ekey) {
44✔
115
    return 1;
36✔
116
  } else if (pData->window.ekey < pos->window.skey) {
8✔
117
    return -1;
2✔
118
  }
119
  return 0;
6✔
120
}
121

122
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
222✔
123
  int32_t size = taosArrayGetSize(pPullWins);
222✔
124
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
222✔
125
  if (index == -1) {
222✔
126
    index = 0;
173✔
127
  } else {
128
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
49✔
129
    if (code == 0) {
49✔
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) {
46!
137
      index++;
46✔
138
    }
139
  }
140
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
219!
141
    return terrno;
×
142
  }
143
  return TSDB_CODE_SUCCESS;
219✔
144
}
145

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

155
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
9,683,066✔
156
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
9,683,066!
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,683,003✔
161
}
162

163
static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
308✔
164
  SWinKey key = {.ts = ts, .groupId = groupId};
308✔
165
  return saveWinResult(&key, pPos, pUpdatedMap);
308✔
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++) {
455✔
171
    SWinKey* pW = taosArrayGet(pWins, i);
249✔
172
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
248✔
173
    if (tmp) {
248!
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
}
206✔
181

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

187
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
26,954✔
188
  taosArraySort(pDelWins, winKeyCmprImpl);
26,954✔
189
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
26,951✔
190
  int32_t delSize = taosArrayGetSize(pDelWins);
26,952✔
191
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
26,952✔
192
    return;
26,603✔
193
  }
194
  void*   pIte = NULL;
351✔
195
  int32_t iter = 0;
351✔
196
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,144✔
197
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
793✔
198
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
793✔
199
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
793✔
200
      taosArrayRemove(pDelWins, index);
597✔
201
      delSize = taosArrayGetSize(pDelWins);
597✔
202
    }
203
  }
204
}
205

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

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

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

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

222
int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,403✔
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,001✔
248
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
249
  int32_t                      code = TSDB_CODE_SUCCESS;
2,001✔
250
  int32_t                      lino = 0;
2,001✔
251
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,001✔
252
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2,001✔
253
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,001✔
254
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
2,001✔
255
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,001✔
256
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
2,001✔
257
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
2,001✔
258
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
2,003✔
259
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
2,003✔
260
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
2,002✔
261
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,002✔
262
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
2,002✔
263
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
4,318✔
264
    SResultRowInfo dumyInfo = {0};
2,318✔
265
    dumyInfo.cur.pageId = -1;
2,318✔
266

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

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

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

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

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

365
    void*       chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey));
5,112✔
366
    STimeWindow win = {
10,224✔
367
        .skey = pWinKey->ts,
5,112✔
368
        .ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1,
5,112✔
369
    };
370
    if (isCloseWindow(&win, pTwSup)) {
5,112✔
371
      if (chIds && pPullDataMap) {
2,138!
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) {
2,137✔
380
        qDebug("===stream===close window %" PRId64, pWinKey->ts);
581✔
381
      }
382

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

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

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

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

410
void doBuildDeleteResultImpl(SStateStore* pAPI, SStreamState* pState, SArray* pWins, int32_t* index,
142,853✔
411
                             SSDataBlock* pBlock) {
412
  int32_t code = TSDB_CODE_SUCCESS;
142,853✔
413
  int32_t lino = 0;
142,853✔
414
  blockDataCleanup(pBlock);
142,853✔
415
  int32_t size = taosArrayGetSize(pWins);
142,855✔
416
  if (*index == size) {
142,854✔
417
    *index = 0;
142,226✔
418
    taosArrayClear(pWins);
142,226✔
419
    goto _end;
142,225✔
420
  }
421
  code = blockDataEnsureCapacity(pBlock, size - *index);
628✔
422
  QUERY_CHECK_CODE(code, lino, _end);
627!
423

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

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

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

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

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

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

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

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

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

499
  // it should be empty.
500
  void* pIte = NULL;
3,920✔
501
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
3,920!
502
    taosArrayDestroy(*(void**)pIte);
×
503
  }
504
  taosHashCleanup(pInfo->pPullDataMap);
3,920✔
505
  taosHashCleanup(pInfo->pFinalPullDataMap);
3,920✔
506
  taosArrayDestroy(pInfo->pPullWins);
3,920✔
507
  blockDataDestroy(pInfo->pPullDataRes);
3,920✔
508
  taosArrayDestroy(pInfo->pDelWins);
3,920✔
509
  blockDataDestroy(pInfo->pDelRes);
3,920✔
510
  blockDataDestroy(pInfo->pMidRetriveRes);
3,920✔
511
  blockDataDestroy(pInfo->pMidPulloverRes);
3,920✔
512
  if (pInfo->pUpdatedMap != NULL) {
3,920!
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,920!
520
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
3,920✔
521
  }
522
  taosArrayDestroy(pInfo->pMidPullDatas);
3,920✔
523

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

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

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

537
  taosMemoryFreeClear(param);
3,920!
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,337✔
552
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
1,337✔
553

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

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

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

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

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

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

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

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

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

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

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

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

627
      pEntryInfo->numOfRes = 1;
49✔
628
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
172!
629
      code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
170✔
630
      QUERY_CHECK_CODE(code, lino, _end);
170!
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:
43✔
641
  if (code != TSDB_CODE_SUCCESS) {
45✔
642
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
643
  }
644
  return code;
45✔
645
}
646

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

651
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
9,688,493✔
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,688,493✔
655
  int32_t lino = 0;
9,688,493✔
656
  SWinKey key = {.ts = win->skey, .groupId = groupId};
9,688,493✔
657
  char*   value = NULL;
9,688,493✔
658
  int32_t size = pAggSup->resultRowSize;
9,688,493✔
659

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

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

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

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

678
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
30,383,574✔
679
                           SStateStore* pStore) {
680
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
30,383,574✔
681
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
24✔
682
    if (!hasIntervalWindow(pState, &key, pStore)) {
24✔
683
      return true;
14✔
684
    }
685
    return false;
10✔
686
  }
687
  return false;
30,383,550✔
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) {
228✔
699
  int32_t code = TSDB_CODE_SUCCESS;
228✔
700
  int32_t lino = 0;
228✔
701
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
228✔
702
  QUERY_CHECK_NULL(childIds, code, lino, _end, terrno);
228!
703
  for (int32_t i = 0; i < size; i++) {
984✔
704
    void* tmp = taosArrayPush(childIds, &i);
756✔
705
    if (!tmp) {
756!
706
      code = terrno;
×
707
      QUERY_CHECK_CODE(code, lino, _end);
×
708
    }
709
  }
710
  code = taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
228✔
711
  QUERY_CHECK_CODE(code, lino, _end);
228!
712
_end:
228✔
713
  if (code != TSDB_CODE_SUCCESS) {
228!
714
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
715
  }
716
  return code;
228✔
717
}
718

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

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

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

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

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

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

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

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

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

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

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

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

824
            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
228✔
825
            if (pFinalCh) {
228✔
826
              int32_t tmpRes = taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
28✔
827
              qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
28!
828
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
28✔
829
              STimeWindow     nextWin = getFinalTimeWindow(winRes.ts, pInterval);
28✔
830
              SPullWindowInfo pull = {.window = nextWin,
28✔
831
                                      .groupId = winRes.groupId,
28✔
832
                                      .calWin.skey = nextWin.skey,
28✔
833
                                      .calWin.ekey = nextWin.skey};
28✔
834
              // add pull data request
835
              qDebug("===stream===prepare final retrive for delete window:%" PRId64 ",groupId:%" PRId64 ", size:%d",
28!
836
                     winRes.ts, winRes.groupId, numOfCh);
837
              if (IS_MID_INTERVAL_OP(pOperator)) {
28!
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) {
28!
846
                void* tmp = taosArrayPush(pInfo->pDelWins, &winRes);
28✔
847
                if (!tmp) {
28!
848
                  code = terrno;
×
849
                  QUERY_CHECK_CODE(code, lino, _end);
×
850
                }
851

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

855
                if (pInfo->destHasPrimaryKey) {
28!
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);
28!
860
              }
861
            }
862
          }
863
        }
864
      }
865
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision, NULL);
756✔
866
    }
867
  }
868
  if (pBeOver) {
516✔
869
    *pBeOver = res;
12✔
870
  }
871

872
_end:
504✔
873
  if (code != TSDB_CODE_SUCCESS) {
516!
874
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
875
  }
876
  return code;
516✔
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++) {
397✔
884
    SWinKey*    winKey = taosArrayGet(wins, i);
193✔
885
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
193✔
886
    void*       chIds = taosHashGet(pInfo->pPullDataMap, winKey, sizeof(SWinKey));
193✔
887
    if (!chIds) {
193!
888
      SPullWindowInfo pull = {
193✔
889
          .window = nextWin, .groupId = winKey->groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
193✔
890
      // add pull data request
891
      if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
193!
892
        code = addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
193✔
893
        QUERY_CHECK_CODE(code, lino, _end);
193!
894

895
        if (pInfo->destHasPrimaryKey) {
193!
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);
193✔
900
      }
901
    } else {
902
      SArray* chArray = *(void**)chIds;
×
903
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
×
904
      qDebug("===stream===check final retrive %" PRId64 ",chid:%d", winKey->ts, index);
×
905
      if (index == -1) {
×
906
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
×
907
        code = taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
×
908
        QUERY_CHECK_CODE(code, lino, _end);
×
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,112✔
921
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
22,291✔
922
    pSup->pCtx[i].saveHandle.currentPage = -1;
20,179✔
923
  }
924
}
2,112✔
925

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

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

941
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
104,429✔
942

943
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
8,447,257✔
944
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
8,430,453✔
945
    SResultRow*  pRow = NULL;
8,430,454✔
946
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
8,430,454✔
947
    QUERY_CHECK_CODE(code, lino, _end);
8,430,456!
948
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
8,430,456✔
949
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
8,430,456✔
950
    // no results, continue to check the next one
951
    if (pRow->numOfRows == 0) {
8,430,375!
952
      pGroupResInfo->index += 1;
×
953
      continue;
×
954
    }
955
    if (pBlock->info.id.groupId == 0) {
8,430,375✔
956
      pBlock->info.id.groupId = groupId;
577,280✔
957
      void*   tbname = NULL;
577,280✔
958
      int32_t winCode = TSDB_CODE_SUCCESS;
577,280✔
959
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
577,280✔
960
                                                    false, &winCode);
961
      QUERY_CHECK_CODE(code, lino, _end);
577,279!
962
      if (winCode != TSDB_CODE_SUCCESS) {
577,279✔
963
        pBlock->info.parTbName[0] = 0;
571,482✔
964
      } else {
965
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
5,797✔
966
      }
967
      pAPI->stateStore.streamStateFreeVal(tbname);
577,279✔
968
    } else {
969
      // current value belongs to different group, it can't be packed into one datablock
970
      if (pBlock->info.id.groupId != groupId) {
7,853,095✔
971
        break;
87,573✔
972
      }
973
    }
974

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

980
    for (int32_t j = 0; j < numOfExprs; ++j) {
67,885,868✔
981
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
59,543,040✔
982

983
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
59,543,040✔
984

985
      if (pCtx[j].fpSet.finalize) {
59,543,061✔
986
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
39,523,652✔
987
        if (TAOS_FAILED(tmpRes)) {
39,523,657!
988
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
989
          QUERY_CHECK_CODE(code, lino, _end);
×
990
        }
991
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
20,019,409✔
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);
19,950,645✔
997
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
19,950,642✔
998
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
39,901,321✔
999
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
19,950,642✔
1000
          QUERY_CHECK_CODE(code, lino, _end);
19,950,679!
1001
        }
1002
      }
1003
    }
1004

1005
    if (pSessionKeys) {
8,342,828!
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;
8,342,828✔
1014
  }
1015

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

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

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

1032
  blockDataCleanup(pBlock);
142,651✔
1033
  taosArrayClear(pSessionKeys);
142,651✔
1034
  if (!hasRemainResults(pGroupResInfo)) {
142,652✔
1035
    return;
38,225✔
1036
  }
1037

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

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

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

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

1072
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,037,829✔
1073
  tsCols = (int64_t*)pColDataInfo->pData;
1,037,832✔
1074

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

1082
  if (pSDataBlock->info.window.skey != tsCols[0] || pSDataBlock->info.window.ekey != tsCols[endRowId]) {
1,037,830!
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;
1,037,832✔
1096
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
1,037,832✔
1097
  STimeWindow nextWin = {0};
1,037,833✔
1098
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,037,833✔
1099
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,337✔
1100
  } else {
1101
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
1,035,496✔
1102
  }
1103
  while (1) {
8,649,889✔
1104
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
9,687,723✔
1105
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
9,688,433!
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,689,661!
1112
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
1,226✔
1113
                          nextWin.ekey, pPkVal, pkLen)) ||
9,688,327✔
1114
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
9,688,412✔
1115
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
38✔
1116
      if (startPos < 0) {
42✔
1117
        break;
1,037,831✔
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;
57✔
1122
    }
1123

1124
    if (IS_FINAL_INTERVAL_OP(pOperator) && pInfo->numOfChild > 0) {
9,688,312!
1125
      bool    ignore = true;
242,334✔
1126
      SWinKey winRes = {
242,334✔
1127
          .ts = nextWin.skey,
242,334✔
1128
          .groupId = groupId,
1129
      };
1130
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
242,334✔
1131
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore) && isClosed &&
242,334!
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;
242,333✔
1147
        SArray* chArray = NULL;
242,333✔
1148
        int32_t chId = 0;
242,333✔
1149
        if (chIds) {
242,333✔
1150
          chArray = *(void**)chIds;
352✔
1151
          chId = getChildIndex(pSDataBlock);
352✔
1152
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
352✔
1153
        }
1154
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
242,333✔
1155
          ignore = false;
242,197✔
1156
        }
1157
      }
1158

1159
      if (ignore) {
242,334✔
1160
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
137✔
1161
        if (startPos < 0) {
137✔
1162
          break;
99✔
1163
        }
1164
        continue;
38✔
1165
      }
1166
    }
1167

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

1173
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator) &&
9,687,563✔
1174
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
8,783,562!
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,687,563✔
1182

1183
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,687,563✔
1184
      forwardRows = 1;
242,197✔
1185
    } else {
1186
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
9,445,366✔
1187
                                             NULL, TSDB_ORDER_ASC);
1188
    }
1189

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

1195
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
9,689,523!
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,689,523!
1201
      code = saveWinResult(&key, pResPos, pUpdatedMap);
9,679,166✔
1202
      QUERY_CHECK_CODE(code, lino, _end);
9,678,985!
1203
    }
1204

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

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

1217
    if (pInfo->delKey.ts > key.ts) {
9,689,540✔
1218
      pInfo->delKey = key;
2,030✔
1219
    }
1220
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
9,689,540✔
1221
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
9,689,540✔
1222
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
242,197✔
1223
    } else {
1224
      startPos =
1225
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
9,447,343✔
1226
    }
1227
    if (startPos < 0) {
9,687,541✔
1228
      break;
1,037,709✔
1229
    }
1230
  }
1231
_end:
1,037,831✔
1232
  if (code != TSDB_CODE_SUCCESS) {
1,037,831!
1233
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1234
  }
1235
  return code;
1,037,830✔
1236
}
1237

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

1244
  if (pWin1->groupId > pWin2->groupId) {
129,685,793✔
1245
    return 1;
21,945,015✔
1246
  } else if (pWin1->groupId < pWin2->groupId) {
107,740,778✔
1247
    return -1;
20,640,302✔
1248
  }
1249

1250
  if (pWin1->ts > pWin2->ts) {
87,100,476✔
1251
    return 1;
43,866,434✔
1252
  } else if (pWin1->ts < pWin2->ts) {
43,234,042!
1253
    return -1;
43,235,316✔
1254
  }
1255

1256
  return 0;
×
1257
}
1258

1259
static void resetUnCloseWinInfo(SSHashObj* winMap) {
266✔
1260
  void*   pIte = NULL;
266✔
1261
  int32_t iter = 0;
266✔
1262
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
593✔
1263
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
327✔
1264
    pPos->beUsed = true;
327✔
1265
  }
1266
}
266✔
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
  tlen += taosEncodeFixedI32(buf, key->numInGroup);
34✔
1273
  return tlen;
34✔
1274
}
1275

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

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

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

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

1303
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
×
1304
  buf = taosDecodeFixedI64(buf, &pWin->skey);
×
1305
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
×
1306
  return buf;
×
1307
}
1308

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

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

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

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

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

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

1364
  void* pData = (buf == NULL) ? NULL : *buf;
84✔
1365

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

1378
  // 2.twAggSup
1379
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
84✔
1380

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

1398
  // 4.pPullWins
1399
  tlen += encodeSPullWindowInfoArray(buf, pInfo->pPullWins);
84✔
1400

1401
  // 5.dataVersion
1402
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
84✔
1403

1404
  // 6.basicInfo
1405
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
84✔
1406

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

1415
  return tlen;
84✔
1416
}
1417

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

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

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

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

1455
  // 2.twAggSup
1456
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
9✔
1457

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

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

1485
  // 4.pPullWins
1486
  code = decodeSPullWindowInfoArray(buf, pInfo->pPullWins, &buf);
9✔
1487
  QUERY_CHECK_CODE(code, lino, _end);
9!
1488

1489
  // 5.dataVersion
1490
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
9!
1491

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

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

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

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

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

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

1554
  // check if query task is closed or not
1555
  if (isTaskKilled(pTaskInfo)) {
140,197✔
1556
    (*ppRes) = NULL;
3✔
1557
    return code;
3✔
1558
  }
1559

1560
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
267,575✔
1561
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
127,379!
1562
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
140,196✔
1563
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
4,042✔
1564
    if (pInfo->pPullDataRes->info.rows != 0) {
4,042✔
1565
      // process the rest of the data
1566
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
156✔
1567
      (*ppRes) = pInfo->pPullDataRes;
156✔
1568
      return code;
156✔
1569
    }
1570
  }
1571

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

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

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

1605
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
35,534✔
1606
  QUERY_CHECK_CODE(code, lino, _end);
35,529!
1607

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

1616
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
18,912✔
1617
  int32_t code = TSDB_CODE_SUCCESS;
18,912✔
1618
  int32_t lino = 0;
18,912✔
1619
  void*   pIte = NULL;
18,912✔
1620
  int32_t iter = 0;
18,912✔
1621
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
509,954✔
1622
    void* tmp = taosArrayPush(pUpdated, pIte);
491,042✔
1623
    if (!tmp) {
491,042!
1624
      code = terrno;
×
1625
      QUERY_CHECK_CODE(code, lino, _end);
×
1626
    }
1627
  }
1628
  taosArraySort(pUpdated, compar);
18,912✔
1629
  tSimpleHashCleanup(*ppWinUpdated);
18,909✔
1630
  *ppWinUpdated = NULL;
18,913✔
1631

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

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

1646
  SOperatorInfo* downstream = pOperator->pDownstream[0];
13,811✔
1647
  SExprSupp*     pSup = &pOperator->exprSupp;
13,811✔
1648

1649
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
13,811✔
1650

1651
  if (pOperator->status == OP_EXEC_DONE) {
13,814!
1652
    (*ppRes) = NULL;
×
1653
    return code;
×
1654
  } else if (pOperator->status == OP_RES_TO_RETURN) {
13,814✔
1655
    SSDataBlock* resBlock = NULL;
4,629✔
1656
    code = buildIntervalResult(pOperator, &resBlock);
4,629✔
1657
    QUERY_CHECK_CODE(code, lino, _end);
4,628!
1658
    if (resBlock != NULL) {
4,628✔
1659
      (*ppRes) = resBlock;
1,622✔
1660
      return code;
4,628✔
1661
    }
1662

1663
    if (pInfo->recvGetAll) {
3,006✔
1664
      pInfo->recvGetAll = false;
83✔
1665
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
83✔
1666
    }
1667

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

1675
    setStreamOperatorCompleted(pOperator);
3,006✔
1676
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
3,006✔
1677
      clearFunctionContext(&pOperator->exprSupp);
1,613✔
1678
      // semi interval operator clear disk buffer
1679
      clearStreamIntervalOperator(pInfo);
1,613✔
1680
      qDebug("===stream===clear semi operator");
1,613✔
1681
    }
1682
    (*ppRes) = NULL;
3,006✔
1683
    return code;
3,006✔
1684
  } else {
1685
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
9,185✔
1686
      SSDataBlock* resBlock = NULL;
5,961✔
1687
      code = buildIntervalResult(pOperator, &resBlock);
5,961✔
1688
      QUERY_CHECK_CODE(code, lino, _end);
5,959!
1689
      if (resBlock != NULL) {
5,959!
1690
        (*ppRes) = resBlock;
×
1691
        return code;
×
1692
      }
1693

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

1703
  if (!pInfo->pUpdated) {
9,183✔
1704
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
6,106✔
1705
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
6,106!
1706
  }
1707
  if (!pInfo->pUpdatedMap) {
9,183✔
1708
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
6,106✔
1709
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
6,106✔
1710
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
6,103!
1711
  }
1712

1713
  while (1) {
18,604✔
1714
    if (isTaskKilled(pTaskInfo)) {
27,784!
1715
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
1716
      (*ppRes) = NULL;
×
1717
      return code;
3,076✔
1718
    }
1719

1720
    SSDataBlock* pBlock = NULL;
27,778✔
1721
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
27,778✔
1722
    QUERY_CHECK_CODE(code, lino, _end);
27,784!
1723

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

1732
    pInfo->numOfDatapack++;
22,188✔
1733
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
22,188✔
1734
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
22,193✔
1735

1736
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
22,191✔
1737
      pInfo->binfo.pRes->info.type = pBlock->info.type;
15,819✔
1738
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
6,372✔
1739
               pBlock->info.type == STREAM_CLEAR) {
6,140✔
1740
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
406✔
1741
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
408!
1742
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
408✔
1743
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
408✔
1744
      QUERY_CHECK_CODE(code, lino, _end);
408!
1745

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

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

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

1782
      break;
×
1783
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
5,966!
1784
      pInfo->recvGetAll = true;
83✔
1785
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
83✔
1786
      QUERY_CHECK_CODE(code, lino, _end);
83!
1787
      continue;
83✔
1788
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
5,883✔
1789
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
510!
1790
        pInfo->recvRetrive = true;
510✔
1791
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
510✔
1792
        QUERY_CHECK_CODE(code, lino, _end);
510!
1793

1794
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
510✔
1795
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
510✔
1796
        QUERY_CHECK_CODE(code, lino, _end);
509!
1797
        break;
509✔
1798
      }
1799
      continue;
×
1800
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
5,373!
1801
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
504✔
1802
                             pInfo->numOfChild, pOperator, NULL);
1803
      QUERY_CHECK_CODE(code, lino, _end);
504!
1804
      continue;
504✔
1805
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
4,869✔
1806
      (*ppRes) = pBlock;
2,873✔
1807
      return code;
2,873✔
1808
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,996✔
1809
      pAPI->stateStore.streamStateCommit(pInfo->pState);
723✔
1810
      doStreamIntervalSaveCheckpoint(pOperator);
723✔
1811
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
723✔
1812
      QUERY_CHECK_CODE(code, lino, _end);
723!
1813

1814
      continue;
723✔
1815
    } else if (IS_FINAL_INTERVAL_OP(pOperator) && pBlock->info.type == STREAM_MID_RETRIEVE) {
1,273✔
1816
      continue;
510✔
1817
    } else {
1818
      if (pBlock->info.type != STREAM_INVALID) {
763!
1819
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1820
        QUERY_CHECK_CODE(code, lino, _end);
×
1821
      }
1822
    }
1823

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

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

1843
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
6,105✔
1844
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,785✔
1845
  }
1846
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
6,105✔
1847
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,787✔
1848
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1849
    QUERY_CHECK_CODE(code, lino, _end);
1,787!
1850

1851
    if (pInfo->destHasPrimaryKey) {
1,787✔
1852
      code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
2✔
1853
      QUERY_CHECK_CODE(code, lino, _end);
2!
1854
    }
1855
  }
1856
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
6,105✔
1857

1858
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
6,105✔
1859
  QUERY_CHECK_CODE(code, lino, _end);
6,106!
1860

1861
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
6,106✔
1862
  pInfo->pUpdated = NULL;
6,107✔
1863
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
6,107✔
1864
  QUERY_CHECK_CODE(code, lino, _end);
6,106!
1865

1866
  SSDataBlock* resBlock = NULL;
6,106✔
1867
  code = buildIntervalResult(pOperator, &resBlock);
6,106✔
1868
  QUERY_CHECK_CODE(code, lino, _end);
6,107!
1869
  if (resBlock != NULL) {
6,107✔
1870
    (*ppRes) = resBlock;
3,006✔
1871
    return code;
3,006✔
1872
  }
1873

1874
  if (pInfo->recvRetrive) {
3,101✔
1875
    pInfo->recvRetrive = false;
510✔
1876
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
510✔
1877
    (*ppRes) = pInfo->pMidRetriveRes;
505✔
1878
    return code;
505✔
1879
  }
1880

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

1892
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
5,866✔
1893
  if (pWinPhyNode->deleteMark <= 0) {
5,866✔
1894
    return DEAULT_DELETE_MARK;
3,920✔
1895
  }
1896
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
1,946✔
1897
  deleteMark = TMAX(deleteMark, interval);
1,946✔
1898
  return deleteMark;
1,946✔
1899
}
1900

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

1909
TSKEY compareTs(void* pKey) {
31,278,518✔
1910
  SWinKey* pWinKey = (SWinKey*)pKey;
31,278,518✔
1911
  return pWinKey->ts;
31,278,518✔
1912
}
1913

1914
static int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
226,375✔
1915
  if (pCtx->subsidiaries.rowLen == 0) {
226,375!
1916
    int32_t rowLen = 0;
226,379✔
1917
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
226,793✔
1918
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
414✔
1919
      rowLen += pc->pExpr->base.resSchema.bytes;
414✔
1920
    }
1921

1922
    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
226,379✔
1923
  } else {
1924
    return pCtx->subsidiaries.rowLen;
×
1925
  }
1926
}
1927

1928
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
6,112✔
1929
  int32_t size = 0;
6,112✔
1930
  for (int32_t i = 0; i < numOfCols; ++i) {
232,485✔
1931
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
226,371✔
1932
    size = TMAX(size, resSize);
226,373✔
1933
  }
1934
  return size;
6,114✔
1935
}
1936

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

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

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

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

1984
int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
885✔
1985
                                              int32_t numOfChild, SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
1986
  QRY_PARAM_CHECK(pOptrInfo);
885!
1987

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

1998
  pOperator->exprSupp.hasWindowOrGroup = true;
885✔
1999
  pOperator->pTaskInfo = pTaskInfo;
885✔
2000
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
885✔
2001

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

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

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

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

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

2043
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
885!
2044

2045
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
885✔
2046

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

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

2056
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
885✔
2057
  QUERY_CHECK_CODE(code, lino, _error);
885!
2058
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
885✔
2059

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

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

2074
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
885✔
2075
  QUERY_CHECK_CODE(code, lino, _error);
885!
2076

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

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

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

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

2105
  pInfo->dataVersion = 0;
885✔
2106
  pInfo->recvGetAll = false;
885✔
2107
  pInfo->recvPullover = false;
885✔
2108
  pInfo->recvRetrive = false;
885✔
2109

2110
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
885✔
2111
  QUERY_CHECK_CODE(code, lino, _error);
885!
2112
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidRetriveRes);
885✔
2113
  QUERY_CHECK_CODE(code, lino, _error);
885!
2114
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidPulloverRes);
885✔
2115
  QUERY_CHECK_CODE(code, lino, _error);
885!
2116

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

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

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

2145
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
885✔
2146
  QUERY_CHECK_CODE(code, lino, _error);
885!
2147

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

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

2167
  *pOptrInfo = pOperator;
885✔
2168
  return TSDB_CODE_SUCCESS;
885✔
2169

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

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

2189
void destroyResultWinInfo(void* pRes) {
×
2190
  SResultWindowInfo* pWinRes = (SResultWindowInfo*)pRes;
×
2191
  destroyFlusedPos(pWinRes->pStatePos);
×
2192
}
×
2193

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

2204
  pGroupResInfo->freeItem = false;
1,792✔
2205
  taosArrayDestroy(pGroupResInfo->pRows);
1,792✔
2206
  pGroupResInfo->pRows = NULL;
1,792✔
2207
  pGroupResInfo->index = 0;
1,792✔
2208
}
1,792✔
2209

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

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

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

2238
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
906✔
2239
  blockDataDestroy(pInfo->pDelRes);
905✔
2240
  blockDataDestroy(pInfo->pWinBlock);
905✔
2241
  tSimpleHashCleanup(pInfo->pStUpdated);
905✔
2242
  tSimpleHashCleanup(pInfo->pStDeleted);
905✔
2243
  cleanupGroupResInfo(&pInfo->groupResInfo);
906✔
2244

2245
  taosArrayDestroy(pInfo->historyWins);
906✔
2246
  blockDataDestroy(pInfo->pCheckpointRes);
906✔
2247
  tSimpleHashCleanup(pInfo->pPkDeleted);
906✔
2248
  destroyNonBlockAggSupptor(&pInfo->nbSup);
906✔
2249

2250
  taosMemoryFreeClear(param);
906!
2251
}
2252

2253
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
1,790✔
2254
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
2255
  initBasicInfo(pBasicInfo, pResultBlock);
1,790✔
2256
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
1,792✔
2257
  if (code != TSDB_CODE_SUCCESS) {
1,790!
2258
    return code;
×
2259
  }
2260

2261
  for (int32_t i = 0; i < numOfCols; ++i) {
28,566✔
2262
    pSup->pCtx[i].saveHandle.pBuf = NULL;
26,776✔
2263
  }
2264

2265
  return TSDB_CODE_SUCCESS;
1,790✔
2266
}
2267

2268
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
2,194✔
2269
  for (int i = 0; i < nums; i++) {
31,159✔
2270
    pDummy[i].functionId = pCtx[i].functionId;
28,965✔
2271
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
28,965✔
2272
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
28,965✔
2273
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
28,965✔
2274
  }
2275
}
2,194✔
2276

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

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

2307
  pBasic->pTsDataState = pScanInfo->basic.pTsDataState;
1,666✔
2308

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

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

2323
static TSKEY sesionTs(void* pKey) {
4,948✔
2324
  SSessionKey* pWinKey = (SSessionKey*)pKey;
4,948✔
2325
  return pWinKey->win.skey;
4,948✔
2326
}
2327

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

2337
  pSup->gap = gap;
2,194✔
2338
  pSup->stateKeySize = keySize;
2,194✔
2339
  pSup->stateKeyType = keyType;
2,194✔
2340
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
2,194!
2341
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
2,195!
2342

2343
  pSup->stateStore = *pStore;
2,195✔
2344
  pSup->pSessionAPI = pApi;
2,195✔
2345

2346
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
2,195✔
2347
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
2,195!
2348
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
2,195!
2349

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

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

2373
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,193✔
2374
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
2,194✔
2375
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
2,193!
2376

2377
  for (int32_t i = 0; i < numOfOutput; ++i) {
31,134✔
2378
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
28,941✔
2379
  }
2380

2381
  pSup->pCur = NULL;
2,193✔
2382

2383
_end:
2,193✔
2384
  if (code != TSDB_CODE_SUCCESS) {
2,193!
2385
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2386
  }
2387
  return code;
2,193✔
2388
}
2389

2390
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5,425✔
2391
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5,425✔
2392
    return true;
3,965✔
2393
  }
2394
  return false;
1,460✔
2395
}
2396

2397
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
4,496✔
2398
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
4,496✔
2399
}
2400

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

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

2414
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
51,884✔
2415
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
51,884!
2416
    return true;
51,922✔
2417
  }
2418
  return false;
×
2419
}
2420

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

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

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

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

2458
void getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo,
192✔
2459
                      int32_t* pWinCode) {
2460
  int32_t size = 0;
192✔
2461
  (*pWinCode) = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin,
384✔
2462
                                                                 (void**)&pWinInfo->pStatePos, &size);
192✔
2463
  if ((*pWinCode) != TSDB_CODE_SUCCESS) {
192✔
2464
    return;
163✔
2465
  }
2466

2467
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
29✔
2468
}
2469

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

2479
_end:
1,204✔
2480
  if (code != TSDB_CODE_SUCCESS) {
1,204!
2481
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2482
  }
2483
  return code;
1,204✔
2484
}
2485

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

2491
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
13,425✔
2492
  pAPI->streamStateReleaseBuf(pState, pPos, false);
13,425✔
2493
}
13,424✔
2494

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

2510
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
13,446✔
2511
  *pHashKey = *pKey;
13,446✔
2512
  pHashKey->win.ekey = pKey->win.skey;
13,446✔
2513
}
13,446✔
2514

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

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

2549
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
3,076✔
2550
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2551
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2552
                                int32_t* pWinRos) {
2553
  int32_t code = TSDB_CODE_SUCCESS;
3,076✔
2554
  int32_t lino = 0;
3,076✔
2555
  for (int32_t i = start; i < rows; ++i) {
6,973✔
2556
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
3,989!
2557
      (*pWinRos) = i - start;
92✔
2558
      goto _end;
92✔
2559
    }
2560
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
3,897✔
2561
      if (pStDeleted && pWinInfo->isOutput) {
24!
2562
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
19✔
2563
        QUERY_CHECK_CODE(code, lino, _end);
19!
2564
      }
2565

2566
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
24✔
2567
      pWinInfo->sessionWin.win.skey = pStartTs[i];
24✔
2568
    }
2569
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
3,897✔
2570
    if (pEndTs) {
3,897✔
2571
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
3,896✔
2572
    }
2573
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
3,897✔
2574
  }
2575
  (*pWinRos) = rows - start;
2,984✔
2576

2577
_end:
3,076✔
2578
  if (code != TSDB_CODE_SUCCESS) {
3,076!
2579
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2580
  }
2581
  return code;
3,077✔
2582
}
2583

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

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

2602
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
12,270✔
2603
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
12,270✔
2604

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

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

2620
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
15,771✔
2621
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
15,771✔
2622
  if (pVal) {
15,774✔
2623
    SResultWindowInfo* pWin = pVal;
729✔
2624
    pWinInfo->isOutput = pWin->isOutput;
729✔
2625
  }
2626
}
15,774✔
2627

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

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

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

2657
  pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, pNextWin->sessionWin.win.ekey);
25✔
2658
  memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
25✔
2659

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

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

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

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

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

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

2729
_end:
3,095✔
2730
  if (code != TSDB_CODE_SUCCESS) {
3,259✔
2731
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2732
  }
2733
  return code;
3,259✔
2734
}
2735

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

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

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

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

2786
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,003✔
2787
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,003✔
2788
  SColumnInfoData* pEndTsCol = NULL;
3,003✔
2789
  if (hasEndTs) {
3,003✔
2790
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
428✔
2791
  } else {
2792
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,575✔
2793
  }
2794

2795
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
3,003✔
2796

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

2804
  for (int32_t i = 0; i < rows;) {
6,096✔
2805
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
3,095!
2806
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2807
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2808
    }
2809
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
3,277✔
2810
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
183✔
2811
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
183✔
2812
      i++;
18✔
2813
      continue;
18✔
2814
    }
2815
    SResultWindowInfo winInfo = {0};
3,076✔
2816
    int32_t           winCode = TSDB_CODE_SUCCESS;
3,076✔
2817
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo, &winCode);
3,076✔
2818
    QUERY_CHECK_CODE(code, lino, _end);
3,077!
2819

2820
    if (winCode != TSDB_CODE_SUCCESS && IS_NORMAL_SESSION_OP(pOperator) &&
3,075✔
2821
        BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_OPEN)) {
1,945!
2822
      code = addSessionAggNotifyEvent(SNOTIFY_EVENT_WINDOW_OPEN, &winInfo.sessionWin, &pInfo->basic.notifyEventSup,
×
2823
                                      pTaskInfo->streamInfo.pNotifyEventStat);
2824
      QUERY_CHECK_CODE(code, lino, _end);
×
2825
    }
2826

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

2836
    int64_t winDelta = 0;
3,077✔
2837
    if (addGap) {
3,077✔
2838
      winDelta = pAggSup->gap;
2,493✔
2839
    }
2840
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
3,077✔
2841
                              pOperator, winDelta);
2842
    QUERY_CHECK_CODE(code, lino, _end);
3,076!
2843

2844
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL, NULL);
3,076✔
2845
    QUERY_CHECK_CODE(code, lino, _end);
3,077✔
2846

2847
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,075✔
2848
    QUERY_CHECK_CODE(code, lino, _end);
3,075!
2849

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

2866
    i += winRows;
3,075✔
2867
  }
2868

2869
_end:
3,001✔
2870
  if (code != TSDB_CODE_SUCCESS) {
3,003✔
2871
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2872
  }
2873
}
3,003✔
2874

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

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

2906
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
6,264✔
2907
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
6,264✔
2908
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
6,264✔
2909
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
6,264✔
2910
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
6,264✔
2911

2912
  if (pWin1->groupId > pWin2->groupId) {
6,264✔
2913
    return 1;
1,995✔
2914
  } else if (pWin1->groupId < pWin2->groupId) {
4,269✔
2915
    return -1;
1,739✔
2916
  }
2917

2918
  if (pWin1->win.skey > pWin2->win.skey) {
2,530✔
2919
    return 1;
1,396✔
2920
  } else if (pWin1->win.skey < pWin2->win.skey) {
1,134!
2921
    return -1;
1,134✔
2922
  }
2923

2924
  return 0;
×
2925
}
2926

2927
static int32_t appendToDeleteDataBlock(SOperatorInfo* pOp, SSDataBlock *pBlock, SSessionKey *pKey) {
684✔
2928
  int32_t        code = TSDB_CODE_SUCCESS;
684✔
2929
  int32_t        lino = 0;
684✔
2930
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
684✔
2931

2932
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
684!
2933
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
684!
2934

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

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

2943
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
684✔
2944
  colDataSetNULL(pUidCol, pBlock->info.rows);
684!
2945

2946
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
684✔
2947
  code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&pKey->groupId, false);
684✔
2948
  QUERY_CHECK_CODE(code, lino, _end);
684!
2949

2950
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
684✔
2951
  colDataSetNULL(pCalStCol, pBlock->info.rows);
684!
2952

2953
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
684✔
2954
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
684!
2955

2956
  SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
684✔
2957
  if (!pTableCol) {
684!
2958
    QUERY_CHECK_CODE(code, lino, _end);
×
2959
  }
2960

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

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

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

2986
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite,
17,495✔
2987
                            SGroupResInfo* pGroupResInfo) {
2988
  int32_t        code = TSDB_CODE_SUCCESS;
17,495✔
2989
  int32_t        lino = 0;
17,495✔
2990
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
17,495✔
2991
  int64_t        minWindowSize = getMinWindowSize(pOp);
17,495✔
2992
  int32_t        numOfRows = getNumOfTotalRes(pGroupResInfo);
17,489✔
2993

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

3013
  int32_t iter = 0;
538✔
3014
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
1,162✔
3015
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
624!
3016
      break;
×
3017
    }
3018
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
624!
3019
    code = appendToDeleteDataBlock(pOp, pBlock, res);
624✔
3020
    QUERY_CHECK_CODE(code, lino, _end);
624!
3021
  }
3022

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

3036
_end:
520✔
3037
  if ((*Ite) == NULL) {
538!
3038
    tSimpleHashClear(pStDeleted);
538✔
3039
  }
3040

3041
  if (code != TSDB_CODE_SUCCESS) {
538!
3042
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3043
  }
3044
}
3045

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

3054
  int32_t                        size = taosArrayGetSize(pWinArray);
50✔
3055
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
50✔
3056
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
50✔
3057
  int32_t                        numOfOutput = pSup->numOfExprs;
50✔
3058
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
50✔
3059

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

3078
        if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
192!
3079
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
×
3080
          continue;
×
3081
        }
3082

3083
        if (winCode == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
192✔
3084
          if (num == 0) {
20!
3085
            code = setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin,
20✔
3086
                                       &winCode);
3087
            QUERY_CHECK_CODE(code, lino, _end);
20!
3088

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

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

3104
          code = compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo,
20✔
3105
                                  &pInfo->twAggSup.timeWindowData);
3106
          QUERY_CHECK_CODE(code, lino, _end);
20!
3107

3108
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL, NULL);
20✔
3109
          QUERY_CHECK_CODE(code, lino, _end);
20!
3110

3111
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
20✔
3112
        } else {
3113
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
172✔
3114
          break;
172✔
3115
        }
3116
      }
3117
      pAPI->stateStore.streamStateFreeCur(pCur);
172✔
3118
    }
3119
    if (num > 0) {
48✔
3120
      code = saveResult(parentWin, pStUpdated);
20✔
3121
      QUERY_CHECK_CODE(code, lino, _end);
20!
3122

3123
      code = saveSessionOutputBuf(pAggSup, &parentWin);
20✔
3124
      QUERY_CHECK_CODE(code, lino, _end);
20!
3125
    }
3126
  }
3127

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

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

3159
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
3,633✔
3160
  int32_t code = TSDB_CODE_SUCCESS;
3,633✔
3161
  int32_t lino = 0;
3,633✔
3162

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

3178
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
242✔
3179
  int32_t code = TSDB_CODE_SUCCESS;
242✔
3180
  int32_t lino = 0;
242✔
3181
  void*   pIte = NULL;
242✔
3182
  int32_t iter = 0;
242✔
3183
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
342✔
3184
    SResultWindowInfo* pWinInfo = pIte;
100✔
3185
    if (!pWinInfo->pStatePos->beUpdated) {
100✔
3186
      continue;
4✔
3187
    }
3188
    pWinInfo->pStatePos->beUpdated = false;
96✔
3189
    code = saveResult(*pWinInfo, pStUpdated);
96✔
3190
    QUERY_CHECK_CODE(code, lino, _end);
96!
3191
  }
3192

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

3200
int32_t copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
1,100✔
3201
  int32_t code = TSDB_CODE_SUCCESS;
1,100✔
3202
  int32_t lino = 0;
1,100✔
3203
  int32_t size = taosArrayGetSize(pResWins);
1,100✔
3204
  for (int32_t i = 0; i < size; i++) {
2,308✔
3205
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
1,208✔
3206
    if (!pWinKey) continue;
1,208!
3207
    SSessionKey winInfo = {0};
1,208✔
3208
    getSessionHashKey(pWinKey, &winInfo);
1,208✔
3209
    code = tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
1,208✔
3210
    QUERY_CHECK_CODE(code, lino, _end);
1,208!
3211
  }
3212

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

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

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

3241
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
5,539✔
3242

3243
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
12,277✔
3244
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
8,501✔
3245
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
8,501✔
3246
    SResultRow*        pRow = NULL;
8,501✔
3247
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
8,501✔
3248

3249
    if (pBlock->info.id.groupId == 0) {
8,501✔
3250
      pBlock->info.id.groupId = pKey->groupId;
6,056✔
3251

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

3258
      if (winCode != TSDB_CODE_SUCCESS) {
6,057✔
3259
        pBlock->info.parTbName[0] = 0;
1,683✔
3260
      } else {
3261
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,374✔
3262
      }
3263
      pAPI->stateStore.streamStateFreeVal(tbname);
6,057✔
3264
    } else {
3265
      // current value belongs to different group, it can't be packed into one datablock
3266
      if (pBlock->info.id.groupId != pKey->groupId) {
2,445✔
3267
        break;
1,740✔
3268
      }
3269
    }
3270

3271
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
6,763✔
3272
    QUERY_CHECK_CODE(code, lino, _end);
6,761!
3273

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

3288
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,700!
3289
      break;
×
3290
    }
3291

3292
    pGroupResInfo->index += 1;
6,700✔
3293

3294
    for (int32_t j = 0; j < numOfExprs; ++j) {
111,771✔
3295
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
105,092✔
3296

3297
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
105,092✔
3298
      if (pCtx[j].fpSet.finalize) {
105,097✔
3299
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
96,172✔
3300
        if (TAOS_FAILED(tmpRes)) {
96,172!
3301
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
3302
          QUERY_CHECK_CODE(code, lino, _end);
×
3303
        }
3304
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
8,925✔
3305
        // do nothing, todo refactor
3306
      } else {
3307
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
3308
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
3309
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
8,918✔
3310
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
8,919✔
3311
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
17,835✔
3312
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
8,919✔
3313
          QUERY_CHECK_CODE(code, lino, _end);
8,916!
3314
        }
3315
      }
3316
    }
3317

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

3325
    pBlock->info.dataLoad = 1;
6,679✔
3326
    pBlock->info.rows += pRow->numOfRows;
6,679✔
3327
  }
3328
  code = blockDataUpdateTsWindow(pBlock, 0);
5,516✔
3329
  QUERY_CHECK_CODE(code, lino, _end);
5,541!
3330

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

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

3346
  blockDataCleanup(pBlock);
16,939✔
3347
  taosArrayClear(pSessionKeys);
16,951✔
3348
  if (!hasRemainResults(pGroupResInfo)) {
16,951✔
3349
    cleanupGroupResInfo(pGroupResInfo);
11,413✔
3350
    goto _end;
11,423✔
3351
  }
3352

3353
  // clear the existed group id
3354
  pBlock->info.id.groupId = 0;
5,539✔
3355
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo, pSessionKeys);
5,539✔
3356
  QUERY_CHECK_CODE(code, lino, _end);
5,541!
3357

3358
  if (pBlock->info.rows == 0) {
5,541!
3359
    cleanupGroupResInfo(pGroupResInfo);
×
3360
  }
3361

3362
_end:
5,541✔
3363
  if (code != TSDB_CODE_SUCCESS) {
16,964!
3364
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3365
  }
3366
}
16,964✔
3367

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

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

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

3417
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
4,682✔
3418
  QUERY_CHECK_CODE(code, lino, _end);
4,678!
3419

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

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

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

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

3467
int32_t encodeSSessionKey(void** buf, SSessionKey* key) {
8✔
3468
  int32_t tlen = 0;
8✔
3469
  tlen += encodeSTimeWindow(buf, &key->win);
8✔
3470
  tlen += taosEncodeFixedU64(buf, key->groupId);
8✔
3471
  return tlen;
8✔
3472
}
3473

3474
void* decodeSSessionKey(void* buf, SSessionKey* key) {
×
3475
  buf = decodeSTimeWindow(buf, &key->win);
×
3476
  buf = taosDecodeFixedU64(buf, &key->groupId);
×
3477
  return buf;
×
3478
}
3479

3480
int32_t encodeSResultWindowInfo(void** buf, SResultWindowInfo* key, int32_t outLen) {
4✔
3481
  int32_t tlen = 0;
4✔
3482
  tlen += taosEncodeFixedBool(buf, key->isOutput);
4✔
3483
  tlen += encodeSSessionKey(buf, &key->sessionWin);
4✔
3484
  return tlen;
4✔
3485
}
3486

3487
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
×
3488
  buf = taosDecodeFixedBool(buf, &key->isOutput);
×
3489
  buf = decodeSSessionKey(buf, &key->sessionWin);
×
3490
  return buf;
×
3491
}
3492

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

3499
  void* pData = (buf == NULL) ? NULL : *buf;
×
3500

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

3514
  // 2.twAggSup
3515
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3516

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

3525
  // 4.dataVersion
3526
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
3527

3528
  // 5.basicInfo
3529
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
×
3530

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

3541
  return tlen;
×
3542
}
3543

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

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

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

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

3586
  // 2.twAggSup
3587
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3588

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

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

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

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

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

3635
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
103✔
3636
  void*   pIte = NULL;
103✔
3637
  int32_t iter = 0;
103✔
3638
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
203✔
3639
    SResultWindowInfo* pResInfo = pIte;
100✔
3640
    pResInfo->pStatePos->beUsed = true;
100✔
3641
  }
3642
}
103✔
3643

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

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

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

3688
    if (pInfo->recvGetAll) {
1,365✔
3689
      pInfo->recvGetAll = false;
85✔
3690
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
85✔
3691
    }
3692

3693
    if (pInfo->reCkBlock) {
1,365!
3694
      pInfo->reCkBlock = false;
×
3695
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3696
      (*ppRes) = pInfo->pCheckpointRes;
×
3697
      return code;
×
3698
    }
3699

3700
    setStreamOperatorCompleted(pOperator);
1,365✔
3701
    (*ppRes) = NULL;
1,365✔
3702
    return code;
1,365✔
3703
  }
3704

3705
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,452✔
3706
  if (!pInfo->pUpdated) {
4,452✔
3707
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
3,631✔
3708
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
3,630!
3709
  }
3710
  if (!pInfo->pStUpdated) {
4,451✔
3711
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,561✔
3712
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
3,559✔
3713
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
3,558!
3714
  }
3715
  while (1) {
3,217✔
3716
    SSDataBlock* pBlock = NULL;
7,665✔
3717
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,665✔
3718
    QUERY_CHECK_CODE(code, lino, _end);
7,670!
3719

3720
    if (pBlock == NULL) {
7,670✔
3721
      break;
3,632✔
3722
    }
3723
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,038✔
3724
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,039✔
3725

3726
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,040✔
3727
        pBlock->info.type == STREAM_CLEAR) {
3,807✔
3728
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
393✔
3729
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
392!
3730
      // gap must be 0
3731
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
392✔
3732
      QUERY_CHECK_CODE(code, lino, _end);
392!
3733

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

3743
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
50✔
3744
        QUERY_CHECK_CODE(code, lino, _end);
50!
3745
      }
3746
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
392✔
3747
      QUERY_CHECK_CODE(code, lino, _end);
392!
3748

3749
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
392!
3750
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
2✔
3751
        QUERY_CHECK_CODE(code, lino, _end);
2!
3752
      }
3753
      taosArrayDestroy(pWins);
392✔
3754
      continue;
758✔
3755
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,647✔
3756
      pInfo->recvGetAll = true;
190✔
3757
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
190✔
3758
      QUERY_CHECK_CODE(code, lino, _end);
190!
3759
      continue;
190✔
3760
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,457✔
3761
      (*ppRes) = pBlock;
823✔
3762
      return code;
823✔
3763
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,634✔
3764
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
176✔
3765
      doStreamSessionSaveCheckpoint(pOperator);
176✔
3766
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
176✔
3767
      QUERY_CHECK_CODE(code, lino, _end);
176!
3768

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

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

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

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

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

3819
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
3,632✔
3820
  QUERY_CHECK_CODE(code, lino, _end);
3,633!
3821

3822
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
3,633✔
3823
  QUERY_CHECK_CODE(code, lino, _end);
3,634!
3824

3825
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
3,634✔
3826
  QUERY_CHECK_CODE(code, lino, _end);
3,632!
3827

3828
  if (!pInfo->destHasPrimaryKey) {
3,632✔
3829
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
3,615✔
3830
  }
3831
  if (pInfo->isHistoryOp) {
3,631✔
3832
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
197✔
3833
    QUERY_CHECK_CODE(code, lino, _end);
197!
3834
  }
3835
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
3,631!
3836
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
18✔
3837
    QUERY_CHECK_CODE(code, lino, _end);
18!
3838
  }
3839
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
3,631✔
3840
  pInfo->pUpdated = NULL;
3,625✔
3841
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3,625✔
3842
  QUERY_CHECK_CODE(code, lino, _end);
3,632!
3843

3844
  SSDataBlock* opRes = NULL;
3,632✔
3845
  code = buildSessionResult(pOperator, &opRes);
3,632✔
3846
  QUERY_CHECK_CODE(code, lino, _end);
3,630!
3847
  if (opRes) {
3,630✔
3848
    (*ppRes) = opRes;
1,366✔
3849
    return code;
1,366✔
3850
  }
3851

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

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

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

3889
void resetWinRange(STimeWindow* winRange) {
359✔
3890
  winRange->skey = INT64_MIN;
359✔
3891
  winRange->ekey = INT64_MAX;
359✔
3892
}
359✔
3893

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

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

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

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

3923
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
643✔
3924
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
205✔
3925
    return;
205✔
3926
  }
3927

3928
  SStreamScanInfo* pScanInfo = downstream->info;
438✔
3929
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
438✔
3930
}
3931

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

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

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

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

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

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

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

3990
  QUERY_CHECK_CODE(code, lino, _end);
176!
3991

3992
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
176✔
3993
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
176✔
3994

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

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

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

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

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

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

4050
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
904✔
4051
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4052
  QRY_PARAM_CHECK(pOptrInfo);
904!
4053

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

4065
  pOperator->pTaskInfo = pTaskInfo;
906✔
4066

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

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

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

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

4089
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
906✔
4090
  QUERY_CHECK_CODE(code, lino, _error);
906!
4091

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

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

4109
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
906✔
4110
  QUERY_CHECK_CODE(code, lino, _error);
905!
4111

4112
  if (pSessionNode->window.pTsEnd) {
905!
4113
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
906✔
4114
  }
4115

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

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

4139
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
906✔
4140
  QUERY_CHECK_CODE(code, lino, _error);
906!
4141

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

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

4166
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
905✔
4167
  QUERY_CHECK_CODE(code, lino, _error);
906!
4168

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

4186
  if (downstream) {
906✔
4187
    pInfo->basic.primaryPkIndex = -1;
781✔
4188
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
781✔
4189
                          &pInfo->twAggSup, &pInfo->basic, pSessionNode->window.recalculateInterval);
781✔
4190
    QUERY_CHECK_CODE(code, lino, _error);
781!
4191

4192
    code = appendDownstream(pOperator, &downstream, 1);
781✔
4193
    QUERY_CHECK_CODE(code, lino, _error);
781!
4194
  }
4195

4196
  *pOptrInfo = pOperator;
906✔
4197
  return TSDB_CODE_SUCCESS;
906✔
4198

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

4209
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
458✔
4210
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
458✔
4211
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
459✔
4212
  pInfo->clearState = false;
459✔
4213
}
459✔
4214

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

4227
  removeSessionResults(pAggSup, pMapUpdate, pWins);
635✔
4228
  code = copyDeleteWindowInfo(pWins, pMapDelete);
635✔
4229
  QUERY_CHECK_CODE(code, lino, _end);
635!
4230

4231
  if (needAdd) {
635!
4232
    code = copyDeleteWindowInfo(pWins, pPkDelete);
×
4233
    QUERY_CHECK_CODE(code, lino, _end);
×
4234
  }
4235
  taosArrayDestroy(pWins);
635✔
4236

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

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

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

4260
  {
4261
    SSDataBlock* opRes = NULL;
853✔
4262
    code = buildSessionResult(pOperator, &opRes);
853✔
4263
    QUERY_CHECK_CODE(code, lino, _end);
854!
4264
    if (opRes) {
854✔
4265
      (*ppRes) = opRes;
85✔
4266
      return code;
214✔
4267
    }
4268

4269
    if (pInfo->clearState) {
769✔
4270
      clearFunctionContext(&pOperator->exprSupp);
50✔
4271
      // semi session operator clear disk buffer
4272
      clearStreamSessionOperator(pInfo);
50✔
4273
    }
4274

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

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

4306
    if (pBlock == NULL) {
985✔
4307
      pOperator->status = OP_RES_TO_RETURN;
409✔
4308
      break;
409✔
4309
    }
4310
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
576✔
4311
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
576✔
4312

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

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

4350
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
459✔
4351
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
459✔
4352

4353
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
459✔
4354
  QUERY_CHECK_CODE(code, lino, _end);
459!
4355

4356
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
459✔
4357

4358
  if (pInfo->isHistoryOp) {
459✔
4359
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
15✔
4360
    QUERY_CHECK_CODE(code, lino, _end);
15!
4361
  }
4362

4363
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
459✔
4364
  pInfo->pUpdated = NULL;
459✔
4365
  code = blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
459✔
4366
  QUERY_CHECK_CODE(code, lino, _end);
459!
4367

4368
  SSDataBlock* opRes = NULL;
459✔
4369
  code = buildSessionResult(pOperator, &opRes);
459✔
4370
  QUERY_CHECK_CODE(code, lino, _end);
459!
4371
  if (opRes) {
459✔
4372
    (*ppRes) = opRes;
179✔
4373
    return code;
179✔
4374
  }
4375

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

4383
  clearFunctionContext(&pOperator->exprSupp);
280✔
4384
  // semi session operator clear disk buffer
4385
  clearStreamSessionOperator(pInfo);
279✔
4386
  setStreamOperatorCompleted(pOperator);
280✔
4387
  (*ppRes) = NULL;
280✔
4388
  return code;
280✔
4389
}
4390

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

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

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

4411
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
288✔
4412
  pInfo->pOperator = pOperator;
288✔
4413

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

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

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

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

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

4457
  *pOptrInfo = pOperator;
288✔
4458
  return code;
288✔
4459

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

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

4487
  destroyStreamBasicInfo(&pInfo->basic);
353✔
4488
  clearSessionGroupResInfo(&pInfo->groupResInfo);
353✔
4489
  taosArrayDestroyEx(pInfo->pUpdated, destroyResultWinInfo);
353✔
4490
  pInfo->pUpdated = NULL;
353✔
4491
  destroyStreamAggSupporter(&pInfo->streamAggSup);
353✔
4492

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

4508
  taosArrayDestroy(pInfo->historyWins);
353✔
4509
  blockDataDestroy(pInfo->pCheckpointRes);
353✔
4510
  tSimpleHashCleanup(pInfo->pPkDeleted);
353✔
4511
  destroyNonBlockAggSupptor(&pInfo->nbSup);
353✔
4512

4513
  taosMemoryFreeClear(param);
353!
4514
}
4515

4516
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
3,906✔
4517
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
3,906✔
4518
    return true;
1,252✔
4519
  }
4520
  return false;
2,654✔
4521
}
4522

4523
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
6,451✔
4524
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
6,451!
4525
}
4526

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

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

4543
void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
3,324✔
4544
  SStreamStateCur* pCur = NULL;
3,324✔
4545

4546
  if (pAggSup == NULL || pNextWin == NULL) {
3,324!
4547
    return;
×
4548
  }
4549

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

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

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

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

4598
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
129✔
4599
  getNextStateWin(pAggSup, pNextWin, true);
129✔
4600

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

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

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

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

4647
  if (winCode == TSDB_CODE_SUCCESS) {
3,194✔
4648
    pCurWin->winInfo.isOutput = true;
1,992✔
4649
    if (pCurWin->winInfo.pStatePos->needFree) {
1,992✔
4650
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
36✔
4651
    }
4652
  } else if (pKeyData) {
1,202!
4653
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,202!
4654
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4655
    } else {
4656
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,198✔
4657
    }
4658
  }
4659

4660
  *pWinCode = winCode;
3,194✔
4661

4662
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
3,194✔
4663
         pCurWin->winInfo.sessionWin.win.ekey);
4664

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

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

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

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

4723
static bool isWinResult(SSessionKey* pKey, SSHashObj* pSeUpdate, SSHashObj* pResults) {
3,195✔
4724
  SSessionKey checkKey = {0};
3,195✔
4725
  getSessionHashKey(pKey, &checkKey);
3,195✔
4726
  if (tSimpleHashGet(pSeUpdate, &checkKey, sizeof(SSessionKey)) != NULL) {
3,195✔
4727
    return true;
28✔
4728
  }
4729

4730
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
3,167✔
4731
    return true;
17✔
4732
  }
4733
  return false;
3,150✔
4734
}
4735

4736
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
3,098✔
4737
                                 SSHashObj* pStDeleted) {
4738
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3,098✔
4739
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
3,098✔
4740

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

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

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

4770
  int32_t rows = pSDataBlock->info.rows;
3,098✔
4771
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
3,098✔
4772
  QUERY_CHECK_CODE(code, lino, _end);
3,098!
4773

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

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

4812
    if (isWinResult(&nextWin.winInfo.sessionWin, pSeUpdated, pAggSup->pResultRows) == false) {
3,195✔
4813
      releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,150✔
4814
    }
4815

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

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

4829
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
23✔
4830
      releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
23✔
4831
      continue;
23✔
4832
    }
4833

4834
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
3,172✔
4835
                              pOperator, 0);
4836
    QUERY_CHECK_CODE(code, lino, _end);
3,172!
4837

4838
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,172✔
4839
    QUERY_CHECK_CODE(code, lino, _end);
3,172!
4840

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

4846
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,172✔
4847
      code = saveResult(curWin.winInfo, pSeUpdated);
2,857✔
4848
      QUERY_CHECK_CODE(code, lino, _end);
2,857!
4849
    }
4850

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

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

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

4875
int32_t doStreamStateEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
4✔
4876
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4✔
4877
  if (!pInfo) {
4!
4878
    return 0;
×
4879
  }
4880

4881
  void* pData = (buf == NULL) ? NULL : *buf;
4✔
4882

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

4896
  // 2.twAggSup
4897
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
4✔
4898

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

4907
  // 4.dataVersion
4908
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
4✔
4909

4910
  // 5.basicInfo
4911
  tlen += encodeStreamBasicInfo(buf, &pInfo->basic);
4✔
4912

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

4923
  return tlen;
4✔
4924
}
4925

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

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

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

4962
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
4963
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
4964
                          sizeof(SResultWindowInfo));
4965
    QUERY_CHECK_CODE(code, lino, _end);
×
4966
  }
4967

4968
  // 2.twAggSup
4969
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
4970

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

4980
  // 4.dataVersion
4981
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
4982

4983
  if (ppBuf) {
×
4984
    (*ppBuf) = buf;
×
4985
  }
4986

4987
  // 5.basicInfo
4988
  if (buf < pDataEnd) {
×
4989
    code = decodeStreamBasicInfo(&buf, &pInfo->basic);
×
4990
    QUERY_CHECK_CODE(code, lino, _end);
×
4991
  }
4992

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

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

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

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

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

5060
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
2,712✔
5061
  QUERY_CHECK_CODE(code, lino, _end);
2,712!
5062

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

5071
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,610✔
5072
  if (pOperator->status == OP_EXEC_DONE) {
4,610!
5073
    (*ppRes) = NULL;
×
5074
    return TSDB_CODE_SUCCESS;
×
5075
  }
5076

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

5093
    if (pInfo->recvGetAll) {
1,136✔
5094
      pInfo->recvGetAll = false;
3✔
5095
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
3✔
5096
    }
5097

5098
    if (pInfo->reCkBlock) {
1,136!
5099
      pInfo->reCkBlock = false;
×
5100
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5101
      (*ppRes) = pInfo->pCheckpointRes;
×
5102
      return code;
×
5103
    }
5104

5105
    setStreamOperatorCompleted(pOperator);
1,136✔
5106
    (*ppRes) = NULL;
1,136✔
5107
    return code;
1,136✔
5108
  }
5109

5110
  SOperatorInfo* downstream = pOperator->pDownstream[0];
3,115✔
5111
  if (!pInfo->pUpdated) {
3,115✔
5112
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,712✔
5113
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,712!
5114
  }
5115
  if (!pInfo->pSeUpdated) {
3,115✔
5116
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,679✔
5117
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,679✔
5118
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,680!
5119
  }
5120
  while (1) {
4,062✔
5121
    SSDataBlock* pBlock = NULL;
7,178✔
5122
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
7,178✔
5123
    QUERY_CHECK_CODE(code, lino, _end);
7,178!
5124

5125
    if (pBlock == NULL) {
7,178✔
5126
      break;
2,712✔
5127
    }
5128
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,466✔
5129
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,465✔
5130

5131
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,466✔
5132
        pBlock->info.type == STREAM_CLEAR) {
3,987✔
5133
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
517!
5134
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
517✔
5135
                                   pInfo->pPkDeleted, add);
5136
      QUERY_CHECK_CODE(code, lino, _end);
517!
5137
      continue;
964✔
5138
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,949✔
5139
      pInfo->recvGetAll = true;
10✔
5140
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
10✔
5141
      QUERY_CHECK_CODE(code, lino, _end);
10!
5142
      continue;
10✔
5143
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,939✔
5144
      (*ppRes) = pBlock;
404✔
5145
      return code;
404✔
5146
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,535✔
5147
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
437✔
5148
      doStreamStateSaveCheckpoint(pOperator);
437✔
5149
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
437✔
5150
      QUERY_CHECK_CODE(code, lino, _end);
437!
5151

5152
      continue;
437✔
5153
    } else {
5154
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
3,098!
5155
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5156
        QUERY_CHECK_CODE(code, lino, _end);
×
5157
      }
5158
    }
5159

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

5174
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,712✔
5175
  QUERY_CHECK_CODE(code, lino, _end);
2,712!
5176

5177
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,712✔
5178
  QUERY_CHECK_CODE(code, lino, _end);
2,712!
5179

5180
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,712✔
5181

5182
  if (pInfo->isHistoryOp) {
2,712✔
5183
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
91✔
5184
    QUERY_CHECK_CODE(code, lino, _end);
91!
5185
  }
5186
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,712!
5187
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
4✔
5188
    QUERY_CHECK_CODE(code, lino, _end);
4!
5189
  }
5190

5191
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,712✔
5192
  pInfo->pUpdated = NULL;
2,711✔
5193
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,711✔
5194
  QUERY_CHECK_CODE(code, lino, _end);
2,711!
5195

5196
  SSDataBlock* resBlock = NULL;
2,711✔
5197
  code = buildStateResult(pOperator, &resBlock);
2,711✔
5198
  QUERY_CHECK_CODE(code, lino, _end);
2,712!
5199
  if (resBlock != NULL) {
2,712✔
5200
    (*ppRes) = resBlock;
1,136✔
5201
    return code;
1,136✔
5202
  }
5203

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

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

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

5237
  SOperatorInfo* downstream = pOperator->pDownstream[0];
87✔
5238
  if (downstream->fpSet.releaseStreamStateFn) {
87!
5239
    downstream->fpSet.releaseStreamStateFn(downstream);
87✔
5240
  }
5241
}
5242

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

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

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

5267
  int32_t num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
87✔
5268
  qDebug("===stream=== reload state. get result count:%d", num);
87✔
5269
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
87✔
5270

5271
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
87✔
5272
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
87✔
5273
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
87✔
5274

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

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

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

5320
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
129!
5321
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
129✔
5322
      QUERY_CHECK_CODE(code, lino, _end);
129!
5323
    }
5324
  }
5325
  taosMemoryFreeClear(pBuf);
87!
5326

5327
  SOperatorInfo* downstream = pOperator->pDownstream[0];
87✔
5328
  if (downstream->fpSet.reloadStreamStateFn) {
87!
5329
    downstream->fpSet.reloadStreamStateFn(downstream);
87✔
5330
  }
5331
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
87✔
5332

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

5340
int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
351✔
5341
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5342
  QRY_PARAM_CHECK(pOptrInfo);
351!
5343
  int32_t code = 0;
351✔
5344
  int32_t lino = 0;
351✔
5345

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

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

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

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

5376
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
353✔
5377
  QUERY_CHECK_CODE(code, lino, _error);
353!
5378

5379
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
353✔
5380
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
353!
5381
  pInfo->binfo.pRes = pResBlock;
353✔
5382

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

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

5402
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
352✔
5403
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
352✔
5404
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
353!
5405
  pInfo->pDelIterator = NULL;
353✔
5406

5407
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
353✔
5408
  QUERY_CHECK_CODE(code, lino, _error);
353!
5409

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

5422
  if (pHandle) {
352!
5423
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
352✔
5424
  }
5425

5426
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
352✔
5427
  QUERY_CHECK_CODE(code, lino, _error);
353!
5428

5429
  pInfo->recvGetAll = false;
353✔
5430
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
353✔
5431
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
353!
5432
  pInfo->destHasPrimaryKey = pStateNode->window.destHasPrimaryKey;
353✔
5433
  pInfo->pOperator = pOperator;
353✔
5434

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

5452
  if (pStateNode->window.triggerType == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
353!
5453
    if (pHandle->fillHistory == STREAM_HISTORY_OPERATOR) {
×
5454
      setFillHistoryOperatorFlag(&pInfo->basic);
×
5455
    } else if (pHandle->fillHistory == STREAM_RECALCUL_OPERATOR) {
×
5456
      setRecalculateOperatorFlag(&pInfo->basic);
×
5457
    }
5458

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

5469
  code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
353✔
5470
                        &pInfo->twAggSup, &pInfo->basic, 0);
353✔
5471
  QUERY_CHECK_CODE(code, lino, _error);
353!
5472

5473
  code = appendDownstream(pOperator, &downstream, 1);
353✔
5474
  QUERY_CHECK_CODE(code, lino, _error);
353!
5475

5476
  pInfo->trueForLimit = pStateNode->trueForLimit;
353✔
5477

5478
  *pOptrInfo = pOperator;
353✔
5479
  return TSDB_CODE_SUCCESS;
353✔
5480

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

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

5501
static int32_t doStreamIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
126,862✔
5502
  int32_t                      code = TSDB_CODE_SUCCESS;
126,862✔
5503
  int32_t                      lino = 0;
126,862✔
5504
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
126,862✔
5505
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
126,862✔
5506
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
126,862✔
5507
  SExprSupp*                   pSup = &pOperator->exprSupp;
126,862✔
5508

5509
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
126,862✔
5510

5511
  if (pOperator->status == OP_EXEC_DONE) {
126,863✔
5512
    (*ppRes) = NULL;
668✔
5513
    return code;
668✔
5514
  }
5515

5516
  if (pOperator->status == OP_RES_TO_RETURN) {
126,195✔
5517
    SSDataBlock* resBlock = NULL;
100,130✔
5518
    code = buildIntervalResult(pOperator, &resBlock);
100,130✔
5519
    QUERY_CHECK_CODE(code, lino, _end);
100,129!
5520
    if (resBlock != NULL) {
100,129✔
5521
      (*ppRes) = resBlock;
86,078✔
5522
      return code;
100,131✔
5523
    }
5524

5525
    if (pInfo->recvGetAll) {
14,051✔
5526
      pInfo->recvGetAll = false;
183✔
5527
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
183✔
5528
    }
5529

5530
    if (pInfo->reCkBlock) {
14,053✔
5531
      pInfo->reCkBlock = false;
108✔
5532
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
108✔
5533
      (*ppRes) = pInfo->pCheckpointRes;
108✔
5534
      return code;
108✔
5535
    }
5536

5537
    setStreamOperatorCompleted(pOperator);
13,945✔
5538
    (*ppRes) = NULL;
13,945✔
5539
    return code;
13,945✔
5540
  }
5541

5542
  SOperatorInfo* downstream = pOperator->pDownstream[0];
26,065✔
5543

5544
  if (!pInfo->pUpdated) {
26,065✔
5545
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
23,205✔
5546
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
23,208!
5547
  }
5548

5549
  if (!pInfo->pUpdatedMap) {
26,068✔
5550
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
23,208✔
5551
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
23,209✔
5552
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
23,206!
5553
  }
5554

5555
  while (1) {
1,025,008✔
5556
    SSDataBlock* pBlock = NULL;
1,051,074✔
5557
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,051,074✔
5558
    QUERY_CHECK_CODE(code, lino, _end);
1,051,078✔
5559

5560
    if (pBlock == NULL) {
1,051,059✔
5561
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
23,207✔
5562
             pInfo->numOfDatapack);
5563
      pInfo->numOfDatapack = 0;
23,205✔
5564
      break;
23,205✔
5565
    }
5566

5567
    pInfo->numOfDatapack++;
1,027,852✔
5568
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
1,027,852✔
5569
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
1,027,852✔
5570

5571
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
1,027,848✔
5572
        pBlock->info.type == STREAM_CLEAR) {
1,027,478✔
5573
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,068✔
5574
      QUERY_CHECK_CODE(code, lino, _end);
1,069!
5575
      continue;
3,759✔
5576
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,026,780✔
5577
      pInfo->recvGetAll = true;
1,383✔
5578
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
1,383✔
5579
      QUERY_CHECK_CODE(code, lino, _end);
1,383!
5580
      continue;
1,383✔
5581
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
1,025,397✔
5582
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,785✔
5583
      (*ppRes) = pBlock;
2,785✔
5584
      return code;
2,840✔
5585
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
1,022,612✔
5586
      doDeleteWindowByGroupId(pOperator, pBlock);
55✔
5587
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
55✔
5588
      (*ppRes) = pBlock;
55✔
5589
      return code;
55✔
5590
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,022,557✔
5591
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,307✔
5592
      doStreamIntervalSaveCheckpoint(pOperator);
1,307✔
5593
      pInfo->reCkBlock = true;
1,307✔
5594
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,307✔
5595
      QUERY_CHECK_CODE(code, lino, _end);
1,307!
5596

5597
      continue;
1,307✔
5598
    } else {
5599
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,021,250!
5600
        qDebug("===stream===%s ignore recv block. type:%d", GET_TASKID(pTaskInfo), pBlock->info.type);
×
5601
        continue;
×
5602
      }
5603
    }
5604

5605
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
1,021,250✔
5606
      // set input version
5607
      pTaskInfo->version = pBlock->info.version;
322,805✔
5608
    }
5609

5610
    if (pInfo->scalarSupp.pExprInfo != NULL) {
1,021,250✔
5611
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5612
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5613
      QUERY_CHECK_CODE(code, lino, _end);
13!
5614
    }
5615

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

5627
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
1,021,249✔
5628
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
1,021,249!
5629
      pOperator->status = OP_RES_TO_RETURN;
×
5630
      code = TSDB_CODE_SUCCESS;
×
5631
      break;
×
5632
    }
5633
    QUERY_CHECK_CODE(code, lino, _end);
1,021,249!
5634
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
1,021,249✔
5635
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
1,021,249✔
5636
  }
5637
  pOperator->status = OP_RES_TO_RETURN;
23,205✔
5638
  if (!pInfo->destHasPrimaryKey) {
23,205✔
5639
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
23,195✔
5640
  }
5641
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
23,201✔
5642
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5643
  QUERY_CHECK_CODE(code, lino, _end);
23,208!
5644

5645
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
23,208!
5646
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
12✔
5647
    QUERY_CHECK_CODE(code, lino, _end);
12!
5648
  }
5649

5650
  void*   pIte = NULL;
23,208✔
5651
  int32_t iter = 0;
23,208✔
5652
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
8,767,099✔
5653
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
8,743,902✔
5654
    if (!tmp) {
8,743,891!
5655
      code = terrno;
×
5656
      QUERY_CHECK_CODE(code, lino, _end);
×
5657
    }
5658
  }
5659
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
23,200✔
5660

5661
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
23,208✔
5662
  pInfo->pUpdated = NULL;
23,207✔
5663
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
23,207✔
5664
  QUERY_CHECK_CODE(code, lino, _end);
23,209!
5665

5666
  tSimpleHashCleanup(pInfo->pUpdatedMap);
23,209✔
5667
  pInfo->pUpdatedMap = NULL;
23,210✔
5668

5669
  code = buildIntervalResult(pOperator, ppRes);
23,210✔
5670
  QUERY_CHECK_CODE(code, lino, _end);
23,209!
5671

5672
  return code;
23,209✔
5673

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

5685
int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
3,031✔
5686
                                               SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
5687
                                               SOperatorInfo** pOptrInfo) {
5688
  QRY_PARAM_CHECK(pOptrInfo);
3,031!
5689

5690
  int32_t code = TSDB_CODE_SUCCESS;
3,031✔
5691
  int32_t lino = 0;
3,031✔
5692
  int32_t numOfCols = 0;
3,031✔
5693

5694
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
3,031!
5695
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3,034!
5696
  if (pInfo == NULL || pOperator == NULL) {
3,034!
5697
    code = terrno;
×
5698
    QUERY_CHECK_CODE(code, lino, _error);
×
5699
  }
5700

5701
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3,034✔
5702

5703
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3,034✔
5704
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
3,035!
5705
  initBasicInfo(&pInfo->binfo, pResBlock);
3,035✔
5706

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

5718
  pInfo->twAggSup =
3,034✔
5719
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
3,034✔
5720
                           .calTrigger = pIntervalPhyNode->window.triggerType,
3,035✔
5721
                           .maxTs = INT64_MIN,
5722
                           .minTs = INT64_MAX,
5723
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
3,035✔
5724

5725
  pOperator->pTaskInfo = pTaskInfo;
3,034✔
5726
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,034✔
5727

5728
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
3,034✔
5729
  pInfo->ignoreExpiredDataSaved = false;
3,034✔
5730

5731
  SExprSupp* pSup = &pOperator->exprSupp;
3,034✔
5732
  pSup->hasWindowOrGroup = true;
3,034✔
5733

5734
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
3,034✔
5735
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5736

5737
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
3,034✔
5738
  initResultSizeInfo(&pOperator->resultInfo, 4096);
3,034✔
5739

5740
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
3,035!
5741
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
3,034!
5742
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
3,034✔
5743
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
3,034✔
5744

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

5753
  if (pIntervalPhyNode->window.pExprs != NULL) {
3,034✔
5754
    int32_t    numOfScalar = 0;
1✔
5755
    SExprInfo* pScalarExprInfo = NULL;
1✔
5756

5757
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5758
    QUERY_CHECK_CODE(code, lino, _error);
1!
5759

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

5764
  pInfo->invertible = false;
3,034✔
5765
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
3,034✔
5766
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
3,035!
5767
  pInfo->delIndex = 0;
3,035✔
5768

5769
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
3,035✔
5770
  QUERY_CHECK_CODE(code, lino, _error);
3,035!
5771

5772
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
3,035✔
5773

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

5788
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
3,035✔
5789
  pInfo->pState->pFileState = NULL;
3,035✔
5790

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

5796
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
3,035✔
5797
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
3,035✔
5798
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
3,035✔
5799
      &pInfo->pState->pFileState);
3,035✔
5800
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5801

5802
  pInfo->pOperator = pOperator;
3,034✔
5803
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
3,034✔
5804
                  pInfo, pTaskInfo);
5805
  pOperator->fpSet =
5806
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
3,033✔
5807
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5808
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
3,032✔
5809

5810
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
3,034✔
5811
  QUERY_CHECK_CODE(code, lino, _error);
3,035!
5812

5813
  pInfo->recvGetAll = false;
3,035✔
5814

5815
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
3,035✔
5816
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5817

5818
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,034✔
5819
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
3,035✔
5820
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
3,035!
5821
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
3,035✔
5822

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

5833
  pInfo->basic.primaryPkIndex = -1;
3,035✔
5834
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
3,035✔
5835
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5836

5837
  code = appendDownstream(pOperator, &downstream, 1);
3,034✔
5838
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5839

5840
  *pOptrInfo = pOperator;
3,034✔
5841
  return TSDB_CODE_SUCCESS;
3,034✔
5842

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

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

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

5868
  int32_t     startPos = 0;
38✔
5869
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
38✔
5870
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
38✔
5871

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

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

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

5907
    pResult = (SResultRow*)pResPos->pRowBuff;
1,304✔
5908

5909
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,304!
5910
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,304✔
5911
      QUERY_CHECK_CODE(code, lino, _end);
1,304!
5912
    }
5913

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

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

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

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

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

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

5974
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
105✔
5975
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
105✔
5976
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
105✔
5977
  uint16_t                     opType = pOperator->operatorType;
105✔
5978

5979
  if (pInfo->recvPullover) {
105✔
5980
    pInfo->recvPullover = false;
6✔
5981
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5982
    return pInfo->pMidPulloverRes;
6✔
5983
  }
5984

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

5993
  if (pInfo->recvRetrive) {
99✔
5994
    pInfo->recvRetrive = false;
12✔
5995
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5996
    return pInfo->pMidRetriveRes;
12✔
5997
  }
5998

5999
  return NULL;
87✔
6000
}
6001

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

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

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

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

6040
    resBlock = buildMidIntervalResult(pOperator);
69✔
6041
    if (resBlock != NULL) {
69✔
6042
      (*ppRes) = resBlock;
4✔
6043
      return code;
4✔
6044
    }
6045

6046
    if (pInfo->clearState) {
65✔
6047
      pInfo->clearState = false;
18✔
6048
      clearFunctionContext(&pOperator->exprSupp);
18✔
6049
      clearStreamIntervalOperator(pInfo);
18✔
6050
    }
6051
  }
6052

6053
  if (!pInfo->pUpdated) {
65✔
6054
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
62✔
6055
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
62!
6056
  }
6057
  if (!pInfo->pUpdatedMap) {
65✔
6058
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
62✔
6059
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
62✔
6060
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
62!
6061
  }
6062

6063
  while (1) {
54✔
6064
    if (isTaskKilled(pTaskInfo)) {
119!
6065
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
6066
      (*ppRes) = NULL;
×
6067
      return code;
3✔
6068
    }
6069

6070
    SSDataBlock* pBlock = NULL;
119✔
6071
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
119✔
6072
    QUERY_CHECK_CODE(code, lino, _end);
119!
6073

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

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

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

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

6127
      if (pInfo->recvPullover) {
12✔
6128
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
6129
        QUERY_CHECK_CODE(code, lino, _end);
6!
6130

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

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

6151
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
6152
      QUERY_CHECK_CODE(code, lino, _end);
12!
6153

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

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

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

6182
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
62✔
6183
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
62✔
6184

6185
  void*   pIte = NULL;
62✔
6186
  int32_t iter = 0;
62✔
6187
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,266✔
6188
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,204✔
6189
    if (!tmp) {
1,204!
6190
      code = terrno;
×
6191
      QUERY_CHECK_CODE(code, lino, _end);
×
6192
    }
6193
  }
6194

6195
  tSimpleHashCleanup(pInfo->pUpdatedMap);
62✔
6196
  pInfo->pUpdatedMap = NULL;
62✔
6197
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
62✔
6198

6199
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
62✔
6200
  pInfo->pUpdated = NULL;
62✔
6201
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
62✔
6202
  QUERY_CHECK_CODE(code, lino, _end);
62!
6203

6204
  SSDataBlock* resBlock = NULL;
62✔
6205
  code = buildIntervalResult(pOperator, &resBlock);
62✔
6206
  QUERY_CHECK_CODE(code, lino, _end);
62!
6207
  if (resBlock != NULL) {
62✔
6208
    (*ppRes) = resBlock;
26✔
6209
    return code;
26✔
6210
  }
6211

6212
  resBlock = buildMidIntervalResult(pOperator);
36✔
6213
  if (resBlock != NULL) {
36✔
6214
    (*ppRes) = resBlock;
14✔
6215
    return code;
14✔
6216
  }
6217

6218
  if (pInfo->clearState) {
22!
6219
    pInfo->clearState = false;
×
6220
    clearFunctionContext(&pOperator->exprSupp);
×
6221
    clearStreamIntervalOperator(pInfo);
×
6222
  }
6223

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

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

6240
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
36,205✔
6241
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
36,205✔
6242
         getStreamOpName(pOperator->operatorType), pOperator->status);
6243
  setOperatorCompleted(pOperator);
36,205✔
6244
}
36,209✔
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