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

taosdata / TDengine / #3559

18 Dec 2024 12:59AM UTC coverage: 59.805% (+0.03%) from 59.778%
#3559

push

travis-ci

web-flow
Merge pull request #29187 from taosdata/merge/mainto3.0

merge: main to 3.0 branch

132705 of 287544 branches covered (46.15%)

Branch coverage included in aggregate %.

87 of 95 new or added lines in 19 files covered. (91.58%)

1132 existing lines in 133 files now uncovered.

209591 of 284807 relevant lines covered (73.59%)

8125235.78 hits per line

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

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

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

34
#define IS_FINAL_SESSION_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION)
35
#define IS_NORMAL_SESSION_OP(op)                                    \
36
  ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION || \
37
   (op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION)
38

39
#define IS_NORMAL_STATE_OP(op) ((op)->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE)
40

41
#define DEAULT_DELETE_MARK                 INT64_MAX
42
#define STREAM_INTERVAL_OP_STATE_NAME      "StreamIntervalHistoryState"
43
#define STREAM_SESSION_OP_STATE_NAME       "StreamSessionHistoryState"
44
#define STREAM_STATE_OP_STATE_NAME         "StreamStateHistoryState"
45
#define STREAM_INTERVAL_OP_CHECKPOINT_NAME "StreamIntervalOperator_Checkpoint"
46
#define STREAM_SESSION_OP_CHECKPOINT_NAME  "StreamSessionOperator_Checkpoint"
47
#define STREAM_STATE_OP_CHECKPOINT_NAME    "StreamStateOperator_Checkpoint"
48

49
#define MAX_STREAM_HISTORY_RESULT 20000000
50

51
typedef struct SStateWindowInfo {
52
  SResultWindowInfo winInfo;
53
  SStateKeys*       pStateKey;
54
} SStateWindowInfo;
55

56
typedef struct SPullWindowInfo {
57
  STimeWindow window;
58
  uint64_t    groupId;
59
  STimeWindow calWin;
60
} SPullWindowInfo;
61

62
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes);
63

64
typedef int32_t (*__compare_fn_t)(void* pKey, void* data, int32_t index);
65

66
static int32_t binarySearchCom(void* keyList, int num, void* pKey, int order, __compare_fn_t comparefn) {
1,566✔
67
  int firstPos = 0, lastPos = num - 1, midPos = -1;
1,566✔
68
  int numOfRows = 0;
1,566✔
69

70
  if (num <= 0) return -1;
1,566✔
71
  if (order == TSDB_ORDER_DESC) {
1,355!
72
    // find the first position which is smaller or equal than the key
73
    while (1) {
74
      if (comparefn(pKey, keyList, lastPos) >= 0) return lastPos;
1,437✔
75
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
336✔
76
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
209✔
77

78
      numOfRows = lastPos - firstPos + 1;
146✔
79
      midPos = (numOfRows >> 1) + firstPos;
146✔
80

81
      if (comparefn(pKey, keyList, midPos) < 0) {
146✔
82
        lastPos = midPos - 1;
50✔
83
      } else if (comparefn(pKey, keyList, midPos) > 0) {
96✔
84
        firstPos = midPos + 1;
32✔
85
      } else {
86
        break;
64✔
87
      }
88
    }
89

90
  } else {
91
    // find the first position which is bigger or equal than the key
92
    while (1) {
93
      if (comparefn(pKey, keyList, firstPos) <= 0) return firstPos;
×
94
      if (comparefn(pKey, keyList, lastPos) == 0) return lastPos;
×
95

96
      if (comparefn(pKey, keyList, lastPos) > 0) {
×
97
        lastPos = lastPos + 1;
×
98
        if (lastPos >= num)
×
99
          return -1;
×
100
        else
101
          return lastPos;
×
102
      }
103

104
      numOfRows = lastPos - firstPos + 1;
×
105
      midPos = (numOfRows >> 1) + firstPos;
×
106

107
      if (comparefn(pKey, keyList, midPos) < 0) {
×
108
        lastPos = midPos - 1;
×
109
      } else if (comparefn(pKey, keyList, midPos) > 0) {
×
110
        firstPos = midPos + 1;
×
111
      } else {
112
        break;
×
113
      }
114
    }
115
  }
116

117
  return midPos;
64✔
118
}
119

120
static int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
203✔
121
  SArray*          res = (SArray*)data;
203✔
122
  SPullWindowInfo* pos = taosArrayGet(res, index);
203✔
123
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
203✔
124
  if (pData->groupId > pos->groupId) {
203✔
125
    return 1;
89✔
126
  } else if (pData->groupId < pos->groupId) {
114✔
127
    return -1;
61✔
128
  }
129

130
  if (pData->window.skey > pos->window.ekey) {
53✔
131
    return 1;
40✔
132
  } else if (pData->window.ekey < pos->window.skey) {
13✔
133
    return -1;
7✔
134
  }
135
  return 0;
6✔
136
}
137

138
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
225✔
139
  int32_t size = taosArrayGetSize(pPullWins);
225✔
140
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
225✔
141
  if (index == -1) {
225✔
142
    index = 0;
172✔
143
  } else {
144
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
53✔
145
    if (code == 0) {
53✔
146
      SPullWindowInfo* pos = taosArrayGet(pPullWins, index);
3✔
147
      pos->window.skey = TMIN(pos->window.skey, pPullInfo->window.skey);
3✔
148
      pos->window.ekey = TMAX(pos->window.ekey, pPullInfo->window.ekey);
3✔
149
      pos->calWin.skey = TMIN(pos->calWin.skey, pPullInfo->calWin.skey);
3✔
150
      pos->calWin.ekey = TMAX(pos->calWin.ekey, pPullInfo->calWin.ekey);
3✔
151
      return TSDB_CODE_SUCCESS;
3✔
152
    } else if (code > 0) {
50!
153
      index++;
50✔
154
    }
155
  }
156
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
222!
157
    return terrno;
×
158
  }
159
  return TSDB_CODE_SUCCESS;
222✔
160
}
161

162
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
10,004✔
163
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
10,004!
164
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
165
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
166
  }
167
  winInfo.sessionWin.win.ekey = winInfo.sessionWin.win.skey;
10,005✔
168
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
10,005✔
169
}
170

171
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
11,823,167✔
172
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
11,823,167!
173
    qError("%s failed at line %d since too many history result. ", __func__, __LINE__);
×
174
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
175
  }
176
  return tSimpleHashPut(pUpdatedMap, pKey, sizeof(SWinKey), &pPos, POINTER_BYTES);
11,820,431✔
177
}
178

179
static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
316✔
180
  SWinKey key = {.ts = ts, .groupId = groupId};
316✔
181
  return saveWinResult(&key, pPos, pUpdatedMap);
316✔
182
}
183

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

198
static int32_t compareWinKey(void* pKey, void* data, int32_t index) {
3,320✔
199
  void* pDataPos = taosArrayGet((SArray*)data, index);
3,320✔
200
  return winKeyCmprImpl(pKey, pDataPos);
3,320✔
201
}
202

203
void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
27,933✔
204
  taosArraySort(pDelWins, winKeyCmprImpl);
27,933✔
205
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
27,933✔
206
  int32_t delSize = taosArrayGetSize(pDelWins);
27,933✔
207
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
27,933✔
208
    return;
27,316✔
209
  }
210
  void*   pIte = NULL;
617✔
211
  int32_t iter = 0;
617✔
212
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
1,681✔
213
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
1,064✔
214
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
1,064✔
215
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
1,064✔
216
      taosArrayRemove(pDelWins, index);
884✔
217
      delSize = taosArrayGetSize(pDelWins);
884✔
218
    }
219
  }
220
}
221

222
bool isOverdue(TSKEY ekey, STimeWindowAggSupp* pTwSup) {
93,929,294✔
223
  return pTwSup->maxTs != INT64_MIN && ekey < pTwSup->maxTs - pTwSup->waterMark;
93,929,294✔
224
}
225

226
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
42,347,114✔
227

228
static void doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) {
3,570✔
229
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,570✔
230

231
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
3,570✔
232
  SWinKey                      key = {.ts = ts, .groupId = groupId};
3,570✔
233
  int32_t                      tmpRes = tSimpleHashRemove(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey));
3,570✔
234
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,570✔
235
  pAPI->stateStore.streamStateDel(pInfo->pState, &key);
3,570✔
236
}
3,570✔
237

238
static int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
1,485✔
239

240
static int32_t doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins,
2,430✔
241
                               SSHashObj* pUpdatedMap, SHashObj* pInvalidWins) {
242
  int32_t                      code = TSDB_CODE_SUCCESS;
2,430✔
243
  int32_t                      lino = 0;
2,430✔
244
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
2,430✔
245
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2,430✔
246
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,430✔
247
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
2,430✔
248
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,430✔
249
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
2,430✔
250
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
2,430✔
251
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
2,431✔
252
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
2,431✔
253
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
2,431✔
254
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,431✔
255
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
2,430✔
256
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5,164✔
257
    SResultRowInfo dumyInfo = {0};
2,733✔
258
    dumyInfo.cur.pageId = -1;
2,733✔
259

260
    STimeWindow win = {0};
2,733✔
261
    if (IS_FINAL_INTERVAL_OP(pOperator) || IS_MID_INTERVAL_OP(pOperator)) {
2,733✔
262
      win.skey = startTsCols[i];
261✔
263
      win.ekey = endTsCols[i];
261✔
264
    } else {
265
      win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC);
2,472✔
266
    }
267

268
    do {
269
      if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i], pBlock->info.type)) {
3,623✔
270
        getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
26✔
271
        continue;
80✔
272
      }
273
      uint64_t winGpId = pGpDatas[i];
3,597✔
274
      SWinKey  winRes = {.ts = win.skey, .groupId = winGpId};
3,597✔
275
      void*    chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
3,597✔
276
      if (chIds) {
3,598✔
277
        int32_t childId = getChildIndex(pBlock);
54✔
278
        if (pInvalidWins) {
54✔
279
          qDebug("===stream===save invalid delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d", winRes.ts,
48!
280
                 winRes.groupId, childId);
281
          code = taosHashPut(pInvalidWins, &winRes, sizeof(SWinKey), NULL, 0);
48✔
282
          QUERY_CHECK_CODE(code, lino, _end);
48!
283
        }
284

285
        SArray* chArray = *(void**)chIds;
54✔
286
        int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
54✔
287
        if (index != -1) {
54!
288
          qDebug("===stream===try push delete window:%" PRId64 ",groupId:%" PRId64 ",chId:%d ,continue", win.skey,
54!
289
                 winGpId, childId);
290
          getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
54✔
291
          continue;
54✔
292
        }
293
      }
294
      doDeleteWindow(pOperator, win.skey, winGpId);
3,544✔
295
      if (pUpWins) {
3,543✔
296
        void* tmp = taosArrayPush(pUpWins, &winRes);
2,763✔
297
        if (!tmp) {
2,763!
298
          code = terrno;
×
299
          QUERY_CHECK_CODE(code, lino, _end);
×
300
        }
301
      }
302
      if (pUpdatedMap) {
3,542!
303
        int32_t tmpRes = tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey));
3,543✔
304
        qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
3,544✔
305
      }
306
      getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
3,543✔
307
    } while (win.ekey <= endTsCols[i]);
3,624✔
308
  }
309
_end:
2,431✔
310
  if (code != TSDB_CODE_SUCCESS) {
2,431!
311
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
312
  }
313
  return code;
2,431✔
314
}
315

316
static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) {
1,126✔
317
  void*   pIte = NULL;
1,126✔
318
  int32_t iter = 0;
1,126✔
319
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1,484✔
320
    SWinKey*     pKey = tSimpleHashGetKey(pIte, NULL);
358✔
321
    uint64_t     groupId = pKey->groupId;
358✔
322
    TSKEY        ts = pKey->ts;
358✔
323
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
358✔
324
    if (!pPos->beUpdated) {
358✔
325
      continue;
42✔
326
    }
327
    pPos->beUpdated = false;
316✔
328
    int32_t code = saveWinResultInfo(ts, groupId, pPos, resWins);
316✔
329
    if (code != TSDB_CODE_SUCCESS) {
316!
330
      return code;
×
331
    }
332
  }
333
  return TSDB_CODE_SUCCESS;
1,126✔
334
}
335

336
static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval,
26,787✔
337
                                         SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins,
338
                                         SOperatorInfo* pOperator) {
339
  qDebug("===stream===close interval window");
26,787✔
340
  int32_t                      code = TSDB_CODE_SUCCESS;
26,787✔
341
  int32_t                      lino = 0;
26,787✔
342
  void*                        pIte = NULL;
26,787✔
343
  int32_t                      iter = 0;
26,787✔
344
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
26,787✔
345
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
26,787✔
346
  int32_t                      delSize = taosArrayGetSize(pDelWins);
26,787✔
347
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
32,102✔
348
    void*    key = tSimpleHashGetKey(pIte, NULL);
5,316!
349
    SWinKey* pWinKey = (SWinKey*)key;
5,316✔
350
    if (delSize > 0) {
5,316✔
351
      int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey);
277✔
352
      if (index >= 0 && 0 == compareWinKey(pWinKey, pDelWins, index)) {
277✔
353
        taosArrayRemove(pDelWins, index);
128✔
354
        delSize = taosArrayGetSize(pDelWins);
128✔
355
      }
356
    }
357

358
    void*       chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey));
5,316✔
359
    STimeWindow win = {
10,630✔
360
        .skey = pWinKey->ts,
5,315✔
361
        .ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1,
5,315✔
362
    };
363
    if (isCloseWindow(&win, pTwSup)) {
5,315✔
364
      if (chIds && pPullDataMap) {
1,619!
365
        SArray* chAy = *(SArray**)chIds;
×
366
        int32_t size = taosArrayGetSize(chAy);
×
367
        qDebug("===stream===window %" PRId64 " wait child size:%d", pWinKey->ts, size);
×
368
        for (int32_t i = 0; i < size; i++) {
×
369
          qDebug("===stream===window %" PRId64 " wait child id:%d", pWinKey->ts, *(int32_t*)taosArrayGet(chAy, i));
×
370
        }
371
        continue;
×
372
      } else if (pPullDataMap) {
1,619✔
373
        qDebug("===stream===close window %" PRId64, pWinKey->ts);
92✔
374
      }
375

376
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,619!
377
        code = saveWinResult(pWinKey, *(SRowBuffPos**)pIte, closeWins);
1,619✔
378
        QUERY_CHECK_CODE(code, lino, _end);
1,620!
379
      }
380
      int32_t tmpRes = tSimpleHashIterateRemove(pHashMap, pWinKey, sizeof(SWinKey), &pIte, &iter);
1,620✔
381
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,620✔
382
    }
383
  }
384

385
_end:
26,784✔
386
  if (code != TSDB_CODE_SUCCESS) {
26,784!
387
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
388
  }
389
  return code;
26,785✔
390
}
391

392
STimeWindow getFinalTimeWindow(int64_t ts, SInterval* pInterval) {
243,923✔
393
  STimeWindow w = {.skey = ts, .ekey = INT64_MAX};
243,923✔
394
  w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1;
243,923✔
395
  return w;
243,923✔
396
}
397

398
static void doBuildDeleteResult(SStreamIntervalOperatorInfo* pInfo, SArray* pWins, int32_t* index,
165,746✔
399
                                SSDataBlock* pBlock) {
400
  doBuildDeleteResultImpl(&pInfo->stateStore, pInfo->pState, pWins, index, pBlock);
165,746✔
401
}
165,744✔
402

403
void doBuildDeleteResultImpl(SStateStore* pAPI, SStreamState* pState, SArray* pWins, int32_t* index,
166,976✔
404
                             SSDataBlock* pBlock) {
405
  int32_t code = TSDB_CODE_SUCCESS;
166,976✔
406
  int32_t lino = 0;
166,976✔
407
  blockDataCleanup(pBlock);
166,976✔
408
  int32_t size = taosArrayGetSize(pWins);
166,975✔
409
  if (*index == size) {
166,975✔
410
    *index = 0;
166,228✔
411
    taosArrayClear(pWins);
166,228✔
412
    goto _end;
166,228✔
413
  }
414
  code = blockDataEnsureCapacity(pBlock, size - *index);
747✔
415
  QUERY_CHECK_CODE(code, lino, _end);
747!
416

417
  uint64_t uid = 0;
747✔
418
  for (int32_t i = *index; i < size; i++) {
2,334✔
419
    SWinKey* pWin = taosArrayGet(pWins, i);
1,586✔
420
    void*    tbname = NULL;
1,586✔
421
    int32_t  winCode = TSDB_CODE_SUCCESS;
1,586✔
422
    code = pAPI->streamStateGetParName(pState, pWin->groupId, &tbname, false, &winCode);
1,586✔
423
    QUERY_CHECK_CODE(code, lino, _end);
1,587!
424

425
    if (winCode != TSDB_CODE_SUCCESS) {
1,587✔
426
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, NULL);
1,079✔
427
      QUERY_CHECK_CODE(code, lino, _end);
1,079!
428
    } else {
429
      QUERY_CHECK_CONDITION((tbname), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
508!
430
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
431
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
508✔
432
      code = appendDataToSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, parTbName);
508✔
433
      QUERY_CHECK_CODE(code, lino, _end);
507!
434
    }
435
    pAPI->streamStateFreeVal(tbname);
1,586✔
436
    (*index)++;
1,587✔
437
  }
438

439
_end:
748✔
440
  if (code != TSDB_CODE_SUCCESS) {
166,976!
441
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
442
  }
443
}
166,976✔
444

445
void destroyFlusedPos(void* pRes) {
1,026,511✔
446
  SRowBuffPos* pPos = (SRowBuffPos*)pRes;
1,026,511✔
447
  if (!pPos->needFree && !pPos->pRowBuff) {
1,026,511!
448
    taosMemoryFreeClear(pPos->pKey);
482,796!
449
    taosMemoryFree(pPos);
482,796!
450
  }
451
}
1,026,511✔
452

453
void destroyFlusedppPos(void* ppRes) {
×
454
  void* pRes = *(void**)ppRes;
×
455
  destroyFlusedPos(pRes);
×
456
}
×
457

458
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
6,055✔
459
  if (pGroupResInfo->freeItem) {
6,055✔
460
    int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
3,570✔
461
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
1,030,081✔
462
      void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
1,026,511✔
463
      destroyFlusedPos(pPos);
1,026,511✔
464
    }
465
    pGroupResInfo->freeItem = false;
3,570✔
466
  }
467
  taosArrayDestroy(pGroupResInfo->pRows);
6,055✔
468
  pGroupResInfo->pRows = NULL;
6,056✔
469
  pGroupResInfo->index = 0;
6,056✔
470
}
6,056✔
471

472
void destroyStreamFinalIntervalOperatorInfo(void* param) {
3,862✔
473
  if (param == NULL) {
3,862!
474
    return;
×
475
  }
476
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)param;
3,862✔
477
  cleanupBasicInfo(&pInfo->binfo);
3,862✔
478
  if (pInfo->pOperator) {
3,863✔
479
    cleanupResultInfo(pInfo->pOperator->pTaskInfo, &pInfo->pOperator->exprSupp, &pInfo->groupResInfo, &pInfo->aggSup,
3,862✔
480
                      false);
481
    pInfo->pOperator = NULL;
3,863✔
482
  }
483
  cleanupAggSup(&pInfo->aggSup);
3,864✔
484
  clearGroupResInfo(&pInfo->groupResInfo);
3,863✔
485
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
3,863✔
486
  pInfo->pUpdated = NULL;
3,863✔
487

488
  // it should be empty.
489
  void* pIte = NULL;
3,863✔
490
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
3,863!
491
    taosArrayDestroy(*(void**)pIte);
×
492
  }
493
  taosHashCleanup(pInfo->pPullDataMap);
3,863✔
494
  taosHashCleanup(pInfo->pFinalPullDataMap);
3,863✔
495
  taosArrayDestroy(pInfo->pPullWins);
3,863✔
496
  blockDataDestroy(pInfo->pPullDataRes);
3,863✔
497
  taosArrayDestroy(pInfo->pDelWins);
3,863✔
498
  blockDataDestroy(pInfo->pDelRes);
3,863✔
499
  blockDataDestroy(pInfo->pMidRetriveRes);
3,863✔
500
  blockDataDestroy(pInfo->pMidPulloverRes);
3,863✔
501
  if (pInfo->pUpdatedMap != NULL) {
3,863!
502
    // free flushed pos
503
    tSimpleHashSetFreeFp(pInfo->pUpdatedMap, destroyFlusedppPos);
×
504
    tSimpleHashCleanup(pInfo->pUpdatedMap);
×
505
    pInfo->pUpdatedMap = NULL;
×
506
  }
507

508
  if (pInfo->stateStore.streamFileStateDestroy != NULL) {
3,863!
509
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
3,863✔
510
  }
511
  taosArrayDestroy(pInfo->pMidPullDatas);
3,863✔
512

513
  if (pInfo->pState != NULL && pInfo->pState->dump == 1) {
3,863!
514
    taosMemoryFreeClear(pInfo->pState->pTdbState->pOwner);
914!
515
    taosMemoryFreeClear(pInfo->pState->pTdbState);
914!
516
  }
517
  taosMemoryFreeClear(pInfo->pState);
3,863!
518

519
  nodesDestroyNode((SNode*)pInfo->pPhyNode);
3,863✔
520
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
3,863✔
521
  cleanupExprSupp(&pInfo->scalarSupp);
3,863✔
522
  tSimpleHashCleanup(pInfo->pDeletedMap);
3,863✔
523

524
  blockDataDestroy(pInfo->pCheckpointRes);
3,863✔
525

526
  taosMemoryFreeClear(param);
3,863!
527
}
528

529
#ifdef BUILD_NO_CALL
530
static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
531
  for (int32_t i = 0; i < numOfCols; i++) {
532
    if (fmIsUserDefinedFunc(pFCtx[i].functionId) || !fmIsInvertible(pFCtx[i].functionId)) {
533
      return false;
534
    }
535
  }
536
  return true;
537
}
538
#endif
539

540
void reloadFromDownStream(SOperatorInfo* downstream, SStreamIntervalOperatorInfo* pInfo) {
1,360✔
541
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
1,360✔
542

543
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
1,360✔
544
    reloadFromDownStream(downstream->pDownstream[0], pInfo);
64✔
545
    return;
64✔
546
  }
547

548
  SStreamScanInfo* pScanInfo = downstream->info;
1,296✔
549
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
1,296✔
550
}
551

552
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
13,011,463✔
553

554
int32_t initIntervalDownStream(SOperatorInfo* downstream, uint16_t type, SStreamIntervalOperatorInfo* pInfo,
3,989✔
555
                               struct SSteamOpBasicInfo* pBasic) {
556
  int32_t        code = TSDB_CODE_SUCCESS;
3,989✔
557
  int32_t        lino = 0;
3,989✔
558
  SStateStore*   pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
3,989✔
559
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
3,989✔
560

561
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
3,989✔
562
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
249✔
563
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
249✔
564
  }
565

566
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
3,989✔
567
    return initIntervalDownStream(downstream->pDownstream[0], type, pInfo, pBasic);
249✔
568
  }
569

570
  SStreamScanInfo* pScanInfo = downstream->info;
3,740✔
571
  pScanInfo->windowSup.parentType = type;
3,740✔
572
  pScanInfo->windowSup.pIntervalAggSup = &pInfo->aggSup;
3,740✔
573
  if (!pScanInfo->pUpdateInfo) {
3,740✔
574
    code = pAPI->updateInfoInitP(&pInfo->interval, pInfo->twAggSup.waterMark, pScanInfo->igCheckUpdate,
3,483✔
575
                                 pScanInfo->pkColType, pScanInfo->pkColLen, &pScanInfo->pUpdateInfo);
3,483✔
576
    QUERY_CHECK_CODE(code, lino, _end);
3,483!
577
  }
578

579
  pScanInfo->interval = pInfo->interval;
3,740✔
580
  pScanInfo->twAggSup = pInfo->twAggSup;
3,740✔
581
  pScanInfo->pState = pInfo->pState;
3,740✔
582
  pInfo->pUpdateInfo = pScanInfo->pUpdateInfo;
3,740✔
583
  if (!hasSrcPrimaryKeyCol(pBasic)) {
3,740!
584
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
3,740✔
585
  }
586

587
_end:
×
588
  if (code != TSDB_CODE_SUCCESS) {
3,740!
589
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
590
  }
591
  return code;
3,740✔
592
}
593

594
int32_t compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t numOfOutput,
46✔
595
                         SExecTaskInfo* pTaskInfo, SColumnInfoData* pTimeWindowData) {
596
  int32_t code = TSDB_CODE_SUCCESS;
46✔
597
  int32_t lino = 0;
46✔
598
  for (int32_t k = 0; k < numOfOutput; ++k) {
231✔
599
    if (fmIsWindowPseudoColumnFunc(pDestCtx[k].functionId)) {
187✔
600
      if (!pTimeWindowData) {
50!
601
        continue;
×
602
      }
603

604
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pDestCtx[k]);
50✔
605
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
50✔
606
      SColumnInfoData      idata = {0};
50✔
607
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
50✔
608
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
50✔
609
      idata.pData = p;
50✔
610

611
      SScalarParam out = {.columnData = &idata};
50✔
612
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
50✔
613
      code = pDestCtx[k].sfp.process(&tw, 1, &out);
50✔
614
      QUERY_CHECK_CODE(code, lino, _end);
50!
615

616
      pEntryInfo->numOfRes = 1;
50✔
617
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
137!
618
      code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
135✔
619
      QUERY_CHECK_CODE(code, lino, _end);
135!
620
    } else if (pDestCtx[k].fpSet.combine == NULL) {
2!
621
      char* funName = fmGetFuncName(pDestCtx[k].functionId);
2✔
622
      qError("%s error, combine funcion for %s is not implemented", GET_TASKID(pTaskInfo), funName);
2!
623
      taosMemoryFreeClear(funName);
2!
624
      code = TSDB_CODE_FAILED;
2✔
625
      QUERY_CHECK_CODE(code, lino, _end);
2!
626
    }
627
  }
628

629
_end:
44✔
630
  if (code != TSDB_CODE_SUCCESS) {
46✔
631
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
632
  }
633
  return code;
46✔
634
}
635

636
bool hasIntervalWindow(void* pState, SWinKey* pKey, SStateStore* pStore) {
26✔
637
  return pStore->streamStateCheck(pState, pKey);
26✔
638
}
639

640
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
11,805,071✔
641
                             SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset,
642
                             SAggSupporter* pAggSup, SStateStore* pStore, int32_t* pWinCode) {
643
  int32_t code = TSDB_CODE_SUCCESS;
11,805,071✔
644
  int32_t lino = 0;
11,805,071✔
645
  SWinKey key = {.ts = win->skey, .groupId = groupId};
11,805,071✔
646
  char*   value = NULL;
11,805,071✔
647
  int32_t size = pAggSup->resultRowSize;
11,805,071✔
648

649
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
11,805,071✔
650
  QUERY_CHECK_CODE(code, lino, _end);
11,823,659!
651

652
  *pResult = (SRowBuffPos*)value;
11,823,659✔
653
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
11,823,659✔
654

655
  // set time window for current result
656
  res->win = (*win);
11,823,659✔
657
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
11,823,659✔
658
  QUERY_CHECK_CODE(code, lino, _end);
11,752,337!
659

660
_end:
11,752,337✔
661
  if (code != TSDB_CODE_SUCCESS) {
11,752,337!
662
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
663
  }
664
  return code;
11,753,221✔
665
}
666

667
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
29,858,505✔
668
                           SStateStore* pStore) {
669
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
29,858,505✔
670
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
26✔
671
    if (!hasIntervalWindow(pState, &key, pStore)) {
26✔
672
      return true;
14✔
673
    }
674
    return false;
12✔
675
  }
676
  return false;
29,858,479✔
677
}
678

679
int32_t getNexWindowPos(SInterval* pInterval, SDataBlockInfo* pBlockInfo, TSKEY* tsCols, int32_t startPos, TSKEY eKey,
45✔
680
                        STimeWindow* pNextWin) {
681
  int32_t forwardRows =
682
      getNumOfRowsInTimeWindow(pBlockInfo, tsCols, startPos, eKey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
45✔
683
  int32_t prevEndPos = forwardRows - 1 + startPos;
45✔
684
  return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
45✔
685
}
686

687
int32_t addPullWindow(SHashObj* pMap, SWinKey* pWinRes, int32_t size) {
231✔
688
  int32_t code = TSDB_CODE_SUCCESS;
231✔
689
  int32_t lino = 0;
231✔
690
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
231✔
691
  QUERY_CHECK_NULL(childIds, code, lino, _end, terrno);
231!
692
  for (int32_t i = 0; i < size; i++) {
999✔
693
    void* tmp = taosArrayPush(childIds, &i);
768✔
694
    if (!tmp) {
768!
695
      code = terrno;
×
696
      QUERY_CHECK_CODE(code, lino, _end);
×
697
    }
698
  }
699
  code = taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
231✔
700
  QUERY_CHECK_CODE(code, lino, _end);
231!
701
_end:
231✔
702
  if (code != TSDB_CODE_SUCCESS) {
231!
703
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
704
  }
705
  return code;
231✔
706
}
707

708
static void clearStreamIntervalOperator(SStreamIntervalOperatorInfo* pInfo) {
2,243✔
709
  tSimpleHashClear(pInfo->aggSup.pResultRowHashTable);
2,243✔
710
  clearDiskbasedBuf(pInfo->aggSup.pResultBuf);
2,243✔
711
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2,243✔
712
  pInfo->aggSup.currentPageId = -1;
2,243✔
713
  pInfo->stateStore.streamStateClear(pInfo->pState);
2,243✔
714
}
2,243✔
715

716
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
3,865✔
717
  if (pBlock->info.rows <= 0) {
3,865✔
718
    return;
3,705✔
719
  }
720
  blockDataCleanup(pBlock);
160✔
721
}
722

723
static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
3,865✔
724
  int32_t code = TSDB_CODE_SUCCESS;
3,865✔
725
  int32_t lino = 0;
3,865✔
726
  clearSpecialDataBlock(pBlock);
3,865✔
727
  int32_t size = taosArrayGetSize(array);
3,865✔
728
  if (size - (*pIndex) == 0) {
3,865✔
729
    goto _end;
3,705✔
730
  }
731
  code = blockDataEnsureCapacity(pBlock, size - (*pIndex));
160✔
732
  QUERY_CHECK_CODE(code, lino, _end);
160!
733

734
  SColumnInfoData* pStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
160✔
735
  SColumnInfoData* pEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
160✔
736
  SColumnInfoData* pGroupId = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
160✔
737
  SColumnInfoData* pCalStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
160✔
738
  SColumnInfoData* pCalEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
160✔
739
  SColumnInfoData* pTbName = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
160✔
740
  SColumnInfoData* pPrimaryKey = NULL;
160✔
741
  if (taosArrayGetSize(pBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
160!
742
    pPrimaryKey = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
743
  }
744
  for (; (*pIndex) < size; (*pIndex)++) {
382✔
745
    SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
222✔
746
    code = colDataSetVal(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false);
222✔
747
    QUERY_CHECK_CODE(code, lino, _end);
222!
748

749
    code = colDataSetVal(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false);
222✔
750
    QUERY_CHECK_CODE(code, lino, _end);
222!
751

752
    code = colDataSetVal(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false);
222✔
753
    QUERY_CHECK_CODE(code, lino, _end);
222!
754

755
    code = colDataSetVal(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false);
222✔
756
    QUERY_CHECK_CODE(code, lino, _end);
222!
757

758
    code = colDataSetVal(pCalEndTs, pBlock->info.rows, (const char*)&pWin->calWin.ekey, false);
222✔
759
    QUERY_CHECK_CODE(code, lino, _end);
222!
760

761
    colDataSetNULL(pTbName, pBlock->info.rows);
222!
762
    if (pPrimaryKey != NULL) {
222!
763
      colDataSetNULL(pPrimaryKey, pBlock->info.rows);
×
764
    }
765

766
    pBlock->info.rows++;
222✔
767
  }
768
  if ((*pIndex) == size) {
160!
769
    *pIndex = 0;
160✔
770
    taosArrayClear(array);
160✔
771
  }
772
  code = blockDataUpdateTsWindow(pBlock, 0);
160✔
773
  QUERY_CHECK_CODE(code, lino, _end);
160!
774

775
_end:
160✔
776
  if (code != TSDB_CODE_SUCCESS) {
3,865!
777
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
778
  }
779
}
3,865✔
780

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

813
            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
231✔
814
            if (pFinalCh) {
231✔
815
              int32_t tmpRes = taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
27✔
816
              qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
27!
817
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
27✔
818
              STimeWindow     nextWin = getFinalTimeWindow(winRes.ts, pInterval);
27✔
819
              SPullWindowInfo pull = {.window = nextWin,
27✔
820
                                      .groupId = winRes.groupId,
27✔
821
                                      .calWin.skey = nextWin.skey,
27✔
822
                                      .calWin.ekey = nextWin.skey};
27✔
823
              // add pull data request
824
              qDebug("===stream===prepare final retrive for delete window:%" PRId64 ",groupId:%" PRId64 ", size:%d",
27!
825
                     winRes.ts, winRes.groupId, numOfCh);
826
              if (IS_MID_INTERVAL_OP(pOperator)) {
27!
827
                SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
×
828

829
                void* tmp = taosArrayPush(pInfo->pMidPullDatas, &winRes);
×
830
                if (!tmp) {
×
831
                  code = terrno;
×
832
                  QUERY_CHECK_CODE(code, lino, _end);
×
833
                }
834
              } else if (savePullWindow(&pull, pPullWins) == TSDB_CODE_SUCCESS) {
27!
835
                void* tmp = taosArrayPush(pInfo->pDelWins, &winRes);
27✔
836
                if (!tmp) {
27!
837
                  code = terrno;
×
838
                  QUERY_CHECK_CODE(code, lino, _end);
×
839
                }
840

841
                code = addPullWindow(pMap, &winRes, numOfCh);
27✔
842
                QUERY_CHECK_CODE(code, lino, _end);
27!
843

844
                if (pInfo->destHasPrimaryKey) {
27!
845
                  code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
846
                  QUERY_CHECK_CODE(code, lino, _end);
×
847
                }
848
                qDebug("===stream===prepare final retrive for delete %" PRId64 ", size:%d", winRes.ts, numOfCh);
27!
849
              }
850
            }
851
          }
852
        }
853
      }
854
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision, NULL);
768✔
855
    }
856
  }
857
  if (pBeOver) {
539✔
858
    *pBeOver = res;
12✔
859
  }
860

861
_end:
527✔
862
  if (code != TSDB_CODE_SUCCESS) {
539!
863
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
864
  }
865
  return code;
539✔
866
}
867

868
static int32_t addRetriveWindow(SArray* wins, SStreamIntervalOperatorInfo* pInfo, int32_t childId) {
204✔
869
  int32_t code = TSDB_CODE_SUCCESS;
204✔
870
  int32_t lino = 0;
204✔
871
  int32_t size = taosArrayGetSize(wins);
204✔
872
  for (int32_t i = 0; i < size; i++) {
402✔
873
    SWinKey*    winKey = taosArrayGet(wins, i);
198✔
874
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
198✔
875
    void*       chIds = taosHashGet(pInfo->pPullDataMap, winKey, sizeof(SWinKey));
198✔
876
    if (!chIds) {
198!
877
      SPullWindowInfo pull = {
198✔
878
          .window = nextWin, .groupId = winKey->groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
198✔
879
      // add pull data request
880
      if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
198!
881
        code = addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
198✔
882
        QUERY_CHECK_CODE(code, lino, _end);
198!
883

884
        if (pInfo->destHasPrimaryKey) {
198!
885
          code = tSimpleHashPut(pInfo->pDeletedMap, winKey, sizeof(SWinKey), NULL, 0);
×
886
          QUERY_CHECK_CODE(code, lino, _end);
×
887
        }
888
        qDebug("===stream===prepare retrive for delete %" PRId64 ", size:%d", winKey->ts, pInfo->numOfChild);
198✔
889
      }
890
    } else {
891
      SArray* chArray = *(void**)chIds;
×
892
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
×
893
      qDebug("===stream===check final retrive %" PRId64 ",chid:%d", winKey->ts, index);
×
894
      if (index == -1) {
×
895
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
×
896
        code = taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
×
897
        QUERY_CHECK_CODE(code, lino, _end);
×
898
      }
899
    }
900
  }
901

902
_end:
204✔
903
  if (code != TSDB_CODE_SUCCESS) {
204!
904
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
905
  }
906
  return code;
204✔
907
}
908

909
static void clearFunctionContext(SExprSupp* pSup) {
2,830✔
910
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
28,965✔
911
    pSup->pCtx[i].saveHandle.currentPage = -1;
26,135✔
912
  }
913
}
2,830✔
914

915
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
10,419,942✔
916
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
10,419,942✔
917
}
918

919
void buildDataBlockFromGroupRes(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
127,560✔
920
                                SGroupResInfo* pGroupResInfo) {
921
  int32_t         code = TSDB_CODE_SUCCESS;
127,560✔
922
  int32_t         lino = 0;
127,560✔
923
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
127,560✔
924
  SStorageAPI*    pAPI = &pOperator->pTaskInfo->storageAPI;
127,560✔
925
  SExprInfo*      pExprInfo = pSup->pExprInfo;
127,560✔
926
  int32_t         numOfExprs = pSup->numOfExprs;
127,560✔
927
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
127,560✔
928
  SqlFunctionCtx* pCtx = pSup->pCtx;
127,560✔
929

930
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
127,560✔
931

932
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
10,436,693✔
933
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
10,420,106✔
934
    SResultRow*  pRow = NULL;
10,420,058✔
935
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
10,420,058✔
936
    QUERY_CHECK_CODE(code, lino, _end);
10,419,220!
937
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
10,419,220✔
938
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
10,419,220✔
939
    // no results, continue to check the next one
940
    if (pRow->numOfRows == 0) {
10,418,532!
941
      pGroupResInfo->index += 1;
×
942
      continue;
×
943
    }
944
    if (pBlock->info.id.groupId == 0) {
10,418,532✔
945
      pBlock->info.id.groupId = groupId;
563,024✔
946
      void*   tbname = NULL;
563,024✔
947
      int32_t winCode = TSDB_CODE_SUCCESS;
563,024✔
948
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
563,024✔
949
                                                    false, &winCode);
950
      QUERY_CHECK_CODE(code, lino, _end);
563,616!
951
      if (winCode != TSDB_CODE_SUCCESS) {
563,616✔
952
        pBlock->info.parTbName[0] = 0;
558,312✔
953
      } else {
954
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
5,304✔
955
      }
956
      pAPI->stateStore.streamStateFreeVal(tbname);
563,616✔
957
    } else {
958
      // current value belongs to different group, it can't be packed into one datablock
959
      if (pBlock->info.id.groupId != groupId) {
9,855,508✔
960
        break;
109,213✔
961
      }
962
    }
963

964
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
10,311,091✔
965
      break;
1,186✔
966
    }
967
    pGroupResInfo->index += 1;
10,309,905✔
968

969
    for (int32_t j = 0; j < numOfExprs; ++j) {
75,704,616✔
970
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
65,395,483✔
971

972
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
65,395,483✔
973

974
      if (pCtx[j].fpSet.finalize) {
65,390,442✔
975
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
43,437,913✔
976
        if (TAOS_FAILED(tmpRes)) {
43,449,509!
977
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
978
          QUERY_CHECK_CODE(code, lino, _end);
772!
979
        }
980
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
21,952,529✔
981
        // do nothing, todo refactor
982
      } else {
983
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
984
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
985
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
21,906,617✔
986
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
21,901,724✔
987
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
43,800,532✔
988
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
21,902,014✔
989
          QUERY_CHECK_CODE(code, lino, _end);
21,898,808!
990
        }
991
      }
992
    }
993

994
    pBlock->info.rows += pRow->numOfRows;
10,309,133✔
995
  }
996

997
  pBlock->info.dataLoad = 1;
125,800✔
998
  code = blockDataUpdateTsWindow(pBlock, 0);
125,800✔
999
  QUERY_CHECK_CODE(code, lino, _end);
127,560!
1000

1001
_end:
127,560✔
1002
  if (code != TSDB_CODE_SUCCESS) {
127,560!
1003
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1004
  }
1005
}
127,560✔
1006

1007
void doBuildStreamIntervalResult(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock,
166,124✔
1008
                                 SGroupResInfo* pGroupResInfo) {
1009
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
166,124✔
1010
  // set output datablock version
1011
  pBlock->info.version = pTaskInfo->version;
166,124✔
1012

1013
  blockDataCleanup(pBlock);
166,124✔
1014
  if (!hasRemainResults(pGroupResInfo)) {
166,125✔
1015
    return;
38,569✔
1016
  }
1017

1018
  // clear the existed group id
1019
  pBlock->info.id.groupId = 0;
127,560✔
1020
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
127,560✔
1021
}
1022

1023
static int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
243,698✔
1024
                                           TSKEY* primaryKeys, int32_t prevPosition) {
1025
  int32_t startPos = prevPosition + 1;
243,698✔
1026
  if (startPos == pDataBlockInfo->rows) {
243,698✔
1027
    startPos = -1;
2,454✔
1028
  } else {
1029
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
241,244✔
1030
  }
1031
  return startPos;
243,698✔
1032
}
1033

1034
static int32_t doStreamIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, uint64_t groupId,
1,195,032✔
1035
                                       SSHashObj* pUpdatedMap, SSHashObj* pDeletedMap) {
1036
  int32_t                      code = TSDB_CODE_SUCCESS;
1,195,032✔
1037
  int32_t                      lino = 0;
1,195,032✔
1038
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
1,195,032✔
1039
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
1,195,032✔
1040

1041
  SResultRowInfo* pResultRowInfo = &(pInfo->binfo.resultRowInfo);
1,195,032✔
1042
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
1,195,032✔
1043
  SExprSupp*      pSup = &pOperator->exprSupp;
1,195,032✔
1044
  int32_t         numOfOutput = pSup->numOfExprs;
1,195,032✔
1045
  int32_t         step = 1;
1,195,032✔
1046
  TSKEY*          tsCols = NULL;
1,195,032✔
1047
  SRowBuffPos*    pResPos = NULL;
1,195,032✔
1048
  SResultRow*     pResult = NULL;
1,195,032✔
1049
  int32_t         forwardRows = 0;
1,195,032✔
1050
  int32_t         endRowId = pSDataBlock->info.rows - 1;
1,195,032✔
1051

1052
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,195,032✔
1053
  tsCols = (int64_t*)pColDataInfo->pData;
1,194,827✔
1054

1055
  void*            pPkVal = NULL;
1,194,827✔
1056
  int32_t          pkLen = 0;
1,194,827✔
1057
  SColumnInfoData* pPkColDataInfo = NULL;
1,194,827✔
1058
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
1,194,827✔
1059
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
437,206✔
1060
  }
1061

1062
  if (pSDataBlock->info.window.skey != tsCols[0] || pSDataBlock->info.window.ekey != tsCols[endRowId]) {
1,194,468!
1063
    qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64 ",maxKey %" PRId64,
×
1064
           pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
1065
    code = blockDataUpdateTsWindow(pSDataBlock, pInfo->primaryTsIndex);
×
1066
    QUERY_CHECK_CODE(code, lino, _end);
×
1067

1068
    // timestamp of the data is incorrect
1069
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
1070
      qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
1071
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
1072
    }
1073
  }
1074

1075
  int32_t     startPos = 0;
1,194,516✔
1076
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
1,194,516✔
1077
  STimeWindow nextWin = {0};
1,194,366✔
1078
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,194,366✔
1079
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,413✔
1080
  } else {
1081
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
1,191,953✔
1082
  }
1083
  while (1) {
10,614,434✔
1084
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
11,807,312✔
1085
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
11,805,629!
1086
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1087
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1088
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1089
    }
1090

1091
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
11,804,868✔
1092
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
670✔
1093
                          nextWin.ekey, pPkVal, pkLen)) ||
11,797,840✔
1094
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
11,804,172!
1095
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
×
1096
      if (startPos < 0) {
45✔
1097
        break;
1,189,958✔
1098
      }
1099
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
19!
1100
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1101
      continue;
55✔
1102
    }
1103

1104
    if (IS_FINAL_INTERVAL_OP(pOperator) && pInfo->numOfChild > 0) {
11,798,109!
1105
      bool    ignore = true;
242,401✔
1106
      SWinKey winRes = {
242,401✔
1107
          .ts = nextWin.skey,
242,401✔
1108
          .groupId = groupId,
1109
      };
1110
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
242,401✔
1111
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore) && isClosed &&
242,401!
1112
          !chIds) {
×
1113
        SPullWindowInfo pull = {
×
1114
            .window = nextWin, .groupId = groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
×
1115
        // add pull data request
1116
        if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
×
1117
          code = addPullWindow(pInfo->pPullDataMap, &winRes, pInfo->numOfChild);
×
1118
          QUERY_CHECK_CODE(code, lino, _end);
×
1119

1120
          if (pInfo->destHasPrimaryKey) {
×
1121
            code = tSimpleHashPut(pInfo->pDeletedMap, &winRes, sizeof(SWinKey), NULL, 0);
×
1122
            QUERY_CHECK_CODE(code, lino, _end);
×
1123
          }
1124
        }
1125
      } else {
1126
        int32_t index = -1;
242,401✔
1127
        SArray* chArray = NULL;
242,401✔
1128
        int32_t chId = 0;
242,401✔
1129
        if (chIds) {
242,401✔
1130
          chArray = *(void**)chIds;
358✔
1131
          chId = getChildIndex(pSDataBlock);
358✔
1132
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
358✔
1133
        }
1134
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
242,401✔
1135
          ignore = false;
242,259✔
1136
        }
1137
      }
1138

1139
      if (ignore) {
242,401✔
1140
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
142✔
1141
        if (startPos < 0) {
142✔
1142
          break;
106✔
1143
        }
1144
        continue;
36✔
1145
      }
1146
    }
1147

1148
    int32_t winCode = TSDB_CODE_SUCCESS;
11,797,967✔
1149
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
11,797,967✔
1150
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1151
    QUERY_CHECK_CODE(code, lino, _end);
11,751,536!
1152

1153
    pResult = (SResultRow*)pResPos->pRowBuff;
11,751,536✔
1154

1155
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
11,751,536✔
1156
      forwardRows = 1;
242,259✔
1157
    } else {
1158
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
11,509,277✔
1159
                                             NULL, TSDB_ORDER_ASC);
1160
    }
1161

1162
    SWinKey key = {
11,831,404✔
1163
        .ts = pResult->win.skey,
11,831,404✔
1164
        .groupId = groupId,
1165
    };
1166

1167
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
11,831,404!
1168
      code = tSimpleHashPut(pDeletedMap, &key, sizeof(SWinKey), NULL, 0);
×
1169
      QUERY_CHECK_CODE(code, lino, _end);
×
1170
    }
1171

1172
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
11,831,404!
1173
      code = saveWinResult(&key, pResPos, pUpdatedMap);
11,822,345✔
1174
      QUERY_CHECK_CODE(code, lino, _end);
11,822,199!
1175
    }
1176

1177
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
11,831,258✔
1178
      pResPos->beUpdated = true;
8,092✔
1179
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
8,092✔
1180
      QUERY_CHECK_CODE(code, lino, _end);
8,097!
1181
    }
1182

1183
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
11,831,263✔
1184
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
11,826,710✔
1185
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
11,826,710✔
1186
    QUERY_CHECK_CODE(code, lino, _end);
11,839,620!
1187
    key.ts = nextWin.skey;
11,839,620✔
1188

1189
    if (pInfo->delKey.ts > key.ts) {
11,839,620✔
1190
      pInfo->delKey = key;
2,044✔
1191
    }
1192
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
11,839,620✔
1193
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
11,839,620✔
1194
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
242,259✔
1195
    } else {
1196
      startPos =
1197
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
11,597,361✔
1198
    }
1199
    if (startPos < 0) {
11,804,205✔
1200
      break;
1,189,826✔
1201
    }
1202
  }
1203
_end:
1,189,958✔
1204
  if (code != TSDB_CODE_SUCCESS) {
1,189,958!
1205
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1206
  }
1207
  return code;
1,189,961✔
1208
}
1209

1210
int winPosCmprImpl(const void* pKey1, const void* pKey2) {
161,139,770✔
1211
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
161,139,770✔
1212
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
161,139,770✔
1213
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
161,139,770✔
1214
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
161,139,770✔
1215

1216
  if (pWin1->groupId > pWin2->groupId) {
161,139,770✔
1217
    return 1;
33,376,777✔
1218
  } else if (pWin1->groupId < pWin2->groupId) {
127,762,993✔
1219
    return -1;
31,621,451✔
1220
  }
1221

1222
  if (pWin1->ts > pWin2->ts) {
96,141,542✔
1223
    return 1;
48,906,144✔
1224
  } else if (pWin1->ts < pWin2->ts) {
47,235,398!
1225
    return -1;
48,287,254✔
1226
  }
1227

1228
  return 0;
×
1229
}
1230

1231
static void resetUnCloseWinInfo(SSHashObj* winMap) {
266✔
1232
  void*   pIte = NULL;
266✔
1233
  int32_t iter = 0;
266✔
1234
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
627✔
1235
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
361✔
1236
    pPos->beUsed = true;
361✔
1237
  }
1238
}
266✔
1239

1240
int32_t encodeSWinKey(void** buf, SWinKey* key) {
42✔
1241
  int32_t tlen = 0;
42✔
1242
  tlen += taosEncodeFixedI64(buf, key->ts);
42✔
1243
  tlen += taosEncodeFixedU64(buf, key->groupId);
42✔
1244
  return tlen;
42✔
1245
}
1246

1247
void* decodeSWinKey(void* buf, SWinKey* key) {
8✔
1248
  buf = taosDecodeFixedI64(buf, &key->ts);
8!
1249
  buf = taosDecodeFixedU64(buf, &key->groupId);
8!
1250
  return buf;
8✔
1251
}
1252

1253
int32_t encodeSTimeWindowAggSupp(void** buf, STimeWindowAggSupp* pTwAggSup) {
152✔
1254
  int32_t tlen = 0;
152✔
1255
  tlen += taosEncodeFixedI64(buf, pTwAggSup->minTs);
152✔
1256
  tlen += taosEncodeFixedI64(buf, pTwAggSup->maxTs);
152✔
1257
  return tlen;
152✔
1258
}
1259

1260
void* decodeSTimeWindowAggSupp(void* buf, STimeWindowAggSupp* pTwAggSup) {
20✔
1261
  buf = taosDecodeFixedI64(buf, &pTwAggSup->minTs);
20!
1262
  buf = taosDecodeFixedI64(buf, &pTwAggSup->maxTs);
20!
1263
  return buf;
20✔
1264
}
1265

1266
int32_t encodeSTimeWindow(void** buf, STimeWindow* pWin) {
12✔
1267
  int32_t tlen = 0;
12✔
1268
  tlen += taosEncodeFixedI64(buf, pWin->skey);
12✔
1269
  tlen += taosEncodeFixedI64(buf, pWin->ekey);
12✔
1270
  return tlen;
12✔
1271
}
1272

1273
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
4✔
1274
  buf = taosDecodeFixedI64(buf, &pWin->skey);
4!
1275
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
4!
1276
  return buf;
4✔
1277
}
1278

1279
int32_t encodeSPullWindowInfo(void** buf, SPullWindowInfo* pPullInfo) {
×
1280
  int32_t tlen = 0;
×
1281
  tlen += encodeSTimeWindow(buf, &pPullInfo->calWin);
×
1282
  tlen += taosEncodeFixedU64(buf, pPullInfo->groupId);
×
1283
  tlen += encodeSTimeWindow(buf, &pPullInfo->window);
×
1284
  return tlen;
×
1285
}
1286

1287
void* decodeSPullWindowInfo(void* buf, SPullWindowInfo* pPullInfo) {
×
1288
  buf = decodeSTimeWindow(buf, &pPullInfo->calWin);
×
1289
  buf = taosDecodeFixedU64(buf, &pPullInfo->groupId);
×
1290
  buf = decodeSTimeWindow(buf, &pPullInfo->window);
×
1291
  return buf;
×
1292
}
1293

1294
int32_t encodeSPullWindowInfoArray(void** buf, SArray* pPullInfos) {
66✔
1295
  int32_t tlen = 0;
66✔
1296
  int32_t size = taosArrayGetSize(pPullInfos);
66✔
1297
  tlen += taosEncodeFixedI32(buf, size);
66✔
1298
  for (int32_t i = 0; i < size; i++) {
66!
1299
    void* pItem = taosArrayGet(pPullInfos, i);
×
1300
    tlen += encodeSPullWindowInfo(buf, pItem);
×
1301
  }
1302
  return tlen;
66✔
1303
}
1304

1305
int32_t decodeSPullWindowInfoArray(void* buf, SArray* pPullInfos, void** ppBuf) {
9✔
1306
  int32_t code = TSDB_CODE_SUCCESS;
9✔
1307
  int32_t lino = 0;
9✔
1308
  int32_t size = 0;
9!
1309
  buf = taosDecodeFixedI32(buf, &size);
9✔
1310
  for (int32_t i = 0; i < size; i++) {
9!
1311
    SPullWindowInfo item = {0};
×
1312
    buf = decodeSPullWindowInfo(buf, &item);
×
1313
    void* tmp = taosArrayPush(pPullInfos, &item);
×
1314
    if (!tmp) {
×
1315
      code = terrno;
×
1316
      QUERY_CHECK_CODE(code, lino, _end);
×
1317
    }
1318
  }
1319
  (*ppBuf) = buf;
9✔
1320

1321
_end:
9✔
1322
  if (code != TSDB_CODE_SUCCESS) {
9!
1323
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1324
  }
1325
  return code;
9✔
1326
}
1327

1328
int32_t doStreamIntervalEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator) {
66✔
1329
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
66✔
1330
  if (!pInfo) {
66!
1331
    return 0;
×
1332
  }
1333

1334
  void* pData = (buf == NULL) ? NULL : *buf;
66✔
1335

1336
  // 1.pResultRowHashTable
1337
  int32_t tlen = 0;
66✔
1338
  int32_t mapSize = tSimpleHashGetSize(pInfo->aggSup.pResultRowHashTable);
66✔
1339
  tlen += taosEncodeFixedI32(buf, mapSize);
66✔
1340
  void*   pIte = NULL;
66✔
1341
  size_t  keyLen = 0;
66✔
1342
  int32_t iter = 0;
66✔
1343
  while ((pIte = tSimpleHashIterate(pInfo->aggSup.pResultRowHashTable, pIte, &iter)) != NULL) {
108✔
1344
    void* key = tSimpleHashGetKey(pIte, &keyLen);
42✔
1345
    tlen += encodeSWinKey(buf, key);
42✔
1346
  }
1347

1348
  // 2.twAggSup
1349
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
66✔
1350

1351
  // 3.pPullDataMap
1352
  int32_t size = taosHashGetSize(pInfo->pPullDataMap);
66✔
1353
  tlen += taosEncodeFixedI32(buf, size);
66✔
1354
  pIte = NULL;
66✔
1355
  keyLen = 0;
66✔
1356
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
66!
1357
    void* key = taosHashGetKey(pIte, &keyLen);
×
1358
    tlen += encodeSWinKey(buf, key);
×
1359
    SArray* pArray = *(SArray**)pIte;
×
1360
    int32_t chSize = taosArrayGetSize(pArray);
×
1361
    tlen += taosEncodeFixedI32(buf, chSize);
×
1362
    for (int32_t i = 0; i < chSize; i++) {
×
1363
      void* pChItem = taosArrayGet(pArray, i);
×
1364
      tlen += taosEncodeFixedI32(buf, *(int32_t*)pChItem);
×
1365
    }
1366
  }
1367

1368
  // 4.pPullWins
1369
  tlen += encodeSPullWindowInfoArray(buf, pInfo->pPullWins);
66✔
1370

1371
  // 5.dataVersion
1372
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
66✔
1373

1374
  // 6.checksum
1375
  if (buf) {
66✔
1376
    uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
66!
1377
    tlen += taosEncodeFixedU32(buf, cksum);
33✔
1378
  } else {
1379
    tlen += sizeof(uint32_t);
33✔
1380
  }
1381

1382
  return tlen;
66✔
1383
}
1384

1385
void doStreamIntervalDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator) {
9✔
1386
  int32_t                      code = TSDB_CODE_SUCCESS;
9✔
1387
  int32_t                      lino = 0;
9✔
1388
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
9✔
1389
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
9✔
1390
  if (!pInfo) {
9!
1391
    code = TSDB_CODE_FAILED;
×
1392
    QUERY_CHECK_CODE(code, lino, _end);
×
1393
  }
1394

1395
  // 6.checksum
1396
  int32_t dataLen = len - sizeof(uint32_t);
9✔
1397
  void*   pCksum = POINTER_SHIFT(buf, dataLen);
9✔
1398
  if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
18!
1399
    code = TSDB_CODE_FAILED;
×
1400
    QUERY_CHECK_CODE(code, lino, _end);
×
1401
  }
1402

1403
  // 1.pResultRowHashTable
1404
  int32_t mapSize = 0;
9✔
1405
  buf = taosDecodeFixedI32(buf, &mapSize);
9!
1406
  for (int32_t i = 0; i < mapSize; i++) {
17✔
1407
    SWinKey key = {0};
8✔
1408
    buf = decodeSWinKey(buf, &key);
8✔
1409
    SRowBuffPos* pPos = NULL;
8✔
1410
    int32_t      resSize = pInfo->aggSup.resultRowSize;
8✔
1411
    int32_t      winCode = TSDB_CODE_SUCCESS;
8✔
1412
    code = pInfo->stateStore.streamStateAddIfNotExist(pInfo->pState, &key, (void**)&pPos, &resSize, &winCode);
8✔
1413
    QUERY_CHECK_CODE(code, lino, _end);
8!
1414
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
8!
1415

1416
    code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pPos, POINTER_BYTES);
8✔
1417
    QUERY_CHECK_CODE(code, lino, _end);
8!
1418
  }
1419

1420
  // 2.twAggSup
1421
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
9✔
1422

1423
  // 3.pPullDataMap
1424
  int32_t size = 0;
9✔
1425
  buf = taosDecodeFixedI32(buf, &size);
9!
1426
  for (int32_t i = 0; i < size; i++) {
9!
1427
    SWinKey key = {0};
×
1428
    SArray* pArray = taosArrayInit(0, sizeof(int32_t));
×
1429
    if (!pArray) {
×
1430
      code = terrno;
×
1431
      QUERY_CHECK_CODE(code, lino, _end);
×
1432
    }
1433

1434
    buf = decodeSWinKey(buf, &key);
×
1435
    int32_t chSize = 0;
×
1436
    buf = taosDecodeFixedI32(buf, &chSize);
×
1437
    for (int32_t i = 0; i < chSize; i++) {
×
1438
      int32_t chId = 0;
×
1439
      buf = taosDecodeFixedI32(buf, &chId);
×
1440
      void* tmp = taosArrayPush(pArray, &chId);
×
1441
      if (!tmp) {
×
1442
        code = terrno;
×
1443
        QUERY_CHECK_CODE(code, lino, _end);
×
1444
      }
1445
    }
1446
    code = taosHashPut(pInfo->pPullDataMap, &key, sizeof(SWinKey), &pArray, POINTER_BYTES);
×
1447
    QUERY_CHECK_CODE(code, lino, _end);
×
1448
  }
1449

1450
  // 4.pPullWins
1451
  code = decodeSPullWindowInfoArray(buf, pInfo->pPullWins, &buf);
9✔
1452
  QUERY_CHECK_CODE(code, lino, _end);
9!
1453

1454
  // 5.dataVersion
1455
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
18!
1456

1457
_end:
9✔
1458
  if (code != TSDB_CODE_SUCCESS) {
9!
1459
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1460
  }
1461
}
9✔
1462

1463
void doStreamIntervalSaveCheckpoint(SOperatorInfo* pOperator) {
1,354✔
1464
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,354✔
1465
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
1,354✔
1466
    int32_t len = doStreamIntervalEncodeOpState(NULL, 0, pOperator);
33✔
1467
    void*   buf = taosMemoryCalloc(1, len);
33!
1468
    if (!buf) {
33!
1469
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1470
      return;
×
1471
    }
1472
    void* pBuf = buf;
33✔
1473
    len = doStreamIntervalEncodeOpState(&pBuf, len, pOperator);
33✔
1474
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
33✔
1475
                                          strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), buf, len);
1476
    taosMemoryFree(buf);
33!
1477
    saveStreamOperatorStateComplete(&pInfo->basic);
33✔
1478
  }
1479
}
1480

1481
int32_t copyIntervalDeleteKey(SSHashObj* pMap, SArray* pWins) {
×
1482
  int32_t code = TSDB_CODE_SUCCESS;
×
1483
  int32_t lino = 0;
×
1484
  void*   pIte = NULL;
×
1485
  int32_t iter = 0;
×
1486
  while ((pIte = tSimpleHashIterate(pMap, pIte, &iter)) != NULL) {
×
1487
    void* pKey = tSimpleHashGetKey(pIte, NULL);
×
1488
    void* tmp = taosArrayPush(pWins, pKey);
×
1489
    if (!tmp) {
×
1490
      code = terrno;
×
1491
      QUERY_CHECK_CODE(code, lino, _end);
×
1492
    }
1493
  }
1494
  tSimpleHashClear(pMap);
×
1495

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

1503
static int32_t buildIntervalResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
165,604✔
1504
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
165,604✔
1505
  int32_t                      code = TSDB_CODE_SUCCESS;
165,604✔
1506
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
165,604✔
1507
  uint16_t                     opType = pOperator->operatorType;
165,604✔
1508

1509
  // check if query task is closed or not
1510
  if (isTaskKilled(pTaskInfo)) {
165,604✔
1511
    (*ppRes) = NULL;
5✔
1512
    return code;
5✔
1513
  }
1514

1515
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
165,598✔
1516
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
3,865✔
1517
    if (pInfo->pPullDataRes->info.rows != 0) {
3,865✔
1518
      // process the rest of the data
1519
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
160✔
1520
      (*ppRes) = pInfo->pPullDataRes;
160✔
1521
      return code;
160✔
1522
    }
1523
  }
1524

1525
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
165,438✔
1526
  if (pInfo->pDelRes->info.rows != 0) {
165,434✔
1527
    // process the rest of the data
1528
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
540✔
1529
    (*ppRes) = pInfo->pDelRes;
540✔
1530
    return code;
540✔
1531
  }
1532

1533
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
164,894✔
1534
  if (pInfo->binfo.pRes->info.rows != 0) {
164,898✔
1535
    printDataBlock(pInfo->binfo.pRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
127,407✔
1536
    (*ppRes) = pInfo->binfo.pRes;
127,408✔
1537
    return code;
127,408✔
1538
  }
1539

1540
  (*ppRes) = NULL;
37,491✔
1541
  return code;
37,491✔
1542
}
1543

1544
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
18,844✔
1545
  int32_t code = TSDB_CODE_SUCCESS;
18,844✔
1546
  int32_t lino = 0;
18,844✔
1547
  void*   pIte = NULL;
18,844✔
1548
  int32_t iter = 0;
18,844✔
1549
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
474,943✔
1550
    void* tmp = taosArrayPush(pUpdated, pIte);
456,099✔
1551
    if (!tmp) {
456,099!
1552
      code = terrno;
×
1553
      QUERY_CHECK_CODE(code, lino, _end);
×
1554
    }
1555
  }
1556
  taosArraySort(pUpdated, compar);
18,840✔
1557
  tSimpleHashCleanup(*ppWinUpdated);
18,841✔
1558
  *ppWinUpdated = NULL;
18,846✔
1559

1560
_end:
18,846✔
1561
  if (code != TSDB_CODE_SUCCESS) {
18,846!
1562
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1563
  }
1564
  return code;
18,842✔
1565
}
1566

1567
static int32_t doStreamFinalIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
12,941✔
1568
  int32_t                      code = TSDB_CODE_SUCCESS;
12,941✔
1569
  int32_t                      lino = 0;
12,941✔
1570
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
12,941✔
1571
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
12,941✔
1572
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
12,941✔
1573

1574
  SOperatorInfo* downstream = pOperator->pDownstream[0];
12,941✔
1575
  SExprSupp*     pSup = &pOperator->exprSupp;
12,941✔
1576

1577
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
12,941✔
1578

1579
  if (pOperator->status == OP_EXEC_DONE) {
12,941!
1580
    (*ppRes) = NULL;
×
1581
    return code;
×
1582
  } else if (pOperator->status == OP_RES_TO_RETURN) {
12,941✔
1583
    SSDataBlock* resBlock = NULL;
4,440✔
1584
    code = buildIntervalResult(pOperator, &resBlock);
4,440✔
1585
    QUERY_CHECK_CODE(code, lino, _end);
4,440!
1586
    if (resBlock != NULL) {
4,440✔
1587
      (*ppRes) = resBlock;
626✔
1588
      return code;
4,440✔
1589
    }
1590

1591
    if (pInfo->recvGetAll) {
3,814✔
1592
      pInfo->recvGetAll = false;
83✔
1593
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
83✔
1594
    }
1595

1596
    if (pInfo->reCkBlock) {
3,814!
1597
      pInfo->reCkBlock = false;
×
1598
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1599
      (*ppRes) = pInfo->pCheckpointRes;
×
1600
      return code;
×
1601
    }
1602

1603
    setStreamOperatorCompleted(pOperator);
3,814✔
1604
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
3,814✔
1605
      clearFunctionContext(&pOperator->exprSupp);
2,197✔
1606
      // semi interval operator clear disk buffer
1607
      clearStreamIntervalOperator(pInfo);
2,197✔
1608
      qDebug("===stream===clear semi operator");
2,197✔
1609
    }
1610
    (*ppRes) = NULL;
3,814✔
1611
    return code;
3,814✔
1612
  } else {
1613
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
8,501✔
1614
      SSDataBlock* resBlock = NULL;
5,750✔
1615
      code = buildIntervalResult(pOperator, &resBlock);
5,750✔
1616
      QUERY_CHECK_CODE(code, lino, _end);
5,750!
1617
      if (resBlock != NULL) {
5,750!
1618
        (*ppRes) = resBlock;
×
1619
        return code;
×
1620
      }
1621

1622
      if (pInfo->recvRetrive) {
5,750!
1623
        pInfo->recvRetrive = false;
×
1624
        printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1625
        (*ppRes) = pInfo->pMidRetriveRes;
×
1626
        return code;
×
1627
      }
1628
    }
1629
  }
1630

1631
  if (!pInfo->pUpdated) {
8,501✔
1632
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
6,551✔
1633
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
6,550!
1634
  }
1635
  if (!pInfo->pUpdatedMap) {
8,500✔
1636
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
6,551✔
1637
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
6,551✔
1638
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
6,553!
1639
  }
1640

1641
  while (1) {
23,585✔
1642
    if (isTaskKilled(pTaskInfo)) {
32,087!
1643
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
1644
      (*ppRes) = NULL;
×
1645
      return code;
1,950✔
1646
    }
1647

1648
    SSDataBlock* pBlock = NULL;
32,087✔
1649
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
32,087✔
1650
    QUERY_CHECK_CODE(code, lino, _end);
32,086!
1651

1652
    if (pBlock == NULL) {
32,086✔
1653
      pOperator->status = OP_RES_TO_RETURN;
6,019✔
1654
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
6,019✔
1655
             pInfo->numOfDatapack);
1656
      pInfo->numOfDatapack = 0;
6,019✔
1657
      break;
6,019✔
1658
    }
1659

1660
    pInfo->numOfDatapack++;
26,067✔
1661
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
26,067✔
1662
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
26,068✔
1663

1664
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
26,068✔
1665
      pInfo->binfo.pRes->info.type = pBlock->info.type;
21,344✔
1666
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,724✔
1667
               pBlock->info.type == STREAM_CLEAR) {
4,492✔
1668
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
408✔
1669
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
408!
1670
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
408✔
1671
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
408✔
1672
      QUERY_CHECK_CODE(code, lino, _end);
408!
1673

1674
      if (IS_FINAL_INTERVAL_OP(pOperator)) {
408✔
1675
        int32_t chId = getChildIndex(pBlock);
204✔
1676
        code = addRetriveWindow(delWins, pInfo, chId);
204✔
1677
        QUERY_CHECK_CODE(code, lino, _end);
204!
1678

1679
        if (pBlock->info.type != STREAM_CLEAR) {
204✔
1680
          void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
116✔
1681
          if (!tmp && taosArrayGetSize(delWins) > 0) {
116!
1682
            code = TSDB_CODE_OUT_OF_MEMORY;
×
1683
            QUERY_CHECK_CODE(code, lino, _end);
×
1684
          }
1685
        }
1686
        taosArrayDestroy(delWins);
204✔
1687
        continue;
1,552✔
1688
      }
1689
      removeResults(delWins, pInfo->pUpdatedMap);
204✔
1690
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
204✔
1691
      if (!tmp && taosArrayGetSize(delWins) > 0) {
204!
1692
        code = TSDB_CODE_OUT_OF_MEMORY;
×
1693
        QUERY_CHECK_CODE(code, lino, _end);
×
1694
      }
1695
      taosArrayDestroy(delWins);
204✔
1696

1697
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
204✔
1698
      if (pInfo->pDelRes->info.rows != 0) {
204!
1699
        // process the rest of the data
1700
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
204✔
1701
        if (pBlock->info.type == STREAM_CLEAR) {
204✔
1702
          pInfo->pDelRes->info.type = STREAM_CLEAR;
88✔
1703
        } else {
1704
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
116✔
1705
        }
1706
        (*ppRes) = pInfo->pDelRes;
204✔
1707
        return code;
204✔
1708
      }
1709

1710
      break;
×
1711
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_INTERVAL_OP(pOperator)) {
4,316!
1712
      pInfo->recvGetAll = true;
83✔
1713
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
83✔
1714
      QUERY_CHECK_CODE(code, lino, _end);
83!
1715
      continue;
83✔
1716
    } else if (pBlock->info.type == STREAM_RETRIEVE) {
4,233✔
1717
      if (!IS_FINAL_INTERVAL_OP(pOperator)) {
533!
1718
        pInfo->recvRetrive = true;
533✔
1719
        code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
533✔
1720
        QUERY_CHECK_CODE(code, lino, _end);
533!
1721

1722
        pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
533✔
1723
        code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap, NULL);
533✔
1724
        QUERY_CHECK_CODE(code, lino, _end);
533!
1725
        break;
533✔
1726
      }
1727
      continue;
×
1728
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_INTERVAL_OP(pOperator)) {
3,700!
1729
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
527✔
1730
                             pInfo->numOfChild, pOperator, NULL);
1731
      QUERY_CHECK_CODE(code, lino, _end);
527!
1732
      continue;
527✔
1733
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,173✔
1734
      (*ppRes) = pBlock;
1,746✔
1735
      return code;
1,746✔
1736
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,427✔
1737
      pAPI->stateStore.streamStateCommit(pInfo->pState);
205✔
1738
      doStreamIntervalSaveCheckpoint(pOperator);
205✔
1739
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
205✔
1740
      QUERY_CHECK_CODE(code, lino, _end);
205!
1741

1742
      continue;
205✔
1743
    } else if (IS_FINAL_INTERVAL_OP(pOperator) && pBlock->info.type == STREAM_MID_RETRIEVE) {
1,222✔
1744
      continue;
533✔
1745
    } else {
1746
      if (pBlock->info.type != STREAM_INVALID) {
689!
1747
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1748
        QUERY_CHECK_CODE(code, lino, _end);
×
1749
      }
1750
    }
1751

1752
    if (pInfo->scalarSupp.pExprInfo != NULL) {
22,033!
1753
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
1754
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
1755
      QUERY_CHECK_CODE(code, lino, _end);
×
1756
    }
1757
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
22,033✔
1758
    QUERY_CHECK_CODE(code, lino, _end);
22,033!
1759

1760
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
22,033✔
1761
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
22,033!
1762
      code = TSDB_CODE_SUCCESS;
×
1763
      pOperator->status = OP_RES_TO_RETURN;
×
1764
      break;
×
1765
    }
1766
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
22,033✔
1767
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
22,033✔
1768
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
22,033✔
1769
  }
1770

1771
  if (IS_FINAL_INTERVAL_OP(pOperator) && !pInfo->destHasPrimaryKey) {
6,552!
1772
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
1,878✔
1773
  }
1774
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
6,552✔
1775
    code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
1,878✔
1776
                                     pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
1777
    QUERY_CHECK_CODE(code, lino, _end);
1,878!
1778

1779
    if (pInfo->destHasPrimaryKey) {
1,878!
1780
      code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
×
1781
      QUERY_CHECK_CODE(code, lino, _end);
×
1782
    }
1783
  }
1784
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
6,552✔
1785

1786
  code = copyUpdateResult(&pInfo->pUpdatedMap, pInfo->pUpdated, winPosCmprImpl);
6,552✔
1787
  QUERY_CHECK_CODE(code, lino, _end);
6,551!
1788

1789
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
6,551✔
1790
  pInfo->pUpdated = NULL;
6,552✔
1791
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
6,552✔
1792
  QUERY_CHECK_CODE(code, lino, _end);
6,552!
1793

1794
  SSDataBlock* resBlock = NULL;
6,552✔
1795
  code = buildIntervalResult(pOperator, &resBlock);
6,552✔
1796
  QUERY_CHECK_CODE(code, lino, _end);
6,552!
1797
  if (resBlock != NULL) {
6,552✔
1798
    (*ppRes) = resBlock;
3,814✔
1799
    return code;
3,814✔
1800
  }
1801

1802
  if (pInfo->recvRetrive) {
2,738✔
1803
    pInfo->recvRetrive = false;
533✔
1804
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
533✔
1805
    (*ppRes) = pInfo->pMidRetriveRes;
533✔
1806
    return code;
533✔
1807
  }
1808

1809
_end:
2,205✔
1810
  if (code != TSDB_CODE_SUCCESS) {
2,205!
1811
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1812
    pTaskInfo->code = code;
×
1813
    T_LONG_JMP(pTaskInfo->env, code);
×
1814
  }
1815
  setStreamOperatorCompleted(pOperator);
2,205✔
1816
  (*ppRes) = NULL;
2,205✔
1817
  return code;
2,205✔
1818
}
1819

1820
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
5,717✔
1821
  if (pWinPhyNode->deleteMark <= 0) {
5,717✔
1822
    return DEAULT_DELETE_MARK;
3,704✔
1823
  }
1824
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
2,013✔
1825
  deleteMark = TMAX(deleteMark, interval);
2,013✔
1826
  return deleteMark;
2,013✔
1827
}
1828

1829
int64_t getDeleteMarkFromOption(SStreamNodeOption* pOption) {
27✔
1830
  if (pOption->deleteMark <= 0) {
27!
1831
    return DEAULT_DELETE_MARK;
27✔
1832
  }
1833
  int64_t deleteMark = TMAX(pOption->deleteMark, pOption->watermark);
×
1834
  return deleteMark;
×
1835
}
1836

1837
TSKEY compareTs(void* pKey) {
33,683,663✔
1838
  SWinKey* pWinKey = (SWinKey*)pKey;
33,683,663✔
1839
  return pWinKey->ts;
33,683,663✔
1840
}
1841

1842
static int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
225,673✔
1843
  if (pCtx->subsidiaries.rowLen == 0) {
225,673!
1844
    int32_t rowLen = 0;
225,673✔
1845
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
225,801✔
1846
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
128✔
1847
      rowLen += pc->pExpr->base.resSchema.bytes;
128✔
1848
    }
1849

1850
    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
225,673✔
1851
  } else {
1852
    return pCtx->subsidiaries.rowLen;
×
1853
  }
1854
}
1855

1856
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
5,745✔
1857
  int32_t size = 0;
5,745✔
1858
  for (int32_t i = 0; i < numOfCols; ++i) {
231,418✔
1859
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
225,672✔
1860
    size = TMAX(size, resSize);
225,673✔
1861
  }
1862
  return size;
5,746✔
1863
}
1864

1865
static void streamIntervalReleaseState(SOperatorInfo* pOperator) {
1,296✔
1866
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,296✔
1867
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,154✔
1868
    SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,144✔
1869
    int32_t                      resSize = sizeof(TSKEY);
1,144✔
1870
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,144✔
1871
                                          strlen(STREAM_INTERVAL_OP_STATE_NAME), &pInfo->twAggSup.maxTs, resSize);
1,144✔
1872
  }
1873
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,296✔
1874
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
1,296✔
1875
  pAPI->stateStore.streamStateCommit(pInfo->pState);
1,296✔
1876
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,296✔
1877
  if (downstream->fpSet.releaseStreamStateFn) {
1,296!
1878
    downstream->fpSet.releaseStreamStateFn(downstream);
1,296✔
1879
  }
1880
}
1,296✔
1881

1882
void streamIntervalReloadState(SOperatorInfo* pOperator) {
1,296✔
1883
  int32_t                      code = TSDB_CODE_SUCCESS;
1,296✔
1884
  int32_t                      lino = 0;
1,296✔
1885
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,296✔
1886
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
1,296✔
1887
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL &&
1,296✔
1888
      pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
1,154✔
1889
    int32_t size = 0;
1,144✔
1890
    void*   pBuf = NULL;
1,144✔
1891
    code = pInfo->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
1,144✔
1892
                                                strlen(STREAM_INTERVAL_OP_STATE_NAME), &pBuf, &size);
1893
    QUERY_CHECK_CODE(code, lino, _end);
1,144!
1894

1895
    TSKEY ts = *(TSKEY*)pBuf;
1,144✔
1896
    taosMemoryFree(pBuf);
1,144!
1897
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
1,144✔
1898
    pInfo->stateStore.streamStateReloadInfo(pInfo->pState, ts);
1,144✔
1899
  }
1900
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,296✔
1901
  if (downstream->fpSet.reloadStreamStateFn) {
1,296!
1902
    downstream->fpSet.reloadStreamStateFn(downstream);
1,296✔
1903
  }
1904
  reloadFromDownStream(downstream, pInfo);
1,296✔
1905

1906
_end:
1,296✔
1907
  if (code != TSDB_CODE_SUCCESS) {
1,296!
1908
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1909
  }
1910
}
1,296✔
1911

1912
int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
940✔
1913
                                              int32_t numOfChild, SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
1914
  QRY_PARAM_CHECK(pOptrInfo);
940!
1915

1916
  int32_t                      code = TSDB_CODE_SUCCESS;
940✔
1917
  int32_t                      lino = 0;
940✔
1918
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
940✔
1919
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
940!
1920
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
941!
1921
  if (pInfo == NULL || pOperator == NULL) {
941!
1922
    code = terrno;
×
1923
    QUERY_CHECK_CODE(code, lino, _error);
×
1924
  }
1925

1926
  pOperator->exprSupp.hasWindowOrGroup = true;
941✔
1927
  pOperator->pTaskInfo = pTaskInfo;
941✔
1928
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
941✔
1929

1930
  pInfo->interval = (SInterval){.interval = pIntervalPhyNode->interval,
941✔
1931
                                .sliding = pIntervalPhyNode->sliding,
941✔
1932
                                .intervalUnit = pIntervalPhyNode->intervalUnit,
941✔
1933
                                .slidingUnit = pIntervalPhyNode->slidingUnit,
941✔
1934
                                .offset = pIntervalPhyNode->offset,
941✔
1935
                                .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
941✔
1936
                                .timeRange = pIntervalPhyNode->timeRange};
941✔
1937
  calcIntervalAutoOffset(&pInfo->interval);
941✔
1938
  pInfo->twAggSup = (STimeWindowAggSupp){
941✔
1939
      .waterMark = pIntervalPhyNode->window.watermark,
941✔
1940
      .calTrigger = pIntervalPhyNode->window.triggerType,
941✔
1941
      .maxTs = INT64_MIN,
1942
      .minTs = INT64_MAX,
1943
      .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval),
941✔
1944
      .deleteMarkSaved = 0,
1945
      .calTriggerSaved = 0,
1946
  };
1947
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
941✔
1948
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
941✔
1949
  initResultSizeInfo(&pOperator->resultInfo, 4096);
941✔
1950
  if (pIntervalPhyNode->window.pExprs != NULL) {
941!
1951
    int32_t    numOfScalar = 0;
×
1952
    SExprInfo* pScalarExprInfo = NULL;
×
1953

1954
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
×
1955
    QUERY_CHECK_CODE(code, lino, _error);
×
1956

1957
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
×
1958
    QUERY_CHECK_CODE(code, lino, _error);
×
1959
  }
1960

1961
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
941✔
1962
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
941!
1963
  initBasicInfo(&pInfo->binfo, pResBlock);
941✔
1964

1965
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
941!
1966
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
941!
1967
  qInfo("open state %p", pInfo->pState);
941!
1968
  pAPI->stateStore.streamStateCopyBackend(pTaskInfo->streamInfo.pState, pInfo->pState);
941✔
1969
  //*(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
1970

1971
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
941!
1972

1973
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
941✔
1974

1975
  int32_t    numOfCols = 0;
941✔
1976
  SExprInfo* pExprInfo = NULL;
941✔
1977
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
941✔
1978
  QUERY_CHECK_CODE(code, lino, _error);
941!
1979

1980
  code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
941✔
1981
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
941✔
1982
  QUERY_CHECK_CODE(code, lino, _error);
941!
1983

1984
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
941✔
1985
  QUERY_CHECK_CODE(code, lino, _error);
941!
1986
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
941✔
1987

1988
  pInfo->numOfChild = numOfChild;
941✔
1989
  pInfo->pPhyNode = NULL;
941✔
1990
  code = nodesCloneNode((SNode*)pPhyNode, (SNode**)&pInfo->pPhyNode);
941✔
1991
  if (TSDB_CODE_SUCCESS != code) {
941!
1992
    goto _error;
×
1993
  }
1994

1995
  pInfo->pPullWins = taosArrayInit(8, sizeof(SPullWindowInfo));
941✔
1996
  QUERY_CHECK_NULL(pInfo->pPullWins, code, lino, _error, terrno);
941!
1997
  pInfo->pullIndex = 0;
941✔
1998
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
941✔
1999
  pInfo->pPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
941✔
2000
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, true, HASH_NO_LOCK);
941✔
2001

2002
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
941✔
2003
  QUERY_CHECK_CODE(code, lino, _error);
941!
2004

2005
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
941✔
2006
  pInfo->ignoreExpiredDataSaved = false;
941✔
2007
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
941✔
2008
  QUERY_CHECK_CODE(code, lino, _error);
941!
2009

2010
  pInfo->delIndex = 0;
941✔
2011
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
941✔
2012
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
941!
2013
  pInfo->delKey.ts = INT64_MAX;
941✔
2014
  pInfo->delKey.groupId = 0;
941✔
2015
  pInfo->numOfDatapack = 0;
941✔
2016
  pInfo->pUpdated = NULL;
941✔
2017
  pInfo->pUpdatedMap = NULL;
941✔
2018
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
941✔
2019
  int32_t funResSize = getMaxFunResSize(&pOperator->exprSupp, numOfCols);
941✔
2020
  pInfo->pState->pFileState = NULL;
940✔
2021

2022
  // used for backward compatibility of function's result info
2023
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
940✔
2024
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
940✔
2025
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
940✔
2026
  
2027
  code =
2028
      pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
940✔
2029
                                           compareTs, pInfo->pState, pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo),
940✔
2030
                                           pHandle->checkpointId, STREAM_STATE_BUFF_HASH, &pInfo->pState->pFileState);
940✔
2031
  QUERY_CHECK_CODE(code, lino, _error);
941!
2032

2033
  pInfo->dataVersion = 0;
941✔
2034
  pInfo->recvGetAll = false;
941✔
2035
  pInfo->recvPullover = false;
941✔
2036
  pInfo->recvRetrive = false;
941✔
2037

2038
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
941✔
2039
  QUERY_CHECK_CODE(code, lino, _error);
941!
2040
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidRetriveRes);
941✔
2041
  QUERY_CHECK_CODE(code, lino, _error);
941!
2042
  code = createSpecialDataBlock(STREAM_MID_RETRIEVE, &pInfo->pMidPulloverRes);
941✔
2043
  QUERY_CHECK_CODE(code, lino, _error);
941!
2044

2045
  pInfo->clearState = false;
941✔
2046
  pInfo->pMidPullDatas = taosArrayInit(4, sizeof(SWinKey));
941✔
2047
  QUERY_CHECK_NULL(pInfo->pMidPullDatas, code, lino, _error, terrno);
941!
2048
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
941✔
2049
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
941!
2050
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
941✔
2051
  pInfo->pOperator = pOperator;
941✔
2052

2053
  pOperator->operatorType = pPhyNode->type;
941✔
2054
  if (!IS_FINAL_INTERVAL_OP(pOperator) || numOfChild == 0) {
941!
2055
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
706✔
2056
  }
2057
  pOperator->name = getStreamOpName(pOperator->operatorType);
941✔
2058
  pOperator->blocking = true;
941✔
2059
  pOperator->status = OP_NOT_OPENED;
941✔
2060
  pOperator->info = pInfo;
941✔
2061

2062
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
941✔
2063
    pOperator->fpSet =
2064
        createOperatorFpSet(NULL, doStreamMidIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
22✔
2065
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2066
  } else {
2067
    pOperator->fpSet =
2068
        createOperatorFpSet(NULL, doStreamFinalIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
919✔
2069
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
2070
  }
2071
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
941✔
2072
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL ||
941✔
2073
      pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL) {
257✔
2074
    pInfo->basic.primaryPkIndex = -1;
706✔
2075
    code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
706✔
2076
    QUERY_CHECK_CODE(code, lino, _error);
706!
2077
  }
2078
  code = appendDownstream(pOperator, &downstream, 1);
941✔
2079
  QUERY_CHECK_CODE(code, lino, _error);
941!
2080

2081
  // for stream
2082
  void*   buff = NULL;
941✔
2083
  int32_t len = 0;
941✔
2084
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
941✔
2085
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
2086
  if (res == TSDB_CODE_SUCCESS) {
941✔
2087
    doStreamIntervalDecodeOpState(buff, len, pOperator);
1✔
2088
    taosMemoryFree(buff);
1!
2089
  }
2090

2091
  *pOptrInfo = pOperator;
941✔
2092
  return TSDB_CODE_SUCCESS;
941✔
2093

2094
_error:
×
2095
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
2096
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
2097
  pTaskInfo->code = code;
×
2098
  return code;
×
2099
}
2100

2101
void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
1,752✔
2102
  tSimpleHashCleanup(pSup->pResultRows);
1,752✔
2103
  destroyDiskbasedBuf(pSup->pResultBuf);
1,752✔
2104
  blockDataDestroy(pSup->pScanBlock);
1,752✔
2105
  if (pSup->stateStore.streamFileStateDestroy != NULL) {
1,752!
2106
    pSup->stateStore.streamFileStateDestroy(pSup->pState->pFileState);
1,752✔
2107
  }
2108
  taosMemoryFreeClear(pSup->pState);
1,752!
2109
  taosMemoryFreeClear(pSup->pDummyCtx);
1,752!
2110
}
1,752✔
2111

2112
void destroyStreamSessionAggOperatorInfo(void* param) {
848✔
2113
  if (param == NULL) {
848!
2114
    return;
×
2115
  }
2116
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
848✔
2117
  cleanupBasicInfo(&pInfo->binfo);
848✔
2118
  if (pInfo->pOperator) {
848!
2119
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
848✔
2120
                              &pInfo->groupResInfo);
2121
    pInfo->pOperator = NULL;
848✔
2122
  }
2123
  destroyStreamAggSupporter(&pInfo->streamAggSup);
848✔
2124
  cleanupExprSupp(&pInfo->scalarSupp);
848✔
2125
  clearGroupResInfo(&pInfo->groupResInfo);
848✔
2126
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
848✔
2127
  pInfo->pUpdated = NULL;
848✔
2128

2129
  if (pInfo->pChildren != NULL) {
848✔
2130
    int32_t size = taosArrayGetSize(pInfo->pChildren);
34✔
2131
    for (int32_t i = 0; i < size; i++) {
143✔
2132
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
109✔
2133
      destroyOperator(pChild);
109✔
2134
    }
2135
    taosArrayDestroy(pInfo->pChildren);
34✔
2136
  }
2137

2138
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
848✔
2139
  blockDataDestroy(pInfo->pDelRes);
848✔
2140
  blockDataDestroy(pInfo->pWinBlock);
848✔
2141
  tSimpleHashCleanup(pInfo->pStUpdated);
848✔
2142
  tSimpleHashCleanup(pInfo->pStDeleted);
848✔
2143
  cleanupGroupResInfo(&pInfo->groupResInfo);
848✔
2144

2145
  taosArrayDestroy(pInfo->historyWins);
848✔
2146
  blockDataDestroy(pInfo->pCheckpointRes);
848✔
2147
  tSimpleHashCleanup(pInfo->pPkDeleted);
848✔
2148

2149
  taosMemoryFreeClear(param);
848!
2150
}
2151

2152
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
1,690✔
2153
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
2154
  initBasicInfo(pBasicInfo, pResultBlock);
1,690✔
2155
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
1,691✔
2156
  if (code != TSDB_CODE_SUCCESS) {
1,691!
2157
    return code;
×
2158
  }
2159

2160
  for (int32_t i = 0; i < numOfCols; ++i) {
28,235✔
2161
    pSup->pCtx[i].saveHandle.pBuf = NULL;
26,544✔
2162
  }
2163

2164
  return TSDB_CODE_SUCCESS;
1,691✔
2165
}
2166

2167
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
1,770✔
2168
  for (int i = 0; i < nums; i++) {
28,713✔
2169
    pDummy[i].functionId = pCtx[i].functionId;
26,943✔
2170
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
26,943✔
2171
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
26,943✔
2172
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
26,943✔
2173
  }
2174
}
1,770✔
2175

2176
int32_t initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
2,210✔
2177
                       STimeWindowAggSupp* pTwSup, struct SSteamOpBasicInfo* pBasic) {
2178
  SExecTaskInfo* pTaskInfo = downstream->pTaskInfo;
2,210✔
2179
  int32_t        code = TSDB_CODE_SUCCESS;
2,210✔
2180
  int32_t        lino = 0;
2,210✔
2181
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
2,210✔
2182
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
628✔
2183
    pScanInfo->tsColIndex = tsColIndex;
628✔
2184
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
628✔
2185
  }
2186

2187
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
2,210✔
2188
    code = initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup, pBasic);
628✔
2189
    return code;
628✔
2190
  }
2191
  SStreamScanInfo* pScanInfo = downstream->info;
1,582✔
2192
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
1,582✔
2193
  pScanInfo->pState = pAggSup->pState;
1,582✔
2194
  if (!pScanInfo->pUpdateInfo) {
1,582✔
2195
    code = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark,
953✔
2196
                                              pScanInfo->igCheckUpdate, pScanInfo->pkColType, pScanInfo->pkColLen,
953✔
2197
                                              &pScanInfo->pUpdateInfo);
953✔
2198
    QUERY_CHECK_CODE(code, lino, _end);
953!
2199
  }
2200
  pScanInfo->twAggSup = *pTwSup;
1,582✔
2201
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
1,582✔
2202
  if (!hasSrcPrimaryKeyCol(pBasic)) {
1,582✔
2203
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
1,126✔
2204
  }
2205

2206
_end:
456✔
2207
  if (code != TSDB_CODE_SUCCESS) {
1,582!
2208
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2209
  }
2210
  return code;
1,582✔
2211
}
2212

2213
static TSKEY sesionTs(void* pKey) {
2,845✔
2214
  SSessionKey* pWinKey = (SSessionKey*)pKey;
2,845✔
2215
  return pWinKey->win.skey;
2,845✔
2216
}
2217

2218
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SExprSupp* pExpSup, int32_t numOfOutput, int64_t gap,
1,769✔
2219
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore,
2220
                               SReadHandle* pHandle, STimeWindowAggSupp* pTwAggSup, const char* taskIdStr,
2221
                               SStorageAPI* pApi, int32_t tsIndex, int8_t stateType, int32_t ratio) {
2222
  pSup->resultRowSize = (keySize + getResultRowSize(pExpSup->pCtx, numOfOutput)) * ratio;
1,769✔
2223
  int32_t lino = 0;
1,770✔
2224
  int32_t code = createSpecialDataBlock(STREAM_CLEAR, &pSup->pScanBlock);
1,770✔
2225
  QUERY_CHECK_CODE(code, lino, _end);
1,770!
2226

2227
  pSup->gap = gap;
1,770✔
2228
  pSup->stateKeySize = keySize;
1,770✔
2229
  pSup->stateKeyType = keyType;
1,770✔
2230
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
1,770!
2231
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
1,770!
2232

2233
  pSup->stateStore = *pStore;
1,770✔
2234
  pSup->pSessionAPI = pApi;
1,770✔
2235

2236
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
1,770✔
2237
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
1,770!
2238
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
1,770!
2239

2240
  *(pSup->pState) = *pState;
1,770✔
2241
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1, tsIndex);
1,770✔
2242
  int32_t funResSize = getMaxFunResSize(pExpSup, numOfOutput);
1,770✔
2243
  if (stateType != STREAM_STATE_BUFF_HASH_SORT) {
1,770✔
2244
    // used for backward compatibility of function's result info
2245
    pSup->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
1,743✔
2246
    pSup->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
1,743✔
2247
    pSup->pState->pExprSupp = pExpSup;
1,743✔
2248
  }
2249

2250
  if (stateType == STREAM_STATE_BUFF_SORT) {
1,770✔
2251
  pSup->pState->pFileState = NULL;
1,691✔
2252
  code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SSessionKey), pSup->resultRowSize,
1,691✔
2253
                                                funResSize, sesionTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
1,691✔
2254
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
1,691✔
2255
  } else if (stateType == STREAM_STATE_BUFF_HASH_SORT || stateType == STREAM_STATE_BUFF_HASH_SEARCH) {
79!
2256
    pSup->pState->pFileState = NULL;
79✔
2257
    code = pSup->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pSup->resultRowSize, funResSize,
79✔
2258
                                                compareTs, pSup->pState, pTwAggSup->deleteMark, taskIdStr,
79✔
2259
                                                pHandle->checkpointId, stateType, &pSup->pState->pFileState);
79✔
2260
  }
2261
  QUERY_CHECK_CODE(code, lino, _end);
1,770!
2262

2263
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
1,770✔
2264
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
1,770✔
2265
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
1,770!
2266

2267
  for (int32_t i = 0; i < numOfOutput; ++i) {
28,716✔
2268
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
26,946✔
2269
  }
2270

2271
_end:
1,770✔
2272
  if (code != TSDB_CODE_SUCCESS) {
1,770!
2273
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2274
  }
2275
  return code;
1,770✔
2276
}
2277

2278
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5,287✔
2279
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5,287✔
2280
    return true;
4,033✔
2281
  }
2282
  return false;
1,254✔
2283
}
2284

2285
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
4,553✔
2286
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
4,553✔
2287
}
2288

2289
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
4,262✔
2290
                         SSessionKey* pKey) {
2291
  pKey->win.skey = startTs;
4,262✔
2292
  pKey->win.ekey = endTs;
4,262✔
2293
  pKey->groupId = groupId;
4,262✔
2294
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
4,262✔
2295
  if (code != TSDB_CODE_SUCCESS) {
4,261✔
2296
    SET_SESSION_WIN_KEY_INVALID(pKey);
1,200✔
2297
  }
2298
}
4,261✔
2299

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

2302
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
51,103✔
2303
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
51,103!
2304
    return true;
51,142✔
2305
  }
2306
  return false;
×
2307
}
2308

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

2311
int32_t setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
3,220✔
2312
                            SResultWindowInfo* pCurWin) {
2313
  int32_t code = TSDB_CODE_SUCCESS;
3,220✔
2314
  int32_t lino = 0;
3,220✔
2315
  pCurWin->sessionWin.groupId = groupId;
3,220✔
2316
  pCurWin->sessionWin.win.skey = startTs;
3,220✔
2317
  pCurWin->sessionWin.win.ekey = endTs;
3,220✔
2318
  int32_t size = pAggSup->resultRowSize;
3,220✔
2319
  int32_t winCode = TSDB_CODE_SUCCESS;
3,220✔
2320
  code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin, pAggSup->gap,
3,220✔
2321
                                                             (void**)&pCurWin->pStatePos, &size, &winCode);
3,220✔
2322
  QUERY_CHECK_CODE(code, lino, _end);
3,221!
2323

2324
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->sessionWin.win)) {
3,221!
2325
    winCode = TSDB_CODE_FAILED;
×
2326
    clearOutputBuf(pAggSup->pState, pCurWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2327
  }
2328

2329
  if (winCode == TSDB_CODE_SUCCESS) {
3,221✔
2330
    pCurWin->isOutput = true;
973✔
2331
    if (pCurWin->pStatePos->needFree) {
973✔
2332
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
138✔
2333
    }
2334
  } else {
2335
    pCurWin->sessionWin.win.skey = startTs;
2,248✔
2336
    pCurWin->sessionWin.win.ekey = endTs;
2,248✔
2337
  }
2338
  qDebug("===stream===set session window buff .start:%" PRId64 ",end:%" PRId64 ",groupid:%" PRIu64,
3,221✔
2339
         pCurWin->sessionWin.win.skey, pCurWin->sessionWin.win.ekey, pCurWin->sessionWin.groupId);
2340

2341
_end:
1,766✔
2342
  if (code != TSDB_CODE_SUCCESS) {
3,221!
2343
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2344
  }
2345
  return code;
3,221✔
2346
}
2347

2348
void getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo,
245✔
2349
                      int32_t* pWinCode) {
2350
  int32_t size = 0;
245✔
2351
  (*pWinCode) = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin,
490✔
2352
                                                                 (void**)&pWinInfo->pStatePos, &size);
245✔
2353
  if ((*pWinCode) != TSDB_CODE_SUCCESS) {
245✔
2354
    return;
209✔
2355
  }
2356

2357
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
36✔
2358
}
2359

2360
int32_t saveDeleteInfo(SArray* pWins, SSessionKey key) {
1,158✔
2361
  int32_t code = TSDB_CODE_SUCCESS;
1,158✔
2362
  int32_t lino = 0;
1,158✔
2363
  void*   res = taosArrayPush(pWins, &key);
1,158✔
2364
  if (!res) {
1,158!
2365
    code = terrno;
×
2366
    QUERY_CHECK_CODE(code, lino, _end);
×
2367
  }
2368

2369
_end:
1,158✔
2370
  if (code != TSDB_CODE_SUCCESS) {
1,158!
2371
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2372
  }
2373
  return code;
1,157✔
2374
}
2375

2376
int32_t saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
44✔
2377
  key.win.ekey = key.win.skey;
44✔
2378
  return tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
44✔
2379
}
2380

2381
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
8,688✔
2382
  pAPI->streamStateReleaseBuf(pState, pPos, false);
8,688✔
2383
}
8,688✔
2384

2385
void removeSessionResult(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SSHashObj* pResMap, SSessionKey* pKey) {
50✔
2386
  int32_t     code = TSDB_CODE_SUCCESS;
50✔
2387
  int32_t     lino = 0;
50✔
2388
  SSessionKey key = {0};
50✔
2389
  getSessionHashKey(pKey, &key);
50✔
2390
  void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
50✔
2391
  if (pVal) {
50✔
2392
    releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
4✔
2393
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
4✔
2394
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
4!
2395
  }
2396
  int32_t tmpRes = tSimpleHashRemove(pResMap, &key, sizeof(SSessionKey));
50✔
2397
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
50!
2398
}
50✔
2399

2400
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
9,599✔
2401
  *pHashKey = *pKey;
9,599✔
2402
  pHashKey->win.ekey = pKey->win.skey;
9,599✔
2403
}
9,599✔
2404

2405
void removeSessionDeleteResults(SSHashObj* pHashMap, SArray* pWins) {
11,136✔
2406
  if (tSimpleHashGetSize(pHashMap) == 0) {
11,136✔
2407
    return;
10,136✔
2408
  }
2409
  int32_t size = taosArrayGetSize(pWins);
1,003✔
2410
  for (int32_t i = 0; i < size; i++) {
2,124✔
2411
    SResultWindowInfo* pWin = taosArrayGet(pWins, i);
1,121✔
2412
    if (!pWin) continue;
1,121!
2413
    SSessionKey key = {0};
1,121✔
2414
    getSessionHashKey(&pWin->sessionWin, &key);
1,121✔
2415
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
1,121✔
2416
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,121!
2417
  }
2418
}
2419

2420
void removeSessionResults(SStreamAggSupporter* pAggSup, SSHashObj* pHashMap, SArray* pWins) {
1,057✔
2421
  if (tSimpleHashGetSize(pHashMap) == 0) {
1,057✔
2422
    return;
811✔
2423
  }
2424
  int32_t size = taosArrayGetSize(pWins);
247✔
2425
  for (int32_t i = 0; i < size; i++) {
524✔
2426
    SSessionKey* pWin = taosArrayGet(pWins, i);
277✔
2427
    if (!pWin) continue;
277!
2428
    SSessionKey key = {0};
277✔
2429
    getSessionHashKey(pWin, &key);
277✔
2430
    void* pVal = tSimpleHashGet(pHashMap, &key, sizeof(SSessionKey));
277✔
2431
    if (pVal) {
277✔
2432
      releaseOutputBuf(pAggSup->pState, *(void**)pVal, &pAggSup->pSessionAPI->stateStore);
165✔
2433
      int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
165✔
2434
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
165!
2435
    }
2436
  }
2437
}
2438

2439
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
3,194✔
2440
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2441
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2442
                                int32_t* pWinRos) {
2443
  int32_t code = TSDB_CODE_SUCCESS;
3,194✔
2444
  int32_t lino = 0;
3,194✔
2445
  for (int32_t i = start; i < rows; ++i) {
7,198✔
2446
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
4,067!
2447
      (*pWinRos) = i - start;
64✔
2448
      goto _end;
64✔
2449
    }
2450
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
4,004✔
2451
      if (pStDeleted && pWinInfo->isOutput) {
26!
2452
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
21✔
2453
        QUERY_CHECK_CODE(code, lino, _end);
21!
2454
      }
2455
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
26✔
2456
      pWinInfo->sessionWin.win.skey = pStartTs[i];
26✔
2457
    }
2458
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
4,004✔
2459
    if (pEndTs) {
4,004!
2460
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
4,004✔
2461
    }
2462
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
4,004✔
2463
  }
2464
  (*pWinRos) = rows - start;
3,131✔
2465

2466
_end:
3,195✔
2467
  if (code != TSDB_CODE_SUCCESS) {
3,195!
2468
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2469
  }
2470
  return code;
3,195✔
2471
}
2472

2473
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
12,123✔
2474
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
2475
  *pResult = (SResultRow*)pWinInfo->pStatePos->pRowBuff;
12,123✔
2476
  // set time window for current result
2477
  (*pResult)->win = pWinInfo->sessionWin.win;
12,123✔
2478
  return setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
12,123✔
2479
}
2480

2481
int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
12,031✔
2482
                           int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
2483
                           SOperatorInfo* pOperator, int64_t winDelta) {
2484
  int32_t        code = TSDB_CODE_SUCCESS;
12,031✔
2485
  int32_t        lino = 0;
12,031✔
2486
  SExprSupp*     pSup = &pOperator->exprSupp;
12,031✔
2487
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
12,031✔
2488
  code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
12,031✔
2489
  QUERY_CHECK_CODE(code, lino, _end);
12,034!
2490

2491
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
12,034✔
2492
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
12,033✔
2493

2494
_end:
12,033✔
2495
  if (code != TSDB_CODE_SUCCESS) {
12,033!
2496
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2497
  }
2498
  return code;
12,033✔
2499
}
2500

2501
void doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
1,239✔
2502
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
1,239✔
2503
  SSessionKey hashKey = {0};
1,240✔
2504
  getSessionHashKey(pKey, &hashKey);
1,240✔
2505
  int32_t tmpRes = tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
1,240✔
2506
  qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
1,240!
2507
}
1,240✔
2508

2509
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
15,591✔
2510
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
15,591✔
2511
  if (pVal) {
15,596✔
2512
    SResultWindowInfo* pWin = pVal;
715✔
2513
    pWinInfo->isOutput = pWin->isOutput;
715✔
2514
  }
2515
}
15,596✔
2516

2517
void getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
3,499✔
2518
                           SResultWindowInfo* pNextWin) {
2519
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
3,499✔
2520
  pNextWin->isOutput = true;
3,497✔
2521
  setSessionWinOutputInfo(pStUpdated, pNextWin);
3,497✔
2522
  int32_t size = 0;
3,498✔
2523
  pNextWin->sessionWin = pCurWin->sessionWin;
3,498✔
2524
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin,
3,498✔
2525
                                                                  (void**)&pNextWin->pStatePos, &size);
3,498✔
2526
  if (code != TSDB_CODE_SUCCESS) {
3,499✔
2527
    SET_SESSION_WIN_INVALID(*pNextWin);
3,078✔
2528
  }
2529
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,499✔
2530
}
3,499✔
2531

2532
int32_t compactTimeWindow(SExprSupp* pSup, SStreamAggSupporter* pAggSup, STimeWindowAggSupp* pTwAggSup,
19✔
2533
                          SExecTaskInfo* pTaskInfo, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
2534
                          SSHashObj* pStUpdated, SSHashObj* pStDeleted, bool addGap) {
2535
  int32_t     code = TSDB_CODE_SUCCESS;
19✔
2536
  int32_t     lino = 0;
19✔
2537
  SResultRow* pCurResult = NULL;
19✔
2538
  int32_t     numOfOutput = pSup->numOfExprs;
19✔
2539
  code = initSessionOutputBuf(pCurWin, &pCurResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
19✔
2540
  QUERY_CHECK_CODE(code, lino, _end);
19!
2541

2542
  SResultRow* pWinResult = NULL;
19✔
2543
  code = initSessionOutputBuf(pNextWin, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
19✔
2544
  QUERY_CHECK_CODE(code, lino, _end);
19!
2545

2546
  pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, pNextWin->sessionWin.win.ekey);
19✔
2547
  memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
19✔
2548

2549
  int64_t winDelta = 0;
19✔
2550
  if (addGap) {
19✔
2551
    winDelta = pAggSup->gap;
15✔
2552
  }
2553
  updateTimeWindowInfo(&pTwAggSup->timeWindowData, &pCurWin->sessionWin.win, winDelta);
19✔
2554
  code = compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pTwAggSup->timeWindowData);
19✔
2555
  QUERY_CHECK_CODE(code, lino, _end);
19✔
2556

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

2560
  if (pNextWin->isOutput && pStDeleted) {
17!
2561
    qDebug("===stream=== save delete window info %" PRId64 ", %" PRIu64, pNextWin->sessionWin.win.skey,
16!
2562
           pNextWin->sessionWin.groupId);
2563
    code = saveDeleteRes(pStDeleted, pNextWin->sessionWin);
16✔
2564
    QUERY_CHECK_CODE(code, lino, _end);
16!
2565
  }
2566
  removeSessionResult(pAggSup, pStUpdated, pAggSup->pResultRows, &pNextWin->sessionWin);
17✔
2567
  doDeleteSessionWindow(pAggSup, &pNextWin->sessionWin);
17✔
2568
  releaseOutputBuf(pAggSup->pState, pNextWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
17✔
2569

2570
_end:
19✔
2571
  if (code != TSDB_CODE_SUCCESS) {
19✔
2572
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2573
  }
2574
  return code;
19✔
2575
}
2576

2577
static int32_t compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
3,380✔
2578
                                    SSHashObj* pStDeleted, bool addGap, int32_t* pWinNum) {
2579
  int32_t                        code = TSDB_CODE_SUCCESS;
3,380✔
2580
  int32_t                        lino = 0;
3,380✔
2581
  SExprSupp*                     pSup = &pOperator->exprSupp;
3,380✔
2582
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,380✔
2583
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
3,380✔
2584
  int32_t                        winNum = 0;
3,380✔
2585
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,380✔
2586
  SResultRow*                    pCurResult = NULL;
3,380✔
2587
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,380✔
2588
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,380✔
2589

2590
  // Just look for the window behind StartIndex
2591
  while (1) {
13✔
2592
    SResultWindowInfo winInfo = {0};
3,393✔
2593
    getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
3,393✔
2594
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
3,393✔
2595
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
15!
2596
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
3,378✔
2597
      break;
3,376✔
2598
    }
2599
    code =
2600
        compactTimeWindow(pSup, pAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, &winInfo, pStUpdated, pStDeleted, true);
15✔
2601
    QUERY_CHECK_CODE(code, lino, _end);
15✔
2602
    winNum++;
13✔
2603
  }
2604
  if (pWinNum) {
3,376✔
2605
    (*pWinNum) = winNum;
159✔
2606
  }
2607

2608
_end:
3,217✔
2609
  if (code != TSDB_CODE_SUCCESS) {
3,378✔
2610
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2611
  }
2612
  return code;
3,377✔
2613
}
2614

2615
static void compactSessionSemiWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin) {
24✔
2616
  SExprSupp*                     pSup = &pOperator->exprSupp;
24✔
2617
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
24✔
2618
  SStorageAPI*                   pAPI = &pOperator->pTaskInfo->storageAPI;
24✔
2619
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
24✔
2620
  SResultRow*                    pCurResult = NULL;
24✔
2621
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
24✔
2622
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
24✔
2623
  // Just look for the window behind StartIndex
2624
  while (1) {
×
2625
    SResultWindowInfo winInfo = {0};
24✔
2626
    getNextSessionWinInfo(pAggSup, NULL, pCurWin, &winInfo);
24✔
2627
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
24!
2628
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
×
2629
      releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
24✔
2630
      break;
24✔
2631
    }
2632
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
×
2633
    memcpy(pCurWin->pStatePos->pKey, &pCurWin->sessionWin, sizeof(SSessionKey));
×
2634
    doDeleteSessionWindow(pAggSup, &winInfo.sessionWin);
×
2635
    releaseOutputBuf(pAggSup->pState, winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2636
  }
2637
}
24✔
2638

2639
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
12,391✔
2640
  qDebug("===stream===try save session result skey:%" PRId64 ", ekey:%" PRId64 ".pos%d", pWinInfo->sessionWin.win.skey,
12,391✔
2641
         pWinInfo->sessionWin.win.ekey, pWinInfo->pStatePos->needFree);
2642
  return pAggSup->stateStore.streamStateSessionPut(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pStatePos,
12,391✔
2643
                                                   pAggSup->resultRowSize);
2644
}
2645

2646
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3,154✔
2647
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
2648
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3,154✔
2649
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3,154✔
2650
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
3,154✔
2651
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
3,154✔
2652
  int32_t                        code = TSDB_CODE_SUCCESS;
3,154✔
2653
  int32_t                        lino = 0;
3,154✔
2654
  SResultRow*                    pResult = NULL;
3,154✔
2655
  int32_t                        rows = pSDataBlock->info.rows;
3,154✔
2656
  int32_t                        winRows = 0;
3,154✔
2657
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3,154✔
2658

2659
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
3,154✔
2660
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
3,154✔
2661
  if (pAggSup->winRange.ekey <= 0) {
3,154!
2662
    pAggSup->winRange.ekey = INT64_MAX;
×
2663
  }
2664

2665
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
3,154✔
2666
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
3,154✔
2667
  SColumnInfoData* pEndTsCol = NULL;
3,154✔
2668
  if (hasEndTs) {
3,154✔
2669
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
540✔
2670
  } else {
2671
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,614✔
2672
  }
2673

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

2676
  void*            pPkVal = NULL;
3,154✔
2677
  int32_t          pkLen = 0;
3,154✔
2678
  SColumnInfoData* pPkColDataInfo = NULL;
3,154✔
2679
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
3,154✔
2680
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
270✔
2681
  }
2682

2683
  for (int32_t i = 0; i < rows;) {
6,366✔
2684
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
3,217!
2685
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2686
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2687
    }
2688
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
3,400✔
2689
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
183✔
2690
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
183✔
2691
      i++;
24✔
2692
      continue;
24✔
2693
    }
2694
    SResultWindowInfo winInfo = {0};
3,193✔
2695
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo);
3,193✔
2696
    QUERY_CHECK_CODE(code, lino, _end);
3,196!
2697

2698
    // coverity scan error
2699
    if (!winInfo.pStatePos) {
3,194!
2700
      continue;
×
2701
    }
2702
    setSessionWinOutputInfo(pStUpdated, &winInfo);
3,194✔
2703
    code = updateSessionWindowInfo(pAggSup, &winInfo, startTsCols, endTsCols, groupId, rows, i, pAggSup->gap,
3,194✔
2704
                                   pAggSup->pResultRows, pStUpdated, pStDeleted, &winRows);
2705
    QUERY_CHECK_CODE(code, lino, _end);
3,195!
2706

2707
    int64_t winDelta = 0;
3,195✔
2708
    if (addGap) {
3,195✔
2709
      winDelta = pAggSup->gap;
2,557✔
2710
    }
2711
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
3,195✔
2712
                              pOperator, winDelta);
2713
    QUERY_CHECK_CODE(code, lino, _end);
3,195!
2714

2715
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL);
3,195✔
2716
    QUERY_CHECK_CODE(code, lino, _end);
3,191✔
2717

2718
    code = saveSessionOutputBuf(pAggSup, &winInfo);
3,189✔
2719
    QUERY_CHECK_CODE(code, lino, _end);
3,188!
2720

2721
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
3,188!
2722
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
×
2723
      QUERY_CHECK_CODE(code, lino, _end);
×
2724
    }
2725
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
3,191✔
2726
      code = saveResult(winInfo, pStUpdated);
2,276✔
2727
      QUERY_CHECK_CODE(code, lino, _end);
2,275!
2728
    }
2729
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,190✔
2730
      winInfo.pStatePos->beUpdated = true;
623✔
2731
      SSessionKey key = {0};
623✔
2732
      getSessionHashKey(&winInfo.sessionWin, &key);
623✔
2733
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
623✔
2734
      QUERY_CHECK_CODE(code, lino, _end);
622!
2735
    }
2736

2737
    i += winRows;
3,189✔
2738
  }
2739

2740
_end:
3,149✔
2741
  if (code != TSDB_CODE_SUCCESS) {
3,151✔
2742
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2743
  }
2744
}
3,151✔
2745

2746
int32_t doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
1,100✔
2747
  int32_t          code = TSDB_CODE_SUCCESS;
1,100✔
2748
  int32_t          lino = 0;
1,100✔
2749
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,100✔
2750
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
1,100✔
2751
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,100✔
2752
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
1,100✔
2753
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,100✔
2754
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
1,100✔
2755
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
2,254✔
2756
    while (1) {
1,187✔
2757
      SSessionKey curWin = {0};
2,341✔
2758
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
2,341✔
2759
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
2,340✔
2760
        break;
1,154✔
2761
      }
2762
      doDeleteSessionWindow(pAggSup, &curWin);
1,186✔
2763
      if (result) {
1,187✔
2764
        code = saveDeleteInfo(result, curWin);
1,132✔
2765
        QUERY_CHECK_CODE(code, lino, _end);
1,132!
2766
      }
2767
    }
2768
  }
2769

2770
_end:
1,100✔
2771
  if (code != TSDB_CODE_SUCCESS) {
1,100!
2772
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2773
  }
2774
  return code;
1,100✔
2775
}
2776

2777
inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
5,569✔
2778
  SResultWindowInfo* pWinInfo1 = (SResultWindowInfo*)pKey1;
5,569✔
2779
  SResultWindowInfo* pWinInfo2 = (SResultWindowInfo*)pKey2;
5,569✔
2780
  SSessionKey*       pWin1 = &pWinInfo1->sessionWin;
5,569✔
2781
  SSessionKey*       pWin2 = &pWinInfo2->sessionWin;
5,569✔
2782

2783
  if (pWin1->groupId > pWin2->groupId) {
5,569✔
2784
    return 1;
2,167✔
2785
  } else if (pWin1->groupId < pWin2->groupId) {
3,402✔
2786
    return -1;
1,820✔
2787
  }
2788

2789
  if (pWin1->win.skey > pWin2->win.skey) {
1,582✔
2790
    return 1;
841✔
2791
  } else if (pWin1->win.skey < pWin2->win.skey) {
741!
2792
    return -1;
741✔
2793
  }
2794

2795
  return 0;
×
2796
}
2797

2798
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
18,205✔
2799
  int32_t        code = TSDB_CODE_SUCCESS;
18,205✔
2800
  int32_t        lino = 0;
18,205✔
2801
  SStorageAPI*   pAPI = &pOp->pTaskInfo->storageAPI;
18,205✔
2802
  SExecTaskInfo* pTaskInfo = pOp->pTaskInfo;
18,205✔
2803

2804
  blockDataCleanup(pBlock);
18,205✔
2805
  int32_t size = tSimpleHashGetSize(pStDeleted);
18,205✔
2806
  if (size == 0) {
18,205✔
2807
    return;
17,690✔
2808
  }
2809
  code = blockDataEnsureCapacity(pBlock, size);
515✔
2810
  QUERY_CHECK_CODE(code, lino, _end);
515!
2811

2812
  int32_t iter = 0;
515✔
2813
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
1,105✔
2814
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
590!
2815
      break;
×
2816
    }
2817
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
590!
2818
    SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
590✔
2819
    code = colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
590✔
2820
    QUERY_CHECK_CODE(code, lino, _end);
590!
2821

2822
    SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
590✔
2823
    code = colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
590✔
2824
    QUERY_CHECK_CODE(code, lino, _end);
590!
2825

2826
    SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
590✔
2827
    colDataSetNULL(pUidCol, pBlock->info.rows);
590!
2828

2829
    SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
590✔
2830
    code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false);
590✔
2831
    QUERY_CHECK_CODE(code, lino, _end);
590!
2832

2833
    SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
590✔
2834
    colDataSetNULL(pCalStCol, pBlock->info.rows);
590!
2835

2836
    SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
590✔
2837
    colDataSetNULL(pCalEdCol, pBlock->info.rows);
590!
2838

2839
    SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
590✔
2840
    if (!pTableCol) {
590!
2841
      QUERY_CHECK_CODE(code, lino, _end);
×
2842
    }
2843

2844
    void*   tbname = NULL;
590✔
2845
    int32_t winCode = TSDB_CODE_SUCCESS;
590✔
2846
    code = pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, res->groupId, &tbname, false,
590✔
2847
                                                  &winCode);
2848
    QUERY_CHECK_CODE(code, lino, _end);
590!
2849

2850
    if (winCode != TSDB_CODE_SUCCESS) {
590✔
2851
      colDataSetNULL(pTableCol, pBlock->info.rows);
150!
2852
    } else {
2853
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
2854
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
440✔
2855
      code = colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
440✔
2856
      QUERY_CHECK_CODE(code, lino, _end);
440!
2857
      pAPI->stateStore.streamStateFreeVal(tbname);
440✔
2858
    }
2859
    pBlock->info.rows += 1;
590✔
2860
  }
2861

2862
_end:
515✔
2863
  if ((*Ite) == NULL) {
515!
2864
    tSimpleHashClear(pStDeleted);
515✔
2865
  }
2866

2867
  if (code != TSDB_CODE_SUCCESS) {
515!
2868
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
2869
  }
2870
}
2871

2872
static int32_t rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
56✔
2873
  int32_t        winCode = TSDB_CODE_SUCCESS;
56✔
2874
  int32_t        code = TSDB_CODE_SUCCESS;
56✔
2875
  int32_t        lino = 0;
56✔
2876
  SExprSupp*     pSup = &pOperator->exprSupp;
56✔
2877
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
56✔
2878
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
56✔
2879

2880
  int32_t                        size = taosArrayGetSize(pWinArray);
56✔
2881
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
56✔
2882
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
56✔
2883
  int32_t                        numOfOutput = pSup->numOfExprs;
56✔
2884
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
56✔
2885

2886
  for (int32_t i = 0; i < size; i++) {
117✔
2887
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
61✔
2888
    int32_t           num = 0;
61✔
2889
    SResultWindowInfo parentWin = {0};
61✔
2890
    for (int32_t j = 0; j < numOfChild; j++) {
279✔
2891
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
218✔
2892
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
218✔
2893
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
218✔
2894
      SSessionKey                    chWinKey = {0};
218✔
2895
      getSessionHashKey(pWinKey, &chWinKey);
218✔
2896
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
218✔
2897
      SResultRow*      pResult = NULL;
218✔
2898
      SResultRow*      pChResult = NULL;
218✔
2899
      while (1) {
27✔
2900
        SResultWindowInfo childWin = {0};
245✔
2901
        childWin.sessionWin = *pWinKey;
245✔
2902
        getSessionWinBuf(pChAggSup, pCur, &childWin, &winCode);
245✔
2903

2904
        if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
245!
2905
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
×
2906
          continue;
×
2907
        }
2908

2909
        if (winCode == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
245✔
2910
          if (num == 0) {
27!
2911
            code = setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin);
27✔
2912
            QUERY_CHECK_CODE(code, lino, _end);
27!
2913

2914
            parentWin.sessionWin = childWin.sessionWin;
27✔
2915
            memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
27✔
2916
            code = initSessionOutputBuf(&parentWin, &pResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
27✔
2917
            QUERY_CHECK_CODE(code, lino, _end);
27!
2918
          }
2919
          num++;
27✔
2920
          parentWin.sessionWin.win.skey = TMIN(parentWin.sessionWin.win.skey, childWin.sessionWin.win.skey);
27✔
2921
          parentWin.sessionWin.win.ekey = TMAX(parentWin.sessionWin.win.ekey, childWin.sessionWin.win.ekey);
27✔
2922
          memcpy(parentWin.pStatePos->pKey, &parentWin.sessionWin, sizeof(SSessionKey));
27✔
2923

2924
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap);
27✔
2925
          code = initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
27✔
2926
                                      pChild->exprSupp.rowEntryInfoOffset);
2927
          QUERY_CHECK_CODE(code, lino, _end);
27!
2928

2929
          code = compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo,
27✔
2930
                                  &pInfo->twAggSup.timeWindowData);
2931
          QUERY_CHECK_CODE(code, lino, _end);
27!
2932

2933
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL);
27✔
2934
          QUERY_CHECK_CODE(code, lino, _end);
27!
2935

2936
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
27✔
2937
        } else {
2938
          releaseOutputBuf(pAggSup->pState, childWin.pStatePos, &pAggSup->stateStore);
218✔
2939
          break;
218✔
2940
        }
2941
      }
2942
      pAPI->stateStore.streamStateFreeCur(pCur);
218✔
2943
    }
2944
    if (num > 0) {
61✔
2945
      code = saveResult(parentWin, pStUpdated);
27✔
2946
      QUERY_CHECK_CODE(code, lino, _end);
27!
2947

2948
      code = saveSessionOutputBuf(pAggSup, &parentWin);
27✔
2949
      QUERY_CHECK_CODE(code, lino, _end);
27!
2950
    }
2951
  }
2952

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

2960
int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) {
11,198✔
2961
  int32_t code = TSDB_CODE_SUCCESS;
11,198✔
2962
  int32_t lino = 0;
11,198✔
2963
  void*   pIte = NULL;
11,198✔
2964
  int32_t iter = 0;
11,198✔
2965
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
12,765✔
2966
    SResultWindowInfo* pWinInfo = pIte;
1,567✔
2967
    if (isCloseWindow(&pWinInfo->sessionWin.win, pTwSup)) {
1,567✔
2968
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
470!
2969
        code = saveResult(*pWinInfo, pClosed);
470✔
2970
        QUERY_CHECK_CODE(code, lino, _end);
470!
2971
      }
2972
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
470!
2973
      code = tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
470✔
2974
      QUERY_CHECK_CODE(code, lino, _end);
470!
2975
    }
2976
  }
2977
_end:
11,202✔
2978
  if (code != TSDB_CODE_SUCCESS) {
11,202!
2979
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2980
  }
2981
  return code;
11,202✔
2982
}
2983

2984
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
4,122✔
2985
  int32_t code = TSDB_CODE_SUCCESS;
4,122✔
2986
  int32_t lino = 0;
4,122✔
2987

2988
  int32_t size = taosArrayGetSize(pChildren);
4,122✔
2989
  for (int32_t i = 0; i < size; i++) {
4,770✔
2990
    SOperatorInfo*                 pChildOp = taosArrayGetP(pChildren, i);
648✔
2991
    SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
648✔
2992
    pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
648✔
2993
    code = closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
648✔
2994
    QUERY_CHECK_CODE(code, lino, _end);
648!
2995
  }
2996
_end:
4,122✔
2997
  if (code != TSDB_CODE_SUCCESS) {
4,122!
2998
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2999
  }
3000
  return code;
4,122✔
3001
}
3002

3003
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
203✔
3004
  int32_t code = TSDB_CODE_SUCCESS;
203✔
3005
  int32_t lino = 0;
203✔
3006
  void*   pIte = NULL;
203✔
3007
  int32_t iter = 0;
203✔
3008
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
293✔
3009
    SResultWindowInfo* pWinInfo = pIte;
90✔
3010
    if (!pWinInfo->pStatePos->beUpdated) {
90✔
3011
      continue;
4✔
3012
    }
3013
    pWinInfo->pStatePos->beUpdated = false;
86✔
3014
    code = saveResult(*pWinInfo, pStUpdated);
86✔
3015
    QUERY_CHECK_CODE(code, lino, _end);
86!
3016
  }
3017

3018
_end:
203✔
3019
  if (code != TSDB_CODE_SUCCESS) {
203!
3020
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3021
  }
3022
  return code;
203✔
3023
}
3024

3025
int32_t copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
1,057✔
3026
  int32_t code = TSDB_CODE_SUCCESS;
1,057✔
3027
  int32_t lino = 0;
1,057✔
3028
  int32_t size = taosArrayGetSize(pResWins);
1,057✔
3029
  for (int32_t i = 0; i < size; i++) {
2,216✔
3030
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
1,158✔
3031
    if (!pWinKey) continue;
1,158!
3032
    SSessionKey winInfo = {0};
1,158✔
3033
    getSessionHashKey(pWinKey, &winInfo);
1,158✔
3034
    code = tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
1,158✔
3035
    QUERY_CHECK_CODE(code, lino, _end);
1,158!
3036
  }
3037

3038
_end:
1,058✔
3039
  if (code != TSDB_CODE_SUCCESS) {
1,058!
3040
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3041
  }
3042
  return code;
1,058✔
3043
}
3044

3045
// the allocated memory comes from outer function.
3046
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
11,139✔
3047
  pGroupResInfo->pRows = pArrayList;
11,139✔
3048
  pGroupResInfo->index = 0;
11,139✔
3049
  pGroupResInfo->pBuf = NULL;
11,139✔
3050
  pGroupResInfo->freeItem = false;
11,139✔
3051
}
11,139✔
3052

3053
int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
5,816✔
3054
                                    SGroupResInfo* pGroupResInfo) {
3055
  int32_t         code = TSDB_CODE_SUCCESS;
5,816✔
3056
  int32_t         lino = 0;
5,816✔
3057
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
5,816✔
3058
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
5,816✔
3059
  SExprInfo*      pExprInfo = pSup->pExprInfo;
5,816✔
3060
  int32_t         numOfExprs = pSup->numOfExprs;
5,816✔
3061
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
5,816✔
3062
  SqlFunctionCtx* pCtx = pSup->pCtx;
5,816✔
3063

3064
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
5,816✔
3065

3066
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
12,519✔
3067
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
8,430✔
3068
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
8,430✔
3069
    SResultRow*        pRow = NULL;
8,430✔
3070
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
8,430✔
3071

3072
    if (pBlock->info.id.groupId == 0) {
8,430✔
3073
      pBlock->info.id.groupId = pKey->groupId;
6,083✔
3074

3075
      void*   tbname = NULL;
6,083✔
3076
      int32_t winCode = TSDB_CODE_SUCCESS;
6,083✔
3077
      code = pAPI->stateStore.streamStateGetParName((void*)pTaskInfo->streamInfo.pState, pBlock->info.id.groupId,
6,083✔
3078
                                                    &tbname, false, &winCode);
3079
      QUERY_CHECK_CODE(code, lino, _end);
6,081!
3080

3081
      if (winCode != TSDB_CODE_SUCCESS) {
6,081✔
3082
        pBlock->info.parTbName[0] = 0;
1,582✔
3083
      } else {
3084
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,499✔
3085
      }
3086
      pAPI->stateStore.streamStateFreeVal(tbname);
6,081✔
3087
    } else {
3088
      // current value belongs to different group, it can't be packed into one datablock
3089
      if (pBlock->info.id.groupId != pKey->groupId) {
2,347✔
3090
        break;
1,715✔
3091
      }
3092
    }
3093

3094
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
6,714✔
3095
    QUERY_CHECK_CODE(code, lino, _end);
6,714!
3096

3097
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
6,714✔
3098
    // no results, continue to check the next one
3099
    if (pRow->numOfRows == 0) {
6,716!
3100
      pGroupResInfo->index += 1;
×
3101
      continue;
×
3102
    }
3103

3104
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,716!
3105
      break;
×
3106
    }
3107

3108
    pGroupResInfo->index += 1;
6,716✔
3109

3110
    for (int32_t j = 0; j < numOfExprs; ++j) {
114,353✔
3111
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
107,650✔
3112

3113
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
107,650✔
3114
      if (pCtx[j].fpSet.finalize) {
107,655✔
3115
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
98,750✔
3116
        if (TAOS_FAILED(tmpRes)) {
98,752!
3117
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
3118
          QUERY_CHECK_CODE(code, lino, _end);
×
3119
        }
3120
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
8,905!
3121
        // do nothing, todo refactor
3122
      } else {
3123
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
3124
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
3125
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
8,966✔
3126
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
8,966✔
3127
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
17,928✔
3128
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
8,966✔
3129
          QUERY_CHECK_CODE(code, lino, _end);
8,962!
3130
        }
3131
      }
3132
    }
3133

3134
    pBlock->info.dataLoad = 1;
6,703✔
3135
    pBlock->info.rows += pRow->numOfRows;
6,703✔
3136
  }
3137
  code = blockDataUpdateTsWindow(pBlock, 0);
5,804✔
3138
  QUERY_CHECK_CODE(code, lino, _end);
5,816!
3139

3140
_end:
5,816✔
3141
  if (code != TSDB_CODE_SUCCESS) {
5,816!
3142
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3143
  }
3144
  return code;
5,816✔
3145
}
3146

3147
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo, SSDataBlock* pBlock) {
17,686✔
3148
  int32_t        code = TSDB_CODE_SUCCESS;
17,686✔
3149
  int32_t        lino = 0;
17,686✔
3150
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
17,686✔
3151
  // set output datablock version
3152
  pBlock->info.version = pTaskInfo->version;
17,686✔
3153

3154
  blockDataCleanup(pBlock);
17,686✔
3155
  if (!hasRemainResults(pGroupResInfo)) {
17,682✔
3156
    cleanupGroupResInfo(pGroupResInfo);
11,867✔
3157
    goto _end;
11,875✔
3158
  }
3159

3160
  // clear the existed group id
3161
  pBlock->info.id.groupId = 0;
5,816✔
3162
  code = buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
5,816✔
3163
  QUERY_CHECK_CODE(code, lino, _end);
5,816!
3164

3165
  if (pBlock->info.rows == 0) {
5,816!
3166
    cleanupGroupResInfo(pGroupResInfo);
×
3167
  }
3168

3169
_end:
5,816✔
3170
  if (code != TSDB_CODE_SUCCESS) {
17,691!
3171
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3172
  }
3173
}
17,691✔
3174

3175
static int32_t buildSessionResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,659✔
3176
  int32_t                        code = TSDB_CODE_SUCCESS;
7,659✔
3177
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
7,659✔
3178
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
7,659✔
3179
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
7,659✔
3180
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
7,659✔
3181
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
7,659✔
3182
  if (pInfo->pDelRes->info.rows > 0) {
7,657✔
3183
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
252✔
3184
    (*ppRes) = pInfo->pDelRes;
252✔
3185
    return code;
252✔
3186
  }
3187

3188
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
7,405✔
3189
  if (pBInfo->pRes->info.rows > 0) {
7,407✔
3190
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,974✔
3191
    (*ppRes) = pBInfo->pRes;
1,974✔
3192
    return code;
1,974✔
3193
  }
3194
  (*ppRes) = NULL;
5,433✔
3195
  return code;
5,433✔
3196
}
3197

3198
int32_t getMaxTsWins(const SArray* pAllWins, SArray* pMaxWins) {
378✔
3199
  int32_t code = TSDB_CODE_SUCCESS;
378✔
3200
  int32_t lino = 0;
378✔
3201
  int32_t size = taosArrayGetSize(pAllWins);
378✔
3202
  if (size == 0) {
378✔
3203
    goto _end;
245✔
3204
  }
3205
  SResultWindowInfo* pWinInfo = taosArrayGet(pAllWins, size - 1);
133✔
3206
  SSessionKey*       pSeKey = &pWinInfo->sessionWin;
133✔
3207
  void*              tmp = taosArrayPush(pMaxWins, pSeKey);
133✔
3208
  if (!tmp) {
133!
3209
    code = terrno;
×
3210
    QUERY_CHECK_CODE(code, lino, _end);
×
3211
  }
3212

3213
  if (pSeKey->groupId == 0) {
133✔
3214
    goto _end;
17✔
3215
  }
3216
  uint64_t preGpId = pSeKey->groupId;
116✔
3217
  for (int32_t i = size - 2; i >= 0; i--) {
442✔
3218
    pWinInfo = taosArrayGet(pAllWins, i);
326✔
3219
    pSeKey = &pWinInfo->sessionWin;
326✔
3220
    if (preGpId != pSeKey->groupId) {
326✔
3221
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
204✔
3222
      if (!tmp) {
204!
3223
        code = terrno;
×
3224
        QUERY_CHECK_CODE(code, lino, _end);
×
3225
      }
3226
      preGpId = pSeKey->groupId;
204✔
3227
    }
3228
  }
3229

3230
_end:
116✔
3231
  if (code != TSDB_CODE_SUCCESS) {
378!
3232
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3233
  }
3234
  return code;
378✔
3235
}
3236

3237
int32_t encodeSSessionKey(void** buf, SSessionKey* key) {
12✔
3238
  int32_t tlen = 0;
12✔
3239
  tlen += encodeSTimeWindow(buf, &key->win);
12✔
3240
  tlen += taosEncodeFixedU64(buf, key->groupId);
12✔
3241
  return tlen;
12✔
3242
}
3243

3244
void* decodeSSessionKey(void* buf, SSessionKey* key) {
4✔
3245
  buf = decodeSTimeWindow(buf, &key->win);
4✔
3246
  buf = taosDecodeFixedU64(buf, &key->groupId);
4!
3247
  return buf;
4✔
3248
}
3249

3250
int32_t encodeSResultWindowInfo(void** buf, SResultWindowInfo* key, int32_t outLen) {
6✔
3251
  int32_t tlen = 0;
6✔
3252
  tlen += taosEncodeFixedBool(buf, key->isOutput);
6✔
3253
  tlen += encodeSSessionKey(buf, &key->sessionWin);
6✔
3254
  return tlen;
6✔
3255
}
3256

3257
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
2✔
3258
  buf = taosDecodeFixedBool(buf, &key->isOutput);
2✔
3259
  buf = decodeSSessionKey(buf, &key->sessionWin);
2✔
3260
  return buf;
2✔
3261
}
3262

3263
int32_t doStreamSessionEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
×
3264
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3265
  if (!pInfo) {
×
3266
    return 0;
×
3267
  }
3268

3269
  void* pData = (buf == NULL) ? NULL : *buf;
×
3270

3271
  // 1.streamAggSup.pResultRows
3272
  int32_t tlen = 0;
×
3273
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
×
3274
  tlen += taosEncodeFixedI32(buf, mapSize);
×
3275
  void*   pIte = NULL;
×
3276
  size_t  keyLen = 0;
×
3277
  int32_t iter = 0;
×
3278
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
×
3279
    void* key = tSimpleHashGetKey(pIte, &keyLen);
×
3280
    tlen += encodeSSessionKey(buf, key);
×
3281
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
×
3282
  }
3283

3284
  // 2.twAggSup
3285
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3286

3287
  // 3.pChildren
3288
  int32_t size = taosArrayGetSize(pInfo->pChildren);
×
3289
  tlen += taosEncodeFixedI32(buf, size);
×
3290
  for (int32_t i = 0; i < size; i++) {
×
3291
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3292
    tlen += doStreamSessionEncodeOpState(buf, 0, pChOp, false);
×
3293
  }
3294

3295
  // 4.dataVersion
3296
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
3297

3298
  // 5.checksum
3299
  if (isParent) {
×
3300
    if (buf) {
×
3301
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
×
3302
      tlen += taosEncodeFixedU32(buf, cksum);
×
3303
    } else {
3304
      tlen += sizeof(uint32_t);
×
3305
    }
3306
  }
3307

3308
  return tlen;
×
3309
}
3310

3311
int32_t doStreamSessionDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
3312
  int32_t                        code = TSDB_CODE_SUCCESS;
×
3313
  int32_t                        lino = 0;
×
3314
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
3315
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
×
3316
  if (!pInfo) {
×
3317
    code = TSDB_CODE_FAILED;
×
3318
    QUERY_CHECK_CODE(code, lino, _end);
×
3319
  }
3320
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
×
3321

3322
  // 5.checksum
3323
  if (isParent) {
×
3324
    int32_t dataLen = len - sizeof(uint32_t);
×
3325
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
3326
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
3327
      qError("stream session state is invalid");
×
3328
      code = TSDB_CODE_FAILED;
×
3329
      QUERY_CHECK_CODE(code, lino, _end);
×
3330
    }
3331
  }
3332

3333
  // 1.streamAggSup.pResultRows
3334
  int32_t mapSize = 0;
×
3335
  buf = taosDecodeFixedI32(buf, &mapSize);
×
3336
  for (int32_t i = 0; i < mapSize; i++) {
×
3337
    SResultWindowInfo winfo = {0};
×
3338
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
3339
    int32_t winCode = TSDB_CODE_SUCCESS;
×
3340
    code = pAggSup->stateStore.streamStateSessionAddIfNotExist(
×
3341
        pAggSup->pState, &winfo.sessionWin, pAggSup->gap, (void**)&winfo.pStatePos, &pAggSup->resultRowSize, &winCode);
3342
    QUERY_CHECK_CODE(code, lino, _end);
×
3343
    QUERY_CHECK_CONDITION((winCode == TSDB_CODE_SUCCESS), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
3344

3345
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
3346
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
3347
                          sizeof(SResultWindowInfo));
3348
    QUERY_CHECK_CODE(code, lino, _end);
×
3349
  }
3350

3351
  // 2.twAggSup
3352
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
3353

3354
  // 3.pChildren
3355
  int32_t size = 0;
×
3356
  buf = taosDecodeFixedI32(buf, &size);
×
3357
  for (int32_t i = 0; i < size; i++) {
×
3358
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
3359
    code = doStreamSessionDecodeOpState(buf, 0, pChOp, false, &buf);
×
3360
    QUERY_CHECK_CODE(code, lino, _end);
×
3361
  }
3362

3363
  // 4.dataVersion
3364
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
3365
  if (ppBuf) {
×
3366
    (*ppBuf) = buf;
×
3367
  }
3368

3369
_end:
×
3370
  if (code != TSDB_CODE_SUCCESS) {
×
3371
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3372
  }
3373
  return code;
×
3374
}
3375

3376
void doStreamSessionSaveCheckpoint(SOperatorInfo* pOperator) {
191✔
3377
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3378
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
191!
3379
    int32_t len = doStreamSessionEncodeOpState(NULL, 0, pOperator, true);
×
3380
    void*   buf = taosMemoryCalloc(1, len);
×
3381
    if (!buf) {
×
3382
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
3383
      return;
×
3384
    }
3385
    void* pBuf = buf;
×
3386
    len = doStreamSessionEncodeOpState(&pBuf, len, pOperator, true);
×
3387
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
×
3388
                                                       strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), buf, len);
3389
    taosMemoryFree(buf);
×
3390
    saveStreamOperatorStateComplete(&pInfo->basic);
×
3391
  }
3392
}
3393

3394
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
86✔
3395
  void*   pIte = NULL;
86✔
3396
  int32_t iter = 0;
86✔
3397
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
172✔
3398
    SResultWindowInfo* pResInfo = pIte;
86✔
3399
    pResInfo->pStatePos->beUsed = true;
86✔
3400
  }
3401
}
86✔
3402

3403
int32_t copyDeleteSessionKey(SSHashObj* source, SSHashObj* dest) {
×
3404
  int32_t code = TSDB_CODE_SUCCESS;
×
3405
  int32_t lino = 0;
×
3406
  if (tSimpleHashGetSize(source) == 0) {
×
3407
    goto _end;
×
3408
  }
3409
  void*   pIte = NULL;
×
3410
  int32_t iter = 0;
×
3411
  size_t  keyLen = 0;
×
3412
  while ((pIte = tSimpleHashIterate(source, pIte, &iter)) != NULL) {
×
3413
    SSessionKey* pKey = tSimpleHashGetKey(pIte, &keyLen);
×
3414
    code = saveDeleteRes(dest, *pKey);
×
3415
    QUERY_CHECK_CODE(code, lino, _end);
×
3416
  }
3417
  tSimpleHashClear(source);
×
3418

3419
_end:
×
3420
  if (code != TSDB_CODE_SUCCESS) {
×
3421
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3422
  }
3423
  return code;
×
3424
}
3425

3426
static int32_t doStreamSessionAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
6,856✔
3427
  int32_t                        code = TSDB_CODE_SUCCESS;
6,856✔
3428
  int32_t                        lino = 0;
6,856✔
3429
  SExprSupp*                     pSup = &pOperator->exprSupp;
6,856✔
3430
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
6,856✔
3431
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
6,856✔
3432
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
6,856✔
3433
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
6,856✔
3434
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
6,856✔
3435
  if (pOperator->status == OP_EXEC_DONE) {
6,857!
3436
    (*ppRes) = NULL;
×
3437
    return code;
×
3438
  } else if (pOperator->status == OP_RES_TO_RETURN) {
6,857✔
3439
    SSDataBlock* opRes = NULL;
1,900✔
3440
    code = buildSessionResult(pOperator, &opRes);
1,900✔
3441
    QUERY_CHECK_CODE(code, lino, _end);
1,901!
3442
    if (opRes) {
1,901✔
3443
      (*ppRes) = opRes;
395✔
3444
      return code;
1,900✔
3445
    }
3446

3447
    if (pInfo->recvGetAll) {
1,506✔
3448
      pInfo->recvGetAll = false;
83✔
3449
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
83✔
3450
    }
3451

3452
    if (pInfo->reCkBlock) {
1,506!
3453
      pInfo->reCkBlock = false;
×
3454
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
3455
      (*ppRes) = pInfo->pCheckpointRes;
×
3456
      return code;
×
3457
    }
3458

3459
    setStreamOperatorCompleted(pOperator);
1,506✔
3460
    (*ppRes) = NULL;
1,505✔
3461
    return code;
1,505✔
3462
  }
3463

3464
  SOperatorInfo* downstream = pOperator->pDownstream[0];
4,957✔
3465
  if (!pInfo->pUpdated) {
4,957✔
3466
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
4,121✔
3467
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
4,121!
3468
  }
3469
  if (!pInfo->pStUpdated) {
4,957✔
3470
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
4,050✔
3471
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
4,051✔
3472
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
4,048!
3473
  }
3474
  while (1) {
3,305✔
3475
    SSDataBlock* pBlock = NULL;
8,260✔
3476
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
8,260✔
3477
    QUERY_CHECK_CODE(code, lino, _end);
8,262!
3478

3479
    if (pBlock == NULL) {
8,262✔
3480
      break;
4,122✔
3481
    }
3482
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
4,140✔
3483
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
4,142✔
3484

3485
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
4,143✔
3486
        pBlock->info.type == STREAM_CLEAR) {
3,904✔
3487
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
400✔
3488
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
400!
3489
      // gap must be 0
3490
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
400✔
3491
      QUERY_CHECK_CODE(code, lino, _end);
400!
3492

3493
      removeSessionResults(pAggSup, pInfo->pStUpdated, pWins);
400✔
3494
      if (IS_FINAL_SESSION_OP(pOperator)) {
400✔
3495
        int32_t                        childIndex = getChildIndex(pBlock);
56✔
3496
        SOperatorInfo*                 pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
56✔
3497
        SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
56✔
3498
        // gap must be 0
3499
        code = doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
56✔
3500
        QUERY_CHECK_CODE(code, lino, _end);
56!
3501

3502
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
56✔
3503
        QUERY_CHECK_CODE(code, lino, _end);
56!
3504
      }
3505
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
400✔
3506
      QUERY_CHECK_CODE(code, lino, _end);
400!
3507

3508
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
400!
3509
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
×
3510
        QUERY_CHECK_CODE(code, lino, _end);
×
3511
      }
3512
      taosArrayDestroy(pWins);
400✔
3513
      continue;
768✔
3514
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,743✔
3515
      pInfo->recvGetAll = true;
192✔
3516
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
192✔
3517
      QUERY_CHECK_CODE(code, lino, _end);
192!
3518
      continue;
192✔
3519
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,551✔
3520
      (*ppRes) = pBlock;
835✔
3521
      return code;
835✔
3522
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
2,716✔
3523
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
176✔
3524
      doStreamSessionSaveCheckpoint(pOperator);
176✔
3525
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
176✔
3526
      QUERY_CHECK_CODE(code, lino, _end);
176!
3527

3528
      continue;
176✔
3529
    } else {
3530
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
2,540!
3531
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3532
        QUERY_CHECK_CODE(code, lino, _end);
×
3533
      }
3534
    }
3535

3536
    if (pInfo->scalarSupp.pExprInfo != NULL) {
2,540✔
3537
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
3538
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
3539
      QUERY_CHECK_CODE(code, lino, _end);
13!
3540
    }
3541
    // the pDataBlock are always the same one, no need to call this again
3542
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
2,540✔
3543
    QUERY_CHECK_CODE(code, lino, _end);
2,543!
3544

3545
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_SESSION_OP(pOperator),
2,543✔
3546
                           true);
3547
    if (IS_FINAL_SESSION_OP(pOperator)) {
2,537✔
3548
      int32_t chIndex = getChildIndex(pBlock);
270✔
3549
      int32_t size = taosArrayGetSize(pInfo->pChildren);
270✔
3550
      // if chIndex + 1 - size > 0, add new child
3551
      for (int32_t i = 0; i < chIndex + 1 - size; i++) {
270!
3552
        SOperatorInfo* pChildOp = NULL;
×
3553
        code = createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0, NULL, &pChildOp);
×
3554
        if (pChildOp == NULL || code != 0) {
×
3555
          qError("%s create stream child of final session error", GET_TASKID(pTaskInfo));
×
3556
          code = TSDB_CODE_FAILED;
×
3557
          QUERY_CHECK_CODE(code, lino, _end);
×
3558
        }
3559

3560
        void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
×
3561
        if (!tmp) {
×
3562
          code = terrno;
×
3563
          QUERY_CHECK_CODE(code, lino, _end);
×
3564
        }
3565
      }
3566

3567
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
270✔
3568
      code = setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
270✔
3569
      QUERY_CHECK_CODE(code, lino, _end);
270!
3570
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
270✔
3571
    }
3572
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
2,537✔
3573
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
2,537✔
3574
  }
3575
  // restore the value
3576
  pOperator->status = OP_RES_TO_RETURN;
4,122✔
3577

3578
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
4,122✔
3579
  QUERY_CHECK_CODE(code, lino, _end);
4,122!
3580

3581
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
4,122✔
3582
  QUERY_CHECK_CODE(code, lino, _end);
4,122!
3583

3584
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
4,122✔
3585
  QUERY_CHECK_CODE(code, lino, _end);
4,119!
3586

3587
  if (!pInfo->destHasPrimaryKey) {
4,119!
3588
    removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
4,123✔
3589
  }
3590
  if (pInfo->isHistoryOp) {
4,119✔
3591
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
191✔
3592
    QUERY_CHECK_CODE(code, lino, _end);
191!
3593
  }
3594
  if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
4,119!
3595
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pStDeleted);
×
3596
    QUERY_CHECK_CODE(code, lino, _end);
×
3597
  }
3598
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
4,119✔
3599
  pInfo->pUpdated = NULL;
4,118✔
3600
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
4,118✔
3601
  QUERY_CHECK_CODE(code, lino, _end);
4,123!
3602

3603
  SSDataBlock* opRes = NULL;
4,123✔
3604
  code = buildSessionResult(pOperator, &opRes);
4,123✔
3605
  QUERY_CHECK_CODE(code, lino, _end);
4,121!
3606
  if (opRes) {
4,121✔
3607
    (*ppRes) = opRes;
1,505✔
3608
    return code;
1,505✔
3609
  }
3610

3611
_end:
2,616✔
3612
  if (code != TSDB_CODE_SUCCESS) {
2,616!
3613
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3614
    pTaskInfo->code = code;
×
3615
    T_LONG_JMP(pTaskInfo->env, code);
×
3616
  }
3617
  setStreamOperatorCompleted(pOperator);
2,616✔
3618
  (*ppRes) = NULL;
2,613✔
3619
  return code;
2,613✔
3620
}
3621

3622
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
×
3623
  SSDataBlock* pRes = NULL;
×
3624
  int32_t      code = doStreamSessionAggNext(pOperator, &pRes);
×
3625
  return pRes;
×
3626
}
3627

3628
void streamSessionReleaseState(SOperatorInfo* pOperator) {
191✔
3629
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
191✔
3630
  int32_t                        winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
191✔
3631
  int32_t                        resSize = winSize + sizeof(TSKEY);
191✔
3632
  char*                          pBuff = taosMemoryCalloc(1, resSize);
191!
3633
  if (!pBuff) {
191!
3634
    return;
×
3635
  }
3636
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
191✔
3637
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
191✔
3638
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_STATE_NAME,
191✔
3639
                                                     strlen(STREAM_SESSION_OP_STATE_NAME), pBuff, resSize);
3640
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
190✔
3641
  taosMemoryFreeClear(pBuff);
191!
3642
  SOperatorInfo* downstream = pOperator->pDownstream[0];
191✔
3643
  if (downstream->fpSet.releaseStreamStateFn) {
191!
3644
    downstream->fpSet.releaseStreamStateFn(downstream);
191✔
3645
  }
3646
}
3647

3648
void resetWinRange(STimeWindow* winRange) {
349✔
3649
  winRange->skey = INT64_MIN;
349✔
3650
  winRange->ekey = INT64_MAX;
349✔
3651
}
349✔
3652

3653
int32_t getSessionWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SResultWindowInfo* pWinInfo) {
337✔
3654
  int32_t code = TSDB_CODE_SUCCESS;
337✔
3655
  int32_t lino = 0;
337✔
3656
  int32_t rowSize = pAggSup->resultRowSize;
337✔
3657
  int32_t winCode = TSDB_CODE_SUCCESS;
337✔
3658
  code = pAggSup->stateStore.streamStateSessionGet(pAggSup->pState, pKey, (void**)&pWinInfo->pStatePos, &rowSize,
337✔
3659
                                                   &winCode);
3660
  QUERY_CHECK_CODE(code, lino, _end);
337!
3661

3662
  if (winCode == TSDB_CODE_SUCCESS) {
337!
3663
    pWinInfo->sessionWin = *pKey;
337✔
3664
    pWinInfo->isOutput = true;
337✔
3665
    if (pWinInfo->pStatePos->needFree) {
337!
3666
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pWinInfo->sessionWin);
337✔
3667
    }
3668
  } else {
3669
    SET_SESSION_WIN_INVALID((*pWinInfo));
×
3670
  }
3671

3672
_end:
337✔
3673
  if (code != TSDB_CODE_SUCCESS) {
337!
3674
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3675
  }
3676
  return code;
337✔
3677
}
3678

3679
void reloadAggSupFromDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup) {
631✔
3680
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
631✔
3681

3682
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
631✔
3683
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
203✔
3684
    return;
203✔
3685
  }
3686

3687
  SStreamScanInfo* pScanInfo = downstream->info;
428✔
3688
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
428✔
3689
}
3690

3691
void streamSessionSemiReloadState(SOperatorInfo* pOperator) {
15✔
3692
  int32_t                        code = TSDB_CODE_SUCCESS;
15✔
3693
  int32_t                        lino = 0;
15✔
3694
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
15✔
3695
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
15✔
3696
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
15✔
3697
  resetWinRange(&pAggSup->winRange);
15✔
3698

3699
  SResultWindowInfo winInfo = {0};
15✔
3700
  int32_t           size = 0;
15✔
3701
  void*             pBuf = NULL;
15✔
3702
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
15✔
3703
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3704
  QUERY_CHECK_CODE(code, lino, _end);
15!
3705

3706
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
15✔
3707
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
15✔
3708
  for (int32_t i = 0; i < num; i++) {
39✔
3709
    SResultWindowInfo winInfo = {0};
24✔
3710
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
24✔
3711
    QUERY_CHECK_CODE(code, lino, _end);
24!
3712
    if (!IS_VALID_SESSION_WIN(winInfo)) {
24!
3713
      continue;
×
3714
    }
3715
    compactSessionSemiWindow(pOperator, &winInfo);
24✔
3716
    code = saveSessionOutputBuf(pAggSup, &winInfo);
24✔
3717
    QUERY_CHECK_CODE(code, lino, _end);
24!
3718
  }
3719
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
15✔
3720
  taosMemoryFree(pBuf);
15!
3721
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
15✔
3722
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
15✔
3723

3724
  SOperatorInfo* downstream = pOperator->pDownstream[0];
15✔
3725
  if (downstream->fpSet.reloadStreamStateFn) {
15!
3726
    downstream->fpSet.reloadStreamStateFn(downstream);
15✔
3727
  }
3728
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
15✔
3729

3730
_end:
15✔
3731
  if (code != TSDB_CODE_SUCCESS) {
15!
3732
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3733
  }
3734
}
15✔
3735

3736
void streamSessionReloadState(SOperatorInfo* pOperator) {
176✔
3737
  int32_t                        code = TSDB_CODE_SUCCESS;
176✔
3738
  int32_t                        lino = 0;
176✔
3739
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
176✔
3740
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
176✔
3741
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
176✔
3742
  resetWinRange(&pAggSup->winRange);
176✔
3743

3744
  int32_t size = 0;
176✔
3745
  void*   pBuf = NULL;
176✔
3746
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
176✔
3747
                                                strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
3748

3749
  QUERY_CHECK_CODE(code, lino, _end);
176!
3750

3751
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
176✔
3752
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
176✔
3753

3754
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
176✔
3755
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
176✔
3756
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
176✔
3757

3758
  if (!pInfo->pStUpdated && num > 0) {
176!
3759
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
70✔
3760
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
70✔
3761
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
70!
3762
  }
3763
  for (int32_t i = 0; i < num; i++) {
335✔
3764
    SResultWindowInfo winInfo = {0};
159✔
3765
    code = getSessionWindowInfoByKey(pAggSup, pSeKeyBuf + i, &winInfo);
159✔
3766
    QUERY_CHECK_CODE(code, lino, _end);
159!
3767
    if (!IS_VALID_SESSION_WIN(winInfo)) {
159!
3768
      continue;
×
3769
    }
3770

3771
    int32_t winNum = 0;
159✔
3772
    code = compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted, true, &winNum);
159✔
3773
    QUERY_CHECK_CODE(code, lino, _end);
159!
3774

3775
    if (winNum > 0) {
159!
3776
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, winInfo.sessionWin.win.skey,
×
3777
             winInfo.sessionWin.groupId);
3778
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
3779
        code = saveResult(winInfo, pInfo->pStUpdated);
×
3780
        QUERY_CHECK_CODE(code, lino, _end);
×
3781
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
3782
        if (!isCloseWindow(&winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
3783
          code = saveDeleteRes(pInfo->pStDeleted, winInfo.sessionWin);
×
3784
          QUERY_CHECK_CODE(code, lino, _end);
×
3785
        }
3786
        SSessionKey key = {0};
×
3787
        getSessionHashKey(&winInfo.sessionWin, &key);
×
3788
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
×
3789
        QUERY_CHECK_CODE(code, lino, _end);
×
3790
      }
3791
    }
3792
    code = saveSessionOutputBuf(pAggSup, &winInfo);
159✔
3793
    QUERY_CHECK_CODE(code, lino, _end);
159!
3794
  }
3795
  taosMemoryFree(pBuf);
176!
3796

3797
  SOperatorInfo* downstream = pOperator->pDownstream[0];
176✔
3798
  if (downstream->fpSet.reloadStreamStateFn) {
176!
3799
    downstream->fpSet.reloadStreamStateFn(downstream);
176✔
3800
  }
3801
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
176✔
3802

3803
_end:
176✔
3804
  if (code != TSDB_CODE_SUCCESS) {
176!
3805
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3806
  }
3807
}
176✔
3808

3809
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
847✔
3810
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
3811
  QRY_PARAM_CHECK(pOptrInfo);
847!
3812

3813
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
847✔
3814
  int32_t                        numOfCols = 0;
847✔
3815
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
847✔
3816
  int32_t                        lino = 0;
847✔
3817
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
847!
3818
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
848!
3819
  if (pInfo == NULL || pOperator == NULL) {
848!
3820
    code = terrno;
×
3821
    goto _error;
×
3822
  }
3823

3824
  pOperator->pTaskInfo = pTaskInfo;
848✔
3825

3826
  initResultSizeInfo(&pOperator->resultInfo, 4096);
848✔
3827
  if (pSessionNode->window.pExprs != NULL) {
848✔
3828
    int32_t    numOfScalar = 0;
1✔
3829
    SExprInfo* pScalarExprInfo = NULL;
1✔
3830
    code = createExprInfo(pSessionNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
3831
    QUERY_CHECK_CODE(code, lino, _error);
1!
3832

3833
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
3834
    if (code != TSDB_CODE_SUCCESS) {
1!
3835
      goto _error;
×
3836
    }
3837
  }
3838
  SExprSupp* pExpSup = &pOperator->exprSupp;
848✔
3839

3840
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
848✔
3841
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
848!
3842
  pInfo->binfo.pRes = pResBlock;
848✔
3843

3844
  SExprInfo* pExprInfo = NULL;
848✔
3845
  code = createExprInfo(pSessionNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
848✔
3846
  QUERY_CHECK_CODE(code, lino, _error);
848!
3847

3848
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
848✔
3849
  QUERY_CHECK_CODE(code, lino, _error);
848!
3850

3851
  pInfo->twAggSup = (STimeWindowAggSupp){
848✔
3852
      .waterMark = pSessionNode->window.watermark,
848✔
3853
      .calTrigger = pSessionNode->window.triggerType,
848✔
3854
      .maxTs = INT64_MIN,
3855
      .minTs = INT64_MAX,
3856
      .deleteMark = getDeleteMark(&pSessionNode->window, 0),
848✔
3857
  };
3858

3859
  pInfo->primaryTsIndex = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
848✔
3860
  code =
3861
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, pSessionNode->gap, pTaskInfo->streamInfo.pState,
848✔
3862
                             0, 0, &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
848✔
3863
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
3864
  if (code != TSDB_CODE_SUCCESS) {
848!
3865
    goto _error;
×
3866
  }
3867

3868
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
848✔
3869
  QUERY_CHECK_CODE(code, lino, _error);
848!
3870

3871
  if (pSessionNode->window.pTsEnd) {
848!
3872
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
848✔
3873
  }
3874

3875
  pInfo->order = TSDB_ORDER_ASC;
848✔
3876
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
848✔
3877
  pInfo->pStDeleted = tSimpleHashInit(64, hashFn);
848✔
3878
  QUERY_CHECK_NULL(pInfo->pStDeleted, code, lino, _error, terrno);
848!
3879
  pInfo->pDelIterator = NULL;
848✔
3880
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
848✔
3881
  QUERY_CHECK_CODE(code, lino, _error);
848!
3882

3883
  pInfo->pChildren = NULL;
848✔
3884
  pInfo->pPhyNode = pPhyNode;
848✔
3885
  pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
848✔
3886
  pInfo->ignoreExpiredDataSaved = false;
848✔
3887
  pInfo->pUpdated = NULL;
848✔
3888
  pInfo->pStUpdated = NULL;
848✔
3889
  pInfo->dataVersion = 0;
848✔
3890
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
848✔
3891
  if (!pInfo->historyWins) {
848!
3892
    goto _error;
×
3893
  }
3894
  if (pHandle) {
848!
3895
    pInfo->isHistoryOp = pHandle->fillHistory;
848✔
3896
  }
3897

3898
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
848✔
3899
  QUERY_CHECK_CODE(code, lino, _error);
848!
3900

3901
  pInfo->clearState = false;
848✔
3902
  pInfo->recvGetAll = false;
848✔
3903
  pInfo->destHasPrimaryKey = pSessionNode->window.destHasPrimaryKey;
848✔
3904
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
848✔
3905
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
848!
3906
  pInfo->pOperator = pOperator;
848✔
3907

3908
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION;
848✔
3909
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
848✔
3910
                  OP_NOT_OPENED, pInfo, pTaskInfo);
3911
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
848✔
3912
    // for stream
3913
    void*   buff = NULL;
705✔
3914
    int32_t len = 0;
705✔
3915
    int32_t res =
3916
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
705✔
3917
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
3918
    if (res == TSDB_CODE_SUCCESS) {
705!
3919
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
3920
      taosMemoryFree(buff);
×
3921
      QUERY_CHECK_CODE(code, lino, _error);
×
3922
    }
3923
  }
3924
  pOperator->fpSet =
3925
      createOperatorFpSet(optrDummyOpenFn, doStreamSessionAggNext, NULL, destroyStreamSessionAggOperatorInfo,
848✔
3926
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
3927
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
848✔
3928

3929
  if (downstream) {
848✔
3930
    pInfo->basic.primaryPkIndex = -1;
739✔
3931
    code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
739✔
3932
                          &pInfo->twAggSup, &pInfo->basic);
739✔
3933
    QUERY_CHECK_CODE(code, lino, _error);
739!
3934

3935
    code = appendDownstream(pOperator, &downstream, 1);
739✔
3936
    QUERY_CHECK_CODE(code, lino, _error);
739!
3937
  }
3938

3939
  *pOptrInfo = pOperator;
848✔
3940
  return TSDB_CODE_SUCCESS;
848✔
3941

3942
_error:
×
3943
  if (pInfo != NULL) {
×
3944
    destroyStreamSessionAggOperatorInfo(pInfo);
×
3945
  }
3946
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
3947
  pTaskInfo->code = code;
×
3948
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3949
  return code;
×
3950
}
3951

3952
static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
587✔
3953
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
587✔
3954
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
587✔
3955
  pInfo->clearState = false;
587✔
3956
}
587✔
3957

3958
int32_t deleteSessionWinState(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SSHashObj* pMapUpdate,
577✔
3959
                              SSHashObj* pMapDelete, SSHashObj* pPkDelete, bool needAdd) {
3960
  int32_t code = TSDB_CODE_SUCCESS;
577✔
3961
  int32_t lino = 0;
577✔
3962
  SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
577✔
3963
  if (!pWins) {
577!
3964
    code = terrno;
×
3965
    QUERY_CHECK_CODE(code, lino, _end);
×
3966
  }
3967
  code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
577✔
3968
  QUERY_CHECK_CODE(code, lino, _end);
577!
3969

3970
  removeSessionResults(pAggSup, pMapUpdate, pWins);
577✔
3971
  code = copyDeleteWindowInfo(pWins, pMapDelete);
577✔
3972
  QUERY_CHECK_CODE(code, lino, _end);
577!
3973

3974
  if (needAdd) {
577!
3975
    code = copyDeleteWindowInfo(pWins, pPkDelete);
×
3976
    QUERY_CHECK_CODE(code, lino, _end);
×
3977
  }
3978
  taosArrayDestroy(pWins);
577✔
3979

3980
_end:
577✔
3981
  if (code != TSDB_CODE_SUCCESS) {
577!
3982
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3983
  }
3984
  return code;
577✔
3985
}
3986

3987
static int32_t doStreamSessionSemiAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
1,054✔
3988
  int32_t                        code = TSDB_CODE_SUCCESS;
1,054✔
3989
  int32_t                        lino = 0;
1,054✔
3990
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
1,054✔
3991
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
1,054✔
3992
  TSKEY                          maxTs = INT64_MIN;
1,054✔
3993
  SExprSupp*                     pSup = &pOperator->exprSupp;
1,054✔
3994
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
1,054✔
3995
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
1,054✔
3996

3997
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
1,054✔
3998
  if (pOperator->status == OP_EXEC_DONE) {
1,054!
3999
    (*ppRes) = NULL;
×
4000
    return code;
×
4001
  }
4002

4003
  {
4004
    SSDataBlock* opRes = NULL;
1,054✔
4005
    code = buildSessionResult(pOperator, &opRes);
1,054✔
4006
    QUERY_CHECK_CODE(code, lino, _end);
1,053!
4007
    if (opRes) {
1,053✔
4008
      (*ppRes) = opRes;
85✔
4009
      return code;
270✔
4010
    }
4011

4012
    if (pInfo->clearState) {
968✔
4013
      clearFunctionContext(&pOperator->exprSupp);
56✔
4014
      // semi session operator clear disk buffer
4015
      clearStreamSessionOperator(pInfo);
56✔
4016
    }
4017

4018
    if (pOperator->status == OP_RES_TO_RETURN) {
969✔
4019
      if (pInfo->reCkBlock) {
185!
4020
        pInfo->reCkBlock = false;
×
4021
        printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
4022
        (*ppRes) = pInfo->pCheckpointRes;
×
4023
        return code;
×
4024
      }
4025
      clearFunctionContext(&pOperator->exprSupp);
185✔
4026
      // semi session operator clear disk buffer
4027
      clearStreamSessionOperator(pInfo);
185✔
4028
      setStreamOperatorCompleted(pOperator);
185✔
4029
      (*ppRes) = NULL;
185✔
4030
      return code;
185✔
4031
    }
4032
  }
4033

4034
  SOperatorInfo* downstream = pOperator->pDownstream[0];
784✔
4035
  if (!pInfo->pUpdated) {
784✔
4036
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
586✔
4037
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
587!
4038
  }
4039
  if (!pInfo->pStUpdated) {
785✔
4040
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
587✔
4041
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
587✔
4042
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
585!
4043
  }
4044
  while (1) {
357✔
4045
    SSDataBlock* pBlock = NULL;
1,140✔
4046
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,140✔
4047
    QUERY_CHECK_CODE(code, lino, _end);
1,141!
4048

4049
    if (pBlock == NULL) {
1,141✔
4050
      pOperator->status = OP_RES_TO_RETURN;
531✔
4051
      break;
531✔
4052
    }
4053
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
610✔
4054
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
610✔
4055

4056
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
610✔
4057
        pBlock->info.type == STREAM_CLEAR) {
559✔
4058
      // gap must be 0
4059
      code = deleteSessionWinState(pAggSup, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, NULL, false);
56✔
4060
      QUERY_CHECK_CODE(code, lino, _end);
56!
4061
      pInfo->clearState = true;
56✔
4062
      break;
56✔
4063
    } else if (pBlock->info.type == STREAM_GET_ALL) {
554!
4064
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
×
4065
      QUERY_CHECK_CODE(code, lino, _end);
×
4066
      continue;
15✔
4067
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
554✔
4068
      (*ppRes) = pBlock;
197✔
4069
      return code;
197✔
4070
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
357✔
4071
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
15✔
4072
      doStreamSessionSaveCheckpoint(pOperator);
15✔
4073
      continue;
15✔
4074
    } else {
4075
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
342!
4076
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4077
        QUERY_CHECK_CODE(code, lino, _end);
×
4078
      }
4079
    }
4080

4081
    if (pInfo->scalarSupp.pExprInfo != NULL) {
342!
4082
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
4083
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
4084
      QUERY_CHECK_CODE(code, lino, _end);
×
4085
    }
4086
    // the pDataBlock are always the same one, no need to call this again
4087
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
342✔
4088
    QUERY_CHECK_CODE(code, lino, _end);
342!
4089
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
342✔
4090
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
342✔
4091
  }
4092

4093
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
587✔
4094
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
587✔
4095

4096
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
587✔
4097
  QUERY_CHECK_CODE(code, lino, _end);
587!
4098

4099
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
587✔
4100

4101
  if (pInfo->isHistoryOp) {
587✔
4102
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
15✔
4103
    QUERY_CHECK_CODE(code, lino, _end);
15!
4104
  }
4105

4106
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
587✔
4107
  pInfo->pUpdated = NULL;
587✔
4108
  code = blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
587✔
4109
  QUERY_CHECK_CODE(code, lino, _end);
587!
4110

4111
  SSDataBlock* opRes = NULL;
587✔
4112
  code = buildSessionResult(pOperator, &opRes);
587✔
4113
  QUERY_CHECK_CODE(code, lino, _end);
587!
4114
  if (opRes) {
587✔
4115
    (*ppRes) = opRes;
241✔
4116
    return code;
241✔
4117
  }
4118

4119
_end:
346✔
4120
  if (code != TSDB_CODE_SUCCESS) {
346!
4121
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4122
    pTaskInfo->code = code;
×
4123
    T_LONG_JMP(pTaskInfo->env, code);
×
4124
  }
4125

4126
  clearFunctionContext(&pOperator->exprSupp);
346✔
4127
  // semi session operator clear disk buffer
4128
  clearStreamSessionOperator(pInfo);
346✔
4129
  setStreamOperatorCompleted(pOperator);
346✔
4130
  (*ppRes) = NULL;
346✔
4131
  return code;
346✔
4132
}
4133

4134
static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
×
4135
  SSDataBlock* pRes = NULL;
×
4136
  int32_t      code = doStreamSessionSemiAggNext(pOperator, &pRes);
×
4137
  return pRes;
×
4138
}
4139

4140
int32_t createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
252✔
4141
                                                SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle,
4142
                                                SOperatorInfo** pOptrInfo) {
4143
  QRY_PARAM_CHECK(pOptrInfo);
252!
4144

4145
  int32_t        code = TSDB_CODE_SUCCESS;
252✔
4146
  int32_t        lino = 0;
252✔
4147
  SOperatorInfo* pOperator = NULL;
252✔
4148
  code = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, &pOperator);
252✔
4149
  if (pOperator == NULL || code != 0) {
252!
4150
    downstream = NULL;
×
4151
    QUERY_CHECK_CODE(code, lino, _error);
×
4152
  }
4153

4154
  SStorageAPI*                   pAPI = &pTaskInfo->storageAPI;
252✔
4155
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
252✔
4156
  pOperator->operatorType = pPhyNode->type;
252✔
4157
  pInfo->pOperator = pOperator;
252✔
4158

4159
  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
252✔
4160
    pOperator->fpSet =
109✔
4161
        createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAggNext, NULL, destroyStreamSessionAggOperatorInfo,
109✔
4162
                            optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4163
    setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionSemiReloadState);
109✔
4164
  }
4165
  setOperatorInfo(pOperator, getStreamOpName(pOperator->operatorType), pPhyNode->type, false, OP_NOT_OPENED, pInfo,
252✔
4166
                  pTaskInfo);
4167

4168
  if (numOfChild > 0) {
252✔
4169
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
34✔
4170
    QUERY_CHECK_NULL(pInfo->pChildren, code, lino, _error, terrno);
34!
4171
    for (int32_t i = 0; i < numOfChild; i++) {
143✔
4172
      SOperatorInfo* pChildOp = NULL;
109✔
4173
      code = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0, pHandle, &pChildOp);
109✔
4174
      if (pChildOp == NULL || code != 0) {
109!
4175
        QUERY_CHECK_CODE(code, lino, _error);
×
4176
      }
4177

4178
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
109✔
4179
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
109✔
4180
      pAPI->stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i, pInfo->primaryTsIndex);
109✔
4181
      void* tmp = taosArrayPush(pInfo->pChildren, &pChildOp);
109✔
4182
      if (!tmp) {
109!
4183
        code = terrno;
×
4184
        QUERY_CHECK_CODE(code, lino, _error);
×
4185
      }
4186
    }
4187

4188
    void*   buff = NULL;
34✔
4189
    int32_t len = 0;
34✔
4190
    int32_t res =
4191
        pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_CHECKPOINT_NAME,
34✔
4192
                                                          strlen(STREAM_SESSION_OP_CHECKPOINT_NAME), &buff, &len);
4193
    if (res == TSDB_CODE_SUCCESS) {
34!
4194
      code = doStreamSessionDecodeOpState(buff, len, pOperator, true, NULL);
×
4195
      taosMemoryFree(buff);
×
4196
      QUERY_CHECK_CODE(code, lino, _error);
×
4197
    }
4198
  }
4199

4200
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
252✔
4201
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
218✔
4202
  }
4203

4204
  *pOptrInfo = pOperator;
252✔
4205
  return code;
252✔
4206

4207
_error:
×
4208
  if (pInfo != NULL) {
×
4209
    destroyStreamSessionAggOperatorInfo(pInfo);
×
4210
  }
4211
  if (pOperator != NULL) {
×
4212
    pOperator->info = NULL;
×
4213
    destroyOperator(pOperator);
×
4214
  }
4215
  pTaskInfo->code = code;
×
4216
  if (code != TSDB_CODE_SUCCESS) {
×
4217
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4218
  }
4219
  return code;
×
4220
}
4221

4222
void destroyStreamStateOperatorInfo(void* param) {
324✔
4223
  if (param == NULL) {
324!
4224
    return;
×
4225
  }
4226
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
324✔
4227
  cleanupBasicInfo(&pInfo->binfo);
324✔
4228
  if (pInfo->pOperator) {
324!
4229
    cleanupResultInfoInStream(pInfo->pOperator->pTaskInfo, pInfo->streamAggSup.pState, &pInfo->pOperator->exprSupp,
324✔
4230
                              &pInfo->groupResInfo);
4231
    pInfo->pOperator = NULL;
324✔
4232
  }
4233
  destroyStreamAggSupporter(&pInfo->streamAggSup);
324✔
4234
  clearGroupResInfo(&pInfo->groupResInfo);
324✔
4235
  taosArrayDestroyP(pInfo->pUpdated, destroyFlusedPos);
324✔
4236
  pInfo->pUpdated = NULL;
324✔
4237

4238
  cleanupExprSupp(&pInfo->scalarSupp);
324✔
4239
  if (pInfo->pChildren != NULL) {
324!
4240
    int32_t size = taosArrayGetSize(pInfo->pChildren);
×
4241
    for (int32_t i = 0; i < size; i++) {
×
4242
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
×
4243
      destroyOperator(pChild);
×
4244
    }
4245
    taosArrayDestroy(pInfo->pChildren);
×
4246
  }
4247
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
324✔
4248
  blockDataDestroy(pInfo->pDelRes);
324✔
4249
  tSimpleHashCleanup(pInfo->pSeUpdated);
324✔
4250
  tSimpleHashCleanup(pInfo->pSeDeleted);
324✔
4251
  cleanupGroupResInfo(&pInfo->groupResInfo);
324✔
4252

4253
  taosArrayDestroy(pInfo->historyWins);
324✔
4254
  blockDataDestroy(pInfo->pCheckpointRes);
324✔
4255
  tSimpleHashCleanup(pInfo->pPkDeleted);
324✔
4256

4257
  taosMemoryFreeClear(param);
324!
4258
}
4259

4260
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
3,491✔
4261
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
3,491✔
4262
    return true;
1,104✔
4263
  }
4264
  return false;
2,387✔
4265
}
4266

4267
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
5,832✔
4268
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
5,832!
4269
}
4270

4271
bool compareStateKey(void* data, void* key) {
2,305✔
4272
  if (!data || !key) {
2,305!
4273
    return true;
×
4274
  }
4275
  SStateKeys* stateKey = (SStateKeys*)key;
2,305✔
4276
  stateKey->pData = (char*)key + sizeof(SStateKeys);
2,305✔
4277
  return compareVal(data, stateKey);
2,305✔
4278
}
4279

4280
bool compareWinStateKey(SStateKeys* left, SStateKeys* right) {
126✔
4281
  if (!left || !right) {
126!
4282
    return false;
126✔
4283
  }
4284
  return compareVal(left->pData, right);
×
4285
}
4286

4287
int32_t getStateWindowInfoByKey(SStreamAggSupporter* pAggSup, SSessionKey* pKey, SStateWindowInfo* pCurWin,
126✔
4288
                                SStateWindowInfo* pNextWin) {
4289
  int32_t          code = TSDB_CODE_SUCCESS;
126✔
4290
  int32_t          lino = 0;
126✔
4291
  SStreamStateCur* pCur = NULL;
126✔
4292
  int32_t          size = pAggSup->resultRowSize;
126✔
4293
  pCurWin->winInfo.sessionWin.groupId = pKey->groupId;
126✔
4294
  pCurWin->winInfo.sessionWin.win.skey = pKey->win.skey;
126✔
4295
  pCurWin->winInfo.sessionWin.win.ekey = pKey->win.ekey;
126✔
4296
  code = getSessionWindowInfoByKey(pAggSup, pKey, &pCurWin->winInfo);
126✔
4297
  QUERY_CHECK_CODE(code, lino, _end);
126!
4298
  QUERY_CHECK_CONDITION((IS_VALID_SESSION_WIN(pCurWin->winInfo)), code, lino, _end,
126!
4299
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4300

4301
  pCurWin->pStateKey =
126✔
4302
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
126✔
4303
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
126✔
4304
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
126✔
4305
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
126✔
4306
  pCurWin->pStateKey->isNull = false;
126✔
4307
  pCurWin->winInfo.isOutput = true;
126✔
4308
  if (pCurWin->winInfo.pStatePos->needFree) {
126!
4309
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
126✔
4310
  }
4311

4312
  qDebug("===stream===get state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
126✔
4313
         pCurWin->winInfo.sessionWin.win.ekey);
4314

4315
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
126✔
4316
  pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
126✔
4317
  int32_t nextSize = pAggSup->resultRowSize;
126✔
4318
  int32_t winCode = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin,
126✔
4319
                                                                     (void**)&pNextWin->winInfo.pStatePos, &nextSize);
126✔
4320
  if (winCode != TSDB_CODE_SUCCESS) {
126!
4321
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
126✔
4322
  } else {
4323
    pNextWin->pStateKey =
×
4324
        (SStateKeys*)((char*)pNextWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
×
4325
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
×
4326
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
×
4327
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
×
4328
    pNextWin->pStateKey->isNull = false;
×
4329
    pNextWin->winInfo.isOutput = true;
×
4330
  }
4331

4332
_end:
126✔
4333
  pAggSup->stateStore.streamStateFreeCur(pCur);
126✔
4334
  qDebug("===stream===get state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
126✔
4335
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4336
  if (code != TSDB_CODE_SUCCESS) {
126!
4337
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4338
  }
4339
  return code;
126✔
4340
}
4341

4342
int32_t setStateOutputBuf(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
3,012✔
4343
                          SStateWindowInfo* pCurWin, SStateWindowInfo* pNextWin) {
4344
  int32_t          size = pAggSup->resultRowSize;
3,012✔
4345
  SStreamStateCur* pCur = NULL;
3,012✔
4346
  pCurWin->winInfo.sessionWin.groupId = groupId;
3,012✔
4347
  pCurWin->winInfo.sessionWin.win.skey = ts;
3,012✔
4348
  pCurWin->winInfo.sessionWin.win.ekey = ts;
3,012✔
4349
  int32_t code = TSDB_CODE_SUCCESS;
3,012✔
4350
  int32_t lino = 0;
3,012✔
4351
  int32_t winCode = TSDB_CODE_SUCCESS;
3,012✔
4352
  code = pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData,
3,012✔
4353
                                                           pAggSup->stateKeySize, compareStateKey,
4354
                                                           (void**)&pCurWin->winInfo.pStatePos, &size, &winCode);
3,012✔
4355
  QUERY_CHECK_CODE(code, lino, _end);
3,012!
4356

4357
  pCurWin->pStateKey =
3,012✔
4358
      (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
3,012✔
4359
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
3,012✔
4360
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
3,012✔
4361
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
3,012✔
4362
  pCurWin->pStateKey->isNull = false;
3,012✔
4363

4364
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->winInfo.sessionWin.win)) {
3,012!
4365
    winCode = TSDB_CODE_FAILED;
×
4366
    clearOutputBuf(pAggSup->pState, pCurWin->winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
4367
    pCurWin->pStateKey =
×
4368
        (SStateKeys*)((char*)pCurWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
×
4369
    pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
×
4370
    pCurWin->pStateKey->type = pAggSup->stateKeyType;
×
4371
    pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
×
4372
    pCurWin->pStateKey->isNull = false;
×
4373
    pCurWin->winInfo.sessionWin.groupId = groupId;
×
4374
    pCurWin->winInfo.sessionWin.win.skey = ts;
×
4375
    pCurWin->winInfo.sessionWin.win.ekey = ts;
×
4376
    qDebug("===stream===reset state win key. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
×
4377
           pCurWin->winInfo.sessionWin.win.ekey);
4378
  }
4379

4380
  if (winCode == TSDB_CODE_SUCCESS) {
3,012✔
4381
    pCurWin->winInfo.isOutput = true;
1,942✔
4382
    if (pCurWin->winInfo.pStatePos->needFree) {
1,942✔
4383
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
8✔
4384
    }
4385
  } else if (pKeyData) {
1,070!
4386
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
1,070!
4387
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
3✔
4388
    } else {
4389
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
1,067✔
4390
    }
4391
  }
4392

4393
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
3,012✔
4394
         pCurWin->winInfo.sessionWin.win.ekey);
4395

4396
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
3,013✔
4397
  pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
3,013✔
4398
  int32_t nextSize = pAggSup->resultRowSize;
3,013✔
4399
  winCode = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin,
6,025✔
4400
                                                             (void**)&pNextWin->winInfo.pStatePos, &nextSize);
3,013✔
4401
  if (winCode != TSDB_CODE_SUCCESS) {
3,012✔
4402
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
2,969✔
4403
  } else {
4404
    pNextWin->pStateKey =
43✔
4405
        (SStateKeys*)((char*)pNextWin->winInfo.pStatePos->pRowBuff + (pAggSup->resultRowSize - pAggSup->stateKeySize));
43✔
4406
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
43✔
4407
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
43✔
4408
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
43✔
4409
    pNextWin->pStateKey->isNull = false;
43✔
4410
    pNextWin->winInfo.isOutput = true;
43✔
4411
  }
4412
  qDebug("===stream===set state next win buff. skey:%" PRId64 ", endkey:%" PRId64,
3,012✔
4413
         pNextWin->winInfo.sessionWin.win.skey, pNextWin->winInfo.sessionWin.win.ekey);
4414
_end:
1,450✔
4415
  pAggSup->stateStore.streamStateFreeCur(pCur);
3,012✔
4416
  if (code != TSDB_CODE_SUCCESS) {
3,012!
4417
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4418
  }
4419
  return code;
3,012✔
4420
}
4421

4422
int32_t updateStateWindowInfo(SStreamAggSupporter* pAggSup, SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin,
3,013✔
4423
                              TSKEY* pTs, uint64_t groupId, SColumnInfoData* pKeyCol, int32_t rows, int32_t start,
4424
                              bool* allEqual, SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted,
4425
                              int32_t* pWinRows) {
4426
  int32_t code = TSDB_CODE_SUCCESS;
3,013✔
4427
  int32_t lino = 0;
3,013✔
4428
  *allEqual = true;
3,013✔
4429
  for (int32_t i = start; i < rows; ++i) {
6,457✔
4430
    char* pKeyData = colDataGetData(pKeyCol, i);
3,491!
4431
    if (!isTsInWindow(pWinInfo, pTs[i])) {
3,491✔
4432
      if (isEqualStateKey(pWinInfo, pKeyData)) {
2,387✔
4433
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
2,341✔
4434
          // ts belongs to the next window
4435
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
22!
4436
            (*pWinRows) = i - start;
×
4437
            goto _end;
×
4438
          }
4439
        }
4440
      } else {
4441
        (*pWinRows) = i - start;
46✔
4442
        goto _end;
46✔
4443
      }
4444
    }
4445

4446
    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
3,445✔
4447
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
2!
4448
        code = saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
2✔
4449
        QUERY_CHECK_CODE(code, lino, _end);
2!
4450
      }
4451
      removeSessionResult(pAggSup, pSeUpdated, pResultRows, &pWinInfo->winInfo.sessionWin);
2✔
4452
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
2✔
4453
    }
4454
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
3,445✔
4455
    memcpy(pWinInfo->winInfo.pStatePos->pKey, &pWinInfo->winInfo.sessionWin, sizeof(SSessionKey));
3,445✔
4456
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
3,445✔
4457
      *allEqual = false;
10✔
4458
    }
4459
  }
4460
  (*pWinRows) = rows - start;
2,966✔
4461

4462
_end:
3,012✔
4463
  if (code != TSDB_CODE_SUCCESS) {
3,012!
4464
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4465
  }
4466
  return code;
3,013✔
4467
}
4468

4469
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
2,976✔
4470
                                 SSHashObj* pStDeleted) {
4471
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
2,976✔
4472
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
2,976✔
4473

4474
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
2,976✔
4475
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
2,976✔
4476
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
2,976✔
4477
  int32_t                      code = TSDB_CODE_SUCCESS;
2,976✔
4478
  int32_t                      lino = 0;
2,976✔
4479
  TSKEY*                       tsCols = NULL;
2,976✔
4480
  SResultRow*                  pResult = NULL;
2,976✔
4481
  int32_t                      winRows = 0;
2,976✔
4482
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
2,976✔
4483

4484
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
2,976✔
4485
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
2,976✔
4486
  if (pAggSup->winRange.ekey <= 0) {
2,976!
4487
    pAggSup->winRange.ekey = INT64_MAX;
×
4488
  }
4489

4490
  if (pSDataBlock->pDataBlock != NULL) {
2,976✔
4491
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
2,975✔
4492
    if (!pColDataInfo) {
2,975!
4493
      code = TSDB_CODE_FAILED;
×
4494
      QUERY_CHECK_CODE(code, lino, _end);
×
4495
    }
4496
    tsCols = (int64_t*)pColDataInfo->pData;
2,975✔
4497
  } else {
4498
    return;
1✔
4499
  }
4500

4501
  int32_t rows = pSDataBlock->info.rows;
2,975✔
4502
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
2,975✔
4503
  QUERY_CHECK_CODE(code, lino, _end);
2,976!
4504

4505
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
2,976✔
4506
  for (int32_t i = 0; i < rows; i += winRows) {
5,998✔
4507
    if (pInfo->ignoreExpiredData && checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo,
3,043✔
4508
                                                     &pInfo->twAggSup, pSDataBlock->info.id.uid, tsCols[i], NULL, 0) ||
22✔
4509
        colDataIsNull_s(pKeyColInfo, i)) {
6,040✔
4510
      i++;
9✔
4511
      continue;
19✔
4512
    }
4513
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
3,012!
4514
    int32_t          winIndex = 0;
3,012✔
4515
    bool             allEqual = true;
3,012✔
4516
    SStateWindowInfo curWin = {0};
3,012✔
4517
    SStateWindowInfo nextWin = {0};
3,012✔
4518
    code = setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin);
3,012✔
4519
    QUERY_CHECK_CODE(code, lino, _end);
3,012!
4520

4521
    releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
3,012✔
4522

4523
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
3,012✔
4524
    code = updateStateWindowInfo(pAggSup, &curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
3,013✔
4525
                                 pAggSup->pResultRows, pSeUpdated, pStDeleted, &winRows);
4526
    QUERY_CHECK_CODE(code, lino, _end);
3,013!
4527

4528
    if (!allEqual) {
3,013✔
4529
      uint64_t uid = 0;
10✔
4530
      code = appendDataToSpecialBlock(pAggSup->pScanBlock, &curWin.winInfo.sessionWin.win.skey,
10✔
4531
                                      &curWin.winInfo.sessionWin.win.ekey, &uid, &groupId, NULL);
4532
      QUERY_CHECK_CODE(code, lino, _end);
10!
4533
      int32_t tmpRes = tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
10✔
4534
      qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
10!
4535

4536
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
10✔
4537
      releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
10✔
4538
      continue;
10✔
4539
    }
4540

4541
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
3,003✔
4542
                              pOperator, 0);
4543
    QUERY_CHECK_CODE(code, lino, _end);
3,003!
4544

4545
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
3,003✔
4546
    QUERY_CHECK_CODE(code, lino, _end);
3,003!
4547

4548
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
3,003!
4549
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
×
4550
      QUERY_CHECK_CODE(code, lino, _end);
×
4551
    }
4552

4553
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
3,003✔
4554
      code = saveResult(curWin.winInfo, pSeUpdated);
2,762✔
4555
      QUERY_CHECK_CODE(code, lino, _end);
2,762!
4556
    }
4557

4558
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
3,003✔
4559
      curWin.winInfo.pStatePos->beUpdated = true;
241✔
4560
      SSessionKey key = {0};
241✔
4561
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
241✔
4562
      code =
4563
          tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
241✔
4564
      QUERY_CHECK_CODE(code, lino, _end);
241!
4565
    }
4566
  }
4567

4568
_end:
2,976✔
4569
  if (code != TSDB_CODE_SUCCESS) {
2,976!
4570
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4571
  }
4572
}
4573

4574
int32_t doStreamStateEncodeOpState(void** buf, int32_t len, SOperatorInfo* pOperator, bool isParent) {
2✔
4575
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
2✔
4576
  if (!pInfo) {
2!
4577
    return 0;
×
4578
  }
4579

4580
  void* pData = (buf == NULL) ? NULL : *buf;
2✔
4581

4582
  // 1.streamAggSup.pResultRows
4583
  int32_t tlen = 0;
2✔
4584
  int32_t mapSize = tSimpleHashGetSize(pInfo->streamAggSup.pResultRows);
2✔
4585
  tlen += taosEncodeFixedI32(buf, mapSize);
2✔
4586
  void*   pIte = NULL;
2✔
4587
  size_t  keyLen = 0;
2✔
4588
  int32_t iter = 0;
2✔
4589
  while ((pIte = tSimpleHashIterate(pInfo->streamAggSup.pResultRows, pIte, &iter)) != NULL) {
4✔
4590
    void* key = tSimpleHashGetKey(pIte, &keyLen);
2✔
4591
    tlen += encodeSSessionKey(buf, key);
2✔
4592
    tlen += encodeSResultWindowInfo(buf, pIte, pInfo->streamAggSup.resultRowSize);
2✔
4593
  }
4594

4595
  // 2.twAggSup
4596
  tlen += encodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
2✔
4597

4598
  // 3.pChildren
4599
  int32_t size = taosArrayGetSize(pInfo->pChildren);
2✔
4600
  tlen += taosEncodeFixedI32(buf, size);
2✔
4601
  for (int32_t i = 0; i < size; i++) {
2!
4602
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4603
    tlen += doStreamStateEncodeOpState(buf, 0, pChOp, false);
×
4604
  }
4605

4606
  // 4.dataVersion
4607
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
2✔
4608

4609
  // 5.checksum
4610
  if (isParent) {
2!
4611
    if (buf) {
2✔
4612
      uint32_t cksum = taosCalcChecksum(0, pData, len - sizeof(uint32_t));
2!
4613
      tlen += taosEncodeFixedU32(buf, cksum);
1✔
4614
    } else {
4615
      tlen += sizeof(uint32_t);
1✔
4616
    }
4617
  }
4618

4619
  return tlen;
2✔
4620
}
4621

4622
int32_t doStreamStateDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator, bool isParent, void** ppBuf) {
×
4623
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
4624
  int32_t                      code = TSDB_CODE_SUCCESS;
×
4625
  int32_t                      lino = 0;
×
4626
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
×
4627
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
4628
  if (!pInfo) {
×
4629
    code = TSDB_CODE_FAILED;
×
4630
    QUERY_CHECK_CODE(code, lino, _end);
×
4631
  }
4632

4633
  // 5.checksum
4634
  if (isParent) {
×
4635
    int32_t dataLen = len - sizeof(uint32_t);
×
4636
    void*   pCksum = POINTER_SHIFT(buf, dataLen);
×
4637
    if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
×
4638
      qError("stream state_window state is invalid");
×
4639
      code = TSDB_CODE_FAILED;
×
4640
      QUERY_CHECK_CODE(code, lino, _end);
×
4641
    }
4642
  }
4643

4644
  // 1.streamAggSup.pResultRows
4645
  int32_t mapSize = 0;
×
4646
  buf = taosDecodeFixedI32(buf, &mapSize);
×
4647
  for (int32_t i = 0; i < mapSize; i++) {
×
4648
    SResultWindowInfo winfo = {0};
×
4649
    buf = decodeSSessionKey(buf, &winfo.sessionWin);
×
4650
    int32_t winCode = TSDB_CODE_SUCCESS;
×
4651
    code = pAggSup->stateStore.streamStateStateAddIfNotExist(
×
4652
        pAggSup->pState, &winfo.sessionWin, NULL, pAggSup->stateKeySize, compareStateKey, (void**)&winfo.pStatePos,
4653
        &pAggSup->resultRowSize, &winCode);
4654
    QUERY_CHECK_CODE(code, lino, _end);
×
4655

4656
    buf = decodeSResultWindowInfo(buf, &winfo, pInfo->streamAggSup.resultRowSize);
×
4657
    code = tSimpleHashPut(pInfo->streamAggSup.pResultRows, &winfo.sessionWin, sizeof(SSessionKey), &winfo,
×
4658
                          sizeof(SResultWindowInfo));
4659
    QUERY_CHECK_CODE(code, lino, _end);
×
4660
  }
4661

4662
  // 2.twAggSup
4663
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
×
4664

4665
  // 3.pChildren
4666
  int32_t size = 0;
×
4667
  buf = taosDecodeFixedI32(buf, &size);
×
4668
  for (int32_t i = 0; i < size; i++) {
×
4669
    SOperatorInfo* pChOp = taosArrayGetP(pInfo->pChildren, i);
×
4670
    code = doStreamStateDecodeOpState(buf, 0, pChOp, false, &buf);
×
4671
    QUERY_CHECK_CODE(code, lino, _end);
×
4672
  }
4673

4674
  // 4.dataVersion
4675
  buf = taosDecodeFixedI64(buf, &pInfo->dataVersion);
×
4676

4677
  if (ppBuf) {
×
4678
    (*ppBuf) = buf;
×
4679
  }
4680

4681
_end:
×
4682
  if (code != TSDB_CODE_SUCCESS) {
×
4683
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4684
  }
4685
  return code;
×
4686
}
4687

4688
void doStreamStateSaveCheckpoint(SOperatorInfo* pOperator) {
89✔
4689
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
89✔
4690
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
89✔
4691
    int32_t len = doStreamStateEncodeOpState(NULL, 0, pOperator, true);
1✔
4692
    void*   buf = taosMemoryCalloc(1, len);
1!
4693
    if (!buf) {
1!
4694
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
4695
      return;
×
4696
    }
4697
    void* pBuf = buf;
1✔
4698
    len = doStreamStateEncodeOpState(&pBuf, len, pOperator, true);
1✔
4699
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
1✔
4700
                                                       strlen(STREAM_STATE_OP_CHECKPOINT_NAME), buf, len);
4701
    taosMemoryFree(buf);
1!
4702
    saveStreamOperatorStateComplete(&pInfo->basic);
1✔
4703
  }
4704
}
4705

4706
static int32_t buildStateResult(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,035✔
4707
  int32_t                      code = TSDB_CODE_SUCCESS;
4,035✔
4708
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4,035✔
4709
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
4,035✔
4710
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4,035✔
4711

4712
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
4,035✔
4713
  if (pInfo->pDelRes->info.rows > 0) {
4,035✔
4714
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
184✔
4715
    (*ppRes) = pInfo->pDelRes;
184✔
4716
    return code;
184✔
4717
  }
4718

4719
  doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes);
3,851✔
4720
  if (pBInfo->pRes->info.rows > 0) {
3,851✔
4721
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,359✔
4722
    (*ppRes) = pBInfo->pRes;
1,359✔
4723
    return code;
1,359✔
4724
  }
4725
  (*ppRes) = NULL;
2,492✔
4726
  return code;
2,492✔
4727
}
4728

4729
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,426✔
4730
  if (pOperator->status == OP_EXEC_DONE) {
4,426!
4731
    (*ppRes) = NULL;
×
4732
    return TSDB_CODE_SUCCESS;
×
4733
  }
4734

4735
  int32_t                      code = TSDB_CODE_SUCCESS;
4,426✔
4736
  int32_t                      lino = 0;
4,426✔
4737
  SExprSupp*                   pSup = &pOperator->exprSupp;
4,426✔
4738
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4,426✔
4739
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
4,426✔
4740
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4,426✔
4741
  qDebug("===stream=== stream state agg");
4,426✔
4742
  if (pOperator->status == OP_RES_TO_RETURN) {
4,426✔
4743
    SSDataBlock* resBlock = NULL;
1,542✔
4744
    code = buildStateResult(pOperator, &resBlock);
1,542✔
4745
    QUERY_CHECK_CODE(code, lino, _end);
1,542!
4746
    if (resBlock != NULL) {
1,542✔
4747
      (*ppRes) = resBlock;
339✔
4748
      return code;
1,542✔
4749
    }
4750

4751
    if (pInfo->recvGetAll) {
1,203✔
4752
      pInfo->recvGetAll = false;
2✔
4753
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
2✔
4754
    }
4755

4756
    if (pInfo->reCkBlock) {
1,203!
4757
      pInfo->reCkBlock = false;
×
4758
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
4759
      (*ppRes) = pInfo->pCheckpointRes;
×
4760
      return code;
×
4761
    }
4762

4763
    setStreamOperatorCompleted(pOperator);
1,203✔
4764
    (*ppRes) = NULL;
1,203✔
4765
    return code;
1,203✔
4766
  }
4767

4768
  SOperatorInfo* downstream = pOperator->pDownstream[0];
2,884✔
4769
  if (!pInfo->pUpdated) {
2,884✔
4770
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,493✔
4771
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,492!
4772
  }
4773
  if (!pInfo->pSeUpdated) {
2,883✔
4774
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,459✔
4775
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
2,459✔
4776
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
2,460!
4777
  }
4778
  while (1) {
3,561✔
4779
    SSDataBlock* pBlock = NULL;
6,445✔
4780
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
6,445✔
4781
    QUERY_CHECK_CODE(code, lino, _end);
6,444!
4782

4783
    if (pBlock == NULL) {
6,444✔
4784
      break;
2,493✔
4785
    }
4786
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
3,951✔
4787
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
3,951✔
4788

4789
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
3,951✔
4790
        pBlock->info.type == STREAM_CLEAR) {
3,487✔
4791
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
487!
4792
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
487✔
4793
                                   pInfo->pPkDeleted, add);
4794
      QUERY_CHECK_CODE(code, lino, _end);
487!
4795
      continue;
585✔
4796
    } else if (pBlock->info.type == STREAM_GET_ALL) {
3,464✔
4797
      pInfo->recvGetAll = true;
9✔
4798
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
9✔
4799
      QUERY_CHECK_CODE(code, lino, _end);
9!
4800
      continue;
9✔
4801
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
3,455✔
4802
      (*ppRes) = pBlock;
391✔
4803
      return code;
391✔
4804
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
3,064✔
4805
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
89✔
4806
      doStreamStateSaveCheckpoint(pOperator);
89✔
4807
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
89✔
4808
      QUERY_CHECK_CODE(code, lino, _end);
89!
4809

4810
      continue;
89✔
4811
    } else {
4812
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
2,975!
4813
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4814
        QUERY_CHECK_CODE(code, lino, _end);
×
4815
      }
4816
    }
4817

4818
    if (pInfo->scalarSupp.pExprInfo != NULL) {
2,975✔
4819
      SExprSupp* pExprSup = &pInfo->scalarSupp;
256✔
4820
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
256✔
4821
      QUERY_CHECK_CODE(code, lino, _end);
255!
4822
    }
4823
    // the pDataBlock are always the same one, no need to call this again
4824
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
2,974✔
4825
    QUERY_CHECK_CODE(code, lino, _end);
2,976!
4826
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
2,976✔
4827
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
2,976✔
4828
  }
4829
  // restore the value
4830
  pOperator->status = OP_RES_TO_RETURN;
2,493✔
4831

4832
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
2,493✔
4833
  QUERY_CHECK_CODE(code, lino, _end);
2,493!
4834

4835
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,493✔
4836
  QUERY_CHECK_CODE(code, lino, _end);
2,493!
4837

4838
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
2,493✔
4839

4840
  if (pInfo->isHistoryOp) {
2,493✔
4841
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
96✔
4842
    QUERY_CHECK_CODE(code, lino, _end);
96!
4843
  }
4844
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
2,493!
4845
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
×
4846
    QUERY_CHECK_CODE(code, lino, _end);
×
4847
  }
4848

4849
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
2,493✔
4850
  pInfo->pUpdated = NULL;
2,493✔
4851
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
2,493✔
4852
  QUERY_CHECK_CODE(code, lino, _end);
2,493!
4853

4854
  SSDataBlock* resBlock = NULL;
2,493✔
4855
  code = buildStateResult(pOperator, &resBlock);
2,493✔
4856
  QUERY_CHECK_CODE(code, lino, _end);
2,493!
4857
  if (resBlock != NULL) {
2,493✔
4858
    (*ppRes) = resBlock;
1,204✔
4859
    return code;
1,204✔
4860
  }
4861

4862
_end:
1,289✔
4863
  if (code != TSDB_CODE_SUCCESS) {
1,289!
4864
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
4865
    pTaskInfo->code = code;
×
4866
    T_LONG_JMP(pTaskInfo->env, code);
×
4867
  }
4868
  setStreamOperatorCompleted(pOperator);
1,289✔
4869
  (*ppRes) = NULL;
1,289✔
4870
  return code;
1,289✔
4871
}
4872

4873
static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
×
4874
  SSDataBlock* pRes = NULL;
×
4875
  int32_t      code = doStreamStateAggNext(pOperator, &pRes);
×
4876
  return pRes;
×
4877
}
4878

4879
void streamStateReleaseState(SOperatorInfo* pOperator) {
85✔
4880
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
85✔
4881
  int32_t                      winSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
85✔
4882
  int32_t                      resSize = winSize + sizeof(TSKEY);
85✔
4883
  char*                        pBuff = taosMemoryCalloc(1, resSize);
85!
4884
  if (!pBuff) {
85!
4885
    return;
×
4886
  }
4887
  memcpy(pBuff, pInfo->historyWins->pData, winSize);
85✔
4888
  memcpy(pBuff + winSize, &pInfo->twAggSup.maxTs, sizeof(TSKEY));
85✔
4889
  qDebug("===stream=== relase state. save result count:%d", (int32_t)taosArrayGetSize(pInfo->historyWins));
85✔
4890
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_STATE_NAME,
85✔
4891
                                                     strlen(STREAM_STATE_OP_STATE_NAME), pBuff, resSize);
4892
  pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
85✔
4893
  taosMemoryFreeClear(pBuff);
85!
4894

4895
  SOperatorInfo* downstream = pOperator->pDownstream[0];
85✔
4896
  if (downstream->fpSet.releaseStreamStateFn) {
85!
4897
    downstream->fpSet.releaseStreamStateFn(downstream);
85✔
4898
  }
4899
}
4900

4901
static int32_t compactStateWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
×
4902
                                  SSHashObj* pStUpdated, SSHashObj* pStDeleted) {
4903
  SExprSupp*                   pSup = &pOperator->exprSupp;
×
4904
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
4905
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
×
4906
  return compactTimeWindow(pSup, &pInfo->streamAggSup, &pInfo->twAggSup, pTaskInfo, pCurWin, pNextWin, pStUpdated,
×
4907
                           pStDeleted, false);
4908
}
4909

4910
void streamStateReloadState(SOperatorInfo* pOperator) {
85✔
4911
  int32_t                      code = TSDB_CODE_SUCCESS;
85✔
4912
  int32_t                      lino = 0;
85✔
4913
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
85✔
4914
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
85✔
4915
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
85✔
4916
  resetWinRange(&pAggSup->winRange);
85✔
4917

4918
  SSessionKey seKey = {.win.skey = INT64_MIN, .win.ekey = INT64_MIN, .groupId = 0};
85✔
4919
  int32_t     size = 0;
85✔
4920
  void*       pBuf = NULL;
85✔
4921
  code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_STATE_OP_STATE_NAME,
85✔
4922
                                                strlen(STREAM_STATE_OP_STATE_NAME), &pBuf, &size);
4923
  QUERY_CHECK_CODE(code, lino, _end);
85!
4924

4925
  int32_t num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
85✔
4926
  qDebug("===stream=== reload state. get result count:%d", num);
85✔
4927
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
85✔
4928

4929
  TSKEY ts = *(TSKEY*)((char*)pBuf + size - sizeof(TSKEY));
85✔
4930
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
85✔
4931
  pAggSup->stateStore.streamStateReloadInfo(pAggSup->pState, ts);
85✔
4932

4933
  if (!pInfo->pSeUpdated && num > 0) {
85!
4934
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
33✔
4935
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
33✔
4936
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
33!
4937
  }
4938
  if (!pInfo->pSeDeleted && num > 0) {
85!
4939
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
4940
    pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
×
4941
    QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _end, terrno);
×
4942
  }
4943
  for (int32_t i = 0; i < num; i++) {
211✔
4944
    SStateWindowInfo curInfo = {0};
126✔
4945
    SStateWindowInfo nextInfo = {0};
126✔
4946
    qDebug("===stream=== reload state. try process result %" PRId64 ", %" PRIu64 ", index:%d", pSeKeyBuf[i].win.skey,
126✔
4947
           pSeKeyBuf[i].groupId, i);
4948
    code = getStateWindowInfoByKey(pAggSup, pSeKeyBuf + i, &curInfo, &nextInfo);
126✔
4949
    QUERY_CHECK_CODE(code, lino, _end);
126!
4950

4951
    bool cpRes = compareWinStateKey(curInfo.pStateKey, nextInfo.pStateKey);
126✔
4952
    qDebug("===stream=== reload state. next window info %" PRId64 ", %" PRIu64 ", compare:%d",
126✔
4953
           nextInfo.winInfo.sessionWin.win.skey, nextInfo.winInfo.sessionWin.groupId, cpRes);
4954
    if (cpRes) {
126!
4955
      code = compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pSeUpdated, pInfo->pSeDeleted);
×
4956
      qDebug("===stream=== reload state. save result %" PRId64 ", %" PRIu64, curInfo.winInfo.sessionWin.win.skey,
×
4957
             curInfo.winInfo.sessionWin.groupId);
4958
      QUERY_CHECK_CODE(code, lino, _end);
×
4959

4960
      if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
4961
        code = saveResult(curInfo.winInfo, pInfo->pSeUpdated);
×
4962
        QUERY_CHECK_CODE(code, lino, _end);
×
4963
      } else if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
×
4964
        if (!isCloseWindow(&curInfo.winInfo.sessionWin.win, &pInfo->twAggSup)) {
×
4965
          code = saveDeleteRes(pInfo->pSeDeleted, curInfo.winInfo.sessionWin);
×
4966
          QUERY_CHECK_CODE(code, lino, _end);
×
4967
        }
4968
        SSessionKey key = {0};
×
4969
        getSessionHashKey(&curInfo.winInfo.sessionWin, &key);
×
4970
        code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curInfo.winInfo,
×
4971
                              sizeof(SResultWindowInfo));
4972
        QUERY_CHECK_CODE(code, lino, _end);
×
4973
      }
4974
    } else if (IS_VALID_SESSION_WIN(nextInfo.winInfo)) {
126!
4975
      releaseOutputBuf(pAggSup->pState, nextInfo.winInfo.pStatePos, &pAggSup->pSessionAPI->stateStore);
×
4976
    }
4977

4978
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
126!
4979
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
126✔
4980
      QUERY_CHECK_CODE(code, lino, _end);
126!
4981
    }
4982
  }
4983
  taosMemoryFreeClear(pBuf);
85!
4984

4985
  SOperatorInfo* downstream = pOperator->pDownstream[0];
85✔
4986
  if (downstream->fpSet.reloadStreamStateFn) {
85!
4987
    downstream->fpSet.reloadStreamStateFn(downstream);
85✔
4988
  }
4989
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
85✔
4990

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

4998
int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
324✔
4999
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5000
  QRY_PARAM_CHECK(pOptrInfo);
324!
5001
  int32_t code = 0;
324✔
5002
  int32_t lino = 0;
324✔
5003

5004
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
324✔
5005
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
324✔
5006
  SColumnNode*                 pColNode = (SColumnNode*)(pStateNode->pStateKey);
324✔
5007
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
324!
5008
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
324!
5009
  if (pInfo == NULL || pOperator == NULL) {
324!
5010
    code = terrno;
×
5011
    QUERY_CHECK_CODE(code, lino, _error);
×
5012
  }
5013

5014
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
324✔
5015
  initResultSizeInfo(&pOperator->resultInfo, 4096);
324✔
5016
  if (pStateNode->window.pExprs != NULL) {
324✔
5017
    int32_t    numOfScalar = 0;
25✔
5018
    SExprInfo* pScalarExprInfo = NULL;
25✔
5019
    code = createExprInfo(pStateNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
25✔
5020
    QUERY_CHECK_CODE(code, lino, _error);
25!
5021

5022
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
25✔
5023
    QUERY_CHECK_CODE(code, lino, _error);
25!
5024
  }
5025

5026
  pInfo->twAggSup = (STimeWindowAggSupp){
324✔
5027
      .waterMark = pStateNode->window.watermark,
324✔
5028
      .calTrigger = pStateNode->window.triggerType,
324✔
5029
      .maxTs = INT64_MIN,
5030
      .minTs = INT64_MAX,
5031
      .deleteMark = getDeleteMark(&pStateNode->window, 0),
324✔
5032
  };
5033

5034
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
324✔
5035
  QUERY_CHECK_CODE(code, lino, _error);
324!
5036

5037
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
324✔
5038
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
324!
5039
  pInfo->binfo.pRes = pResBlock;
324✔
5040

5041
  SExprSupp* pExpSup = &pOperator->exprSupp;
324✔
5042
  int32_t    numOfCols = 0;
324✔
5043
  SExprInfo* pExprInfo = NULL;
324✔
5044
  code = createExprInfo(pStateNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
324✔
5045
  QUERY_CHECK_CODE(code, lino, _error);
324!
5046

5047
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
324✔
5048
  if (code != TSDB_CODE_SUCCESS) {
324!
5049
    goto _error;
×
5050
  }
5051
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
324✔
5052
  int16_t type = pColNode->node.resType.type;
324✔
5053
  pInfo->primaryTsIndex = tsSlotId;
324✔
5054
  code =
5055
      initStreamAggSupporter(&pInfo->streamAggSup, pExpSup, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize, type,
324✔
5056
                             &pTaskInfo->storageAPI.stateStore, pHandle, &pInfo->twAggSup, GET_TASKID(pTaskInfo),
324✔
5057
                             &pTaskInfo->storageAPI, pInfo->primaryTsIndex, STREAM_STATE_BUFF_SORT, 1);
5058
  QUERY_CHECK_CODE(code, lino, _error);
324!
5059

5060
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
324✔
5061
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
324✔
5062
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
324!
5063
  pInfo->pDelIterator = NULL;
324✔
5064

5065
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
324✔
5066
  QUERY_CHECK_CODE(code, lino, _error);
324!
5067

5068
  pInfo->pChildren = NULL;
324✔
5069
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
324✔
5070
  pInfo->ignoreExpiredDataSaved = false;
324✔
5071
  pInfo->pUpdated = NULL;
324✔
5072
  pInfo->pSeUpdated = NULL;
324✔
5073
  pInfo->dataVersion = 0;
324✔
5074
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
324✔
5075
  if (!pInfo->historyWins) {
324!
5076
    code = terrno;
×
5077
    QUERY_CHECK_CODE(code, lino, _error);
×
5078
  }
5079

5080
  if (pHandle) {
324!
5081
    pInfo->isHistoryOp = pHandle->fillHistory;
324✔
5082
  }
5083

5084
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
324✔
5085
  QUERY_CHECK_CODE(code, lino, _error);
324!
5086

5087
  pInfo->recvGetAll = false;
324✔
5088
  pInfo->pPkDeleted = tSimpleHashInit(64, hashFn);
324✔
5089
  QUERY_CHECK_NULL(pInfo->pPkDeleted, code, lino, _error, terrno);
324!
5090
  pInfo->destHasPrimaryKey = pStateNode->window.destHasPrimaryKey;
324✔
5091
  pInfo->pOperator = pOperator;
324✔
5092

5093
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
324✔
5094
                  pInfo, pTaskInfo);
5095
  // for stream
5096
  void*   buff = NULL;
324✔
5097
  int32_t len = 0;
324✔
5098
  int32_t res =
5099
      pInfo->streamAggSup.stateStore.streamStateGetInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_CHECKPOINT_NAME,
324✔
5100
                                                        strlen(STREAM_STATE_OP_CHECKPOINT_NAME), &buff, &len);
5101
  if (res == TSDB_CODE_SUCCESS) {
324!
5102
    code = doStreamStateDecodeOpState(buff, len, pOperator, true, NULL);
×
5103
    taosMemoryFree(buff);
×
5104
    QUERY_CHECK_CODE(code, lino, _error);
×
5105
  }
5106

5107
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAggNext, NULL, destroyStreamStateOperatorInfo,
324✔
5108
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5109
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
324✔
5110
  code = initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex,
324✔
5111
                        &pInfo->twAggSup, &pInfo->basic);
324✔
5112
  QUERY_CHECK_CODE(code, lino, _error);
324!
5113

5114
  code = appendDownstream(pOperator, &downstream, 1);
324✔
5115
  QUERY_CHECK_CODE(code, lino, _error);
323!
5116

5117
  *pOptrInfo = pOperator;
323✔
5118
  return TSDB_CODE_SUCCESS;
323✔
5119

5120
_error:
×
5121
  if (pInfo != NULL) destroyStreamStateOperatorInfo(pInfo);
×
5122
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5123
  pTaskInfo->code = code;
×
5124
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5125
  return code;
×
5126
}
5127

5128
#ifdef BUILD_NO_CALL
5129
static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type) {
5130
  for (int i = 0; i < num; i++) {
5131
    if (type == STREAM_INVERT) {
5132
      fmSetInvertFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5133
    } else if (type == STREAM_NORMAL) {
5134
      fmSetNormalFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
5135
    }
5136
  }
5137
}
5138
#endif
5139

5140
static int32_t doStreamIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
152,179✔
5141
  int32_t                      code = TSDB_CODE_SUCCESS;
152,179✔
5142
  int32_t                      lino = 0;
152,179✔
5143
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
152,179✔
5144
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
152,179✔
5145
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
152,179✔
5146
  SExprSupp*                   pSup = &pOperator->exprSupp;
152,179✔
5147

5148
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
152,179✔
5149

5150
  if (pOperator->status == OP_EXEC_DONE) {
152,179✔
5151
    (*ppRes) = NULL;
666✔
5152
    return code;
666✔
5153
  }
5154

5155
  if (pOperator->status == OP_RES_TO_RETURN) {
151,513✔
5156
    SSDataBlock* resBlock = NULL;
123,772✔
5157
    code = buildIntervalResult(pOperator, &resBlock);
123,772✔
5158
    QUERY_CHECK_CODE(code, lino, _end);
123,773!
5159
    if (resBlock != NULL) {
123,773✔
5160
      (*ppRes) = resBlock;
108,731✔
5161
      return code;
123,772✔
5162
    }
5163

5164
    if (pInfo->recvGetAll) {
15,042✔
5165
      pInfo->recvGetAll = false;
183✔
5166
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
183✔
5167
    }
5168

5169
    if (pInfo->reCkBlock) {
15,042✔
5170
      pInfo->reCkBlock = false;
118✔
5171
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
118✔
5172
      (*ppRes) = pInfo->pCheckpointRes;
118✔
5173
      return code;
118✔
5174
    }
5175

5176
    setStreamOperatorCompleted(pOperator);
14,924✔
5177
    (*ppRes) = NULL;
14,923✔
5178
    return code;
14,923✔
5179
  }
5180

5181
  SOperatorInfo* downstream = pOperator->pDownstream[0];
27,741✔
5182

5183
  if (!pInfo->pUpdated) {
27,741✔
5184
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
24,907✔
5185
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
24,911!
5186
  }
5187

5188
  if (!pInfo->pUpdatedMap) {
27,745✔
5189
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
24,912✔
5190
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
24,912✔
5191
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
24,916!
5192
  }
5193

5194
  while (1) {
1,171,516✔
5195
    SSDataBlock* pBlock = NULL;
1,199,265✔
5196
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
1,199,265✔
5197
    QUERY_CHECK_CODE(code, lino, _end);
1,208,134✔
5198

5199
    if (pBlock == NULL) {
1,208,126✔
5200
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
24,913✔
5201
             pInfo->numOfDatapack);
5202
      pInfo->numOfDatapack = 0;
24,913✔
5203
      break;
24,913✔
5204
    }
5205

5206
    pInfo->numOfDatapack++;
1,183,213✔
5207
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
1,183,213✔
5208
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
1,182,894✔
5209

5210
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
1,182,031✔
5211
        pBlock->info.type == STREAM_CLEAR) {
1,181,492✔
5212
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,491✔
5213
      QUERY_CHECK_CODE(code, lino, _end);
1,475!
5214
      continue;
3,657✔
5215
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,180,540✔
5216
      pInfo->recvGetAll = true;
1,043✔
5217
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
1,043✔
5218
      QUERY_CHECK_CODE(code, lino, _end);
1,043!
5219
      continue;
1,043✔
5220
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE || pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
1,179,497✔
5221
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,853✔
5222
      (*ppRes) = pBlock;
2,831✔
5223
      return code;
2,831✔
5224
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,176,644✔
5225
      pAPI->stateStore.streamStateCommit(pInfo->pState);
1,139✔
5226
      doStreamIntervalSaveCheckpoint(pOperator);
1,139✔
5227
      pInfo->reCkBlock = true;
1,139✔
5228
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
1,139✔
5229
      QUERY_CHECK_CODE(code, lino, _end);
1,139!
5230

5231
      continue;
1,139✔
5232
    } else {
5233
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,175,505!
5234
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5235
        QUERY_CHECK_CODE(code, lino, _end);
×
5236
      }
5237
    }
5238

5239
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
1,175,505✔
5240
      // set input version
5241
      pTaskInfo->version = pBlock->info.version;
327,036✔
5242
    }
5243

5244
    if (pInfo->scalarSupp.pExprInfo != NULL) {
1,175,505✔
5245
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5246
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5247
      QUERY_CHECK_CODE(code, lino, _end);
13!
5248
    }
5249

5250
    // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
5251
    // caller. Note that all the time window are not close till now.
5252
    // the pDataBlock are always the same one, no need to call this again
5253
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
1,175,505✔
5254
    QUERY_CHECK_CODE(code, lino, _end);
1,172,964!
5255
#ifdef BUILD_NO_CALL
5256
    if (pInfo->invertible) {
5257
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
5258
    }
5259
#endif
5260

5261
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
1,172,964✔
5262
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
1,167,859!
5263
      pOperator->status = OP_RES_TO_RETURN;
×
5264
      code = TSDB_CODE_SUCCESS;
×
5265
      break;
×
5266
    }
5267
    QUERY_CHECK_CODE(code, lino, _end);
1,167,859!
5268
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
1,167,859✔
5269
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
1,167,859✔
5270
  }
5271
  pOperator->status = OP_RES_TO_RETURN;
24,913✔
5272
  if (!pInfo->destHasPrimaryKey) {
24,913✔
5273
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
24,912✔
5274
  }
5275
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
24,910✔
5276
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5277
  QUERY_CHECK_CODE(code, lino, _end);
24,907!
5278

5279
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
24,907!
UNCOV
5280
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
×
5281
    QUERY_CHECK_CODE(code, lino, _end);
×
5282
  }
5283

5284
  void*   pIte = NULL;
24,907✔
5285
  int32_t iter = 0;
24,907✔
5286
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
10,911,198✔
5287
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
10,885,810✔
5288
    if (!tmp) {
10,886,291!
5289
      code = terrno;
×
5290
      QUERY_CHECK_CODE(code, lino, _end);
×
5291
    }
5292
  }
5293
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
25,105✔
5294

5295
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
24,912✔
5296
  pInfo->pUpdated = NULL;
24,912✔
5297
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
24,912✔
5298
  QUERY_CHECK_CODE(code, lino, _end);
24,913!
5299

5300
  tSimpleHashCleanup(pInfo->pUpdatedMap);
24,913✔
5301
  pInfo->pUpdatedMap = NULL;
24,912✔
5302

5303
  code = buildIntervalResult(pOperator, ppRes);
24,912✔
5304
  QUERY_CHECK_CODE(code, lino, _end);
24,911!
5305

5306
  return code;
24,911✔
5307

5308
_end:
8✔
5309
  if (code != TSDB_CODE_SUCCESS) {
8!
5310
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
8!
5311
    pTaskInfo->code = code;
8✔
5312
    T_LONG_JMP(pTaskInfo->env, code);
8!
5313
  }
5314
  setStreamOperatorCompleted(pOperator);
×
5315
  (*ppRes) = NULL;
×
5316
  return code;
×
5317
}
5318

5319
static int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
3,034✔
5320
                                                      SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5321
  QRY_PARAM_CHECK(pOptrInfo);
3,034!
5322

5323
  int32_t code = TSDB_CODE_SUCCESS;
3,034✔
5324
  int32_t lino = 0;
3,034✔
5325
  int32_t numOfCols = 0;
3,034✔
5326

5327
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
3,034!
5328
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3,034!
5329
  if (pInfo == NULL || pOperator == NULL) {
3,034!
5330
    code = terrno;
×
5331
    QUERY_CHECK_CODE(code, lino, _error);
×
5332
  }
5333

5334
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3,034✔
5335

5336
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3,034✔
5337
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
3,034!
5338
  initBasicInfo(&pInfo->binfo, pResBlock);
3,034✔
5339

5340
  pInfo->interval = (SInterval){
3,034✔
5341
      .interval = pIntervalPhyNode->interval,
3,034✔
5342
      .sliding = pIntervalPhyNode->sliding,
3,034✔
5343
      .intervalUnit = pIntervalPhyNode->intervalUnit,
3,034✔
5344
      .slidingUnit = pIntervalPhyNode->slidingUnit,
3,034✔
5345
      .offset = pIntervalPhyNode->offset,
3,034✔
5346
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
3,034✔
5347
      .timeRange = pIntervalPhyNode->timeRange,
3,034✔
5348
  };
5349
  calcIntervalAutoOffset(&pInfo->interval);
3,034✔
5350

5351
  pInfo->twAggSup =
3,034✔
5352
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
3,034✔
5353
                           .calTrigger = pIntervalPhyNode->window.triggerType,
3,034✔
5354
                           .maxTs = INT64_MIN,
5355
                           .minTs = INT64_MAX,
5356
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
3,034✔
5357

5358
  pOperator->pTaskInfo = pTaskInfo;
3,034✔
5359
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3,034✔
5360

5361
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
3,034✔
5362
  pInfo->ignoreExpiredDataSaved = false;
3,034✔
5363

5364
  SExprSupp* pSup = &pOperator->exprSupp;
3,034✔
5365
  pSup->hasWindowOrGroup = true;
3,034✔
5366

5367
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
3,034✔
5368
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5369

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

5373
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
3,034!
5374
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
3,034!
5375
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
3,034✔
5376
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
3,034✔
5377

5378
  size_t     keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
3,034✔
5379
  SExprInfo* pExprInfo = NULL;
3,034✔
5380
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
3,034✔
5381
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5382
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str, pInfo->pState,
3,034✔
5383
                    &pTaskInfo->storageAPI.functionStore);
5384
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5385

5386
  if (pIntervalPhyNode->window.pExprs != NULL) {
3,034✔
5387
    int32_t    numOfScalar = 0;
1✔
5388
    SExprInfo* pScalarExprInfo = NULL;
1✔
5389

5390
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5391
    QUERY_CHECK_CODE(code, lino, _error);
1!
5392

5393
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
5394
    QUERY_CHECK_CODE(code, lino, _error);
1!
5395
  }
5396

5397
  pInfo->invertible = false;
3,034✔
5398
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
3,034✔
5399
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
3,034!
5400
  pInfo->delIndex = 0;
3,034✔
5401

5402
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
3,034✔
5403
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5404

5405
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
3,034✔
5406

5407
  pInfo->pPhyNode = NULL;  // create new child
3,034✔
5408
  pInfo->pPullDataMap = NULL;
3,034✔
5409
  pInfo->pFinalPullDataMap = NULL;
3,034✔
5410
  pInfo->pPullWins = NULL;  // SPullWindowInfo
3,034✔
5411
  pInfo->pullIndex = 0;
3,034✔
5412
  pInfo->pPullDataRes = NULL;
3,034✔
5413
  pInfo->numOfChild = 0;
3,034✔
5414
  pInfo->delKey.ts = INT64_MAX;
3,034✔
5415
  pInfo->delKey.groupId = 0;
3,034✔
5416
  pInfo->numOfDatapack = 0;
3,034✔
5417
  pInfo->pUpdated = NULL;
3,034✔
5418
  pInfo->pUpdatedMap = NULL;
3,034✔
5419
  int32_t funResSize = getMaxFunResSize(pSup, numOfCols);
3,034✔
5420

5421
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
3,034✔
5422
  pInfo->pState->pFileState = NULL;
3,034✔
5423

5424
  // used for backward compatibility of function's result info
5425
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
3,034✔
5426
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
3,034✔
5427
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
3,034✔
5428

5429
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
3,034✔
5430
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
3,034✔
5431
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
3,034✔
5432
      &pInfo->pState->pFileState);
3,034✔
5433
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5434

5435
  pInfo->pOperator = pOperator;
3,034✔
5436
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
3,034✔
5437
                  pInfo, pTaskInfo);
5438
  pOperator->fpSet =
5439
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
3,034✔
5440
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5441
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
3,034✔
5442

5443
  pInfo->recvGetAll = false;
3,034✔
5444

5445
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
3,034✔
5446
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5447

5448
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
3,034✔
5449
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
3,034✔
5450
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
3,034!
5451
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
3,034✔
5452

5453
  // for stream
5454
  void*   buff = NULL;
3,034✔
5455
  int32_t len = 0;
3,034✔
5456
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
3,034✔
5457
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
5458
  if (res == TSDB_CODE_SUCCESS) {
3,034✔
5459
    doStreamIntervalDecodeOpState(buff, len, pOperator);
8✔
5460
    taosMemoryFree(buff);
8!
5461
  }
5462

5463
  pInfo->basic.primaryPkIndex = -1;
3,034✔
5464
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
3,034✔
5465
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5466

5467
  code = appendDownstream(pOperator, &downstream, 1);
3,034✔
5468
  QUERY_CHECK_CODE(code, lino, _error);
3,034!
5469

5470
  *pOptrInfo = pOperator;
3,034✔
5471
  return TSDB_CODE_SUCCESS;
3,034✔
5472

5473
_error:
×
5474
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
5475
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5476
  pTaskInfo->code = code;
×
5477
  return code;
×
5478
}
5479

5480
int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
3,086✔
5481
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5482
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3,086✔
5483
  if (pIntervalPhyNode->window.triggerType == STREAM_TRIGGER_FORCE_WINDOW_CLOSE) {
3,086✔
5484
    return createStreamIntervalSliceOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
52✔
5485
  } else {
5486
    return createStreamSingleIntervalOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
3,034✔
5487
  }
5488
  return TSDB_CODE_SUCCESS;
5489
}
5490

5491
static void doStreamMidIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pUpdatedMap) {
41✔
5492
  int32_t                      code = TSDB_CODE_SUCCESS;
41✔
5493
  int32_t                      lino = 0;
41✔
5494
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
41✔
5495
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
41✔
5496

5497
  SResultRowInfo*  pResultRowInfo = &(pInfo->binfo.resultRowInfo);
41✔
5498
  SExecTaskInfo*   pTaskInfo = pOperator->pTaskInfo;
41✔
5499
  SExprSupp*       pSup = &pOperator->exprSupp;
41✔
5500
  int32_t          numOfOutput = pSup->numOfExprs;
41✔
5501
  int32_t          step = 1;
41✔
5502
  SRowBuffPos*     pResPos = NULL;
41✔
5503
  SResultRow*      pResult = NULL;
41✔
5504
  int32_t          forwardRows = 1;
41✔
5505
  uint64_t         groupId = pSDataBlock->info.id.groupId;
41✔
5506
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
41✔
5507
  TSKEY*           tsCol = (int64_t*)pColDataInfo->pData;
41✔
5508

5509
  int32_t     startPos = 0;
41✔
5510
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
41✔
5511
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
41✔
5512

5513
  while (1) {
1,256✔
5514
    SWinKey key = {
1,297✔
5515
        .ts = nextWin.skey,
1,297✔
5516
        .groupId = groupId,
5517
    };
5518
    void*   chIds = taosHashGet(pInfo->pPullDataMap, &key, sizeof(SWinKey));
1,297✔
5519
    int32_t index = -1;
1,304✔
5520
    SArray* chArray = NULL;
1,304✔
5521
    int32_t chId = 0;
1,304✔
5522
    if (chIds) {
1,304✔
5523
      chArray = *(void**)chIds;
4✔
5524
      chId = getChildIndex(pSDataBlock);
4✔
5525
      index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
4✔
5526
    }
5527
    if (!(index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA)) {
1,304!
5528
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, startPos);
×
5529
      if (startPos < 0) {
×
5530
        break;
41✔
5531
      }
5532
      continue;
×
5533
    }
5534

5535
    if (!inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,304!
5536
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCol, startPos, nextWin.ekey, &nextWin);
×
5537
      if (startPos < 0) {
×
5538
        break;
×
5539
      }
5540
      continue;
×
5541
    }
5542

5543
    int32_t winCode = TSDB_CODE_SUCCESS;
1,304✔
5544
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
1,304✔
5545
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
5546
    QUERY_CHECK_CODE(code, lino, _end);
1,301!
5547

5548
    pResult = (SResultRow*)pResPos->pRowBuff;
1,301✔
5549

5550
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,301!
5551
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,301✔
5552
      QUERY_CHECK_CODE(code, lino, _end);
1,301!
5553
    }
5554

5555
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,301!
5556
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
×
5557
      QUERY_CHECK_CODE(code, lino, _end);
×
5558
    }
5559

5560
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
1,301✔
5561
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
1,301✔
5562
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
1,301✔
5563
    QUERY_CHECK_CODE(code, lino, _end);
1,297!
5564
    key.ts = nextWin.skey;
1,297✔
5565

5566
    if (pInfo->delKey.ts > key.ts) {
1,297✔
5567
      pInfo->delKey = key;
10✔
5568
    }
5569
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
1,297✔
5570
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
1,297!
5571
      qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64
×
5572
             ",maxKey %" PRId64,
5573
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5574
      code = blockDataUpdateTsWindow(pSDataBlock, 0);
×
5575
      QUERY_CHECK_CODE(code, lino, _end);
×
5576

5577
      // timestamp of the data is incorrect
5578
      if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
×
5579
        qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
×
5580
               pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
5581
      }
5582
    }
5583
    startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCol, prevEndPos);
1,297✔
5584
    if (startPos < 0) {
1,297✔
5585
      break;
41✔
5586
    }
5587
  }
5588

5589
_end:
41✔
5590
  if (code != TSDB_CODE_SUCCESS) {
41!
5591
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5592
  }
5593
}
41✔
5594

5595
static int32_t addMidRetriveWindow(SArray* wins, SHashObj* pMidPullMap, int32_t numOfChild) {
12✔
5596
  int32_t code = TSDB_CODE_SUCCESS;
12✔
5597
  int32_t lino = 0;
12✔
5598
  int32_t size = taosArrayGetSize(wins);
12✔
5599
  for (int32_t i = 0; i < size; i++) {
18✔
5600
    SWinKey* winKey = taosArrayGet(wins, i);
6✔
5601
    void*    chIds = taosHashGet(pMidPullMap, winKey, sizeof(SWinKey));
6✔
5602
    if (!chIds) {
6!
5603
      code = addPullWindow(pMidPullMap, winKey, numOfChild);
6✔
5604
      qDebug("===stream===prepare mid operator retrive for delete %" PRId64 ", size:%d", winKey->ts, numOfChild);
6!
5605
      QUERY_CHECK_CODE(code, lino, _end);
6!
5606
    }
5607
  }
5608
_end:
12✔
5609
  if (code != TSDB_CODE_SUCCESS) {
12!
5610
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5611
  }
5612
  return code;
12✔
5613
}
5614

5615
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
109✔
5616
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
109✔
5617
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
109✔
5618
  uint16_t                     opType = pOperator->operatorType;
109✔
5619

5620
  if (pInfo->recvPullover) {
109✔
5621
    pInfo->recvPullover = false;
6✔
5622
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5623
    return pInfo->pMidPulloverRes;
6✔
5624
  }
5625

5626
  qDebug("===stream=== build mid interval result");
103!
5627
  doBuildDeleteResult(pInfo, pInfo->pMidPullDatas, &pInfo->midDelIndex, pInfo->pDelRes);
103✔
5628
  if (pInfo->pDelRes->info.rows != 0) {
103!
5629
    // process the rest of the data
5630
    printDataBlock(pInfo->pDelRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
×
5631
    return pInfo->pDelRes;
×
5632
  }
5633

5634
  if (pInfo->recvRetrive) {
103✔
5635
    pInfo->recvRetrive = false;
12✔
5636
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5637
    return pInfo->pMidRetriveRes;
12✔
5638
  }
5639

5640
  return NULL;
91✔
5641
}
5642

5643
static int32_t doStreamMidIntervalAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
111✔
5644
  int32_t                      code = TSDB_CODE_SUCCESS;
111✔
5645
  int32_t                      lino = 0;
111✔
5646
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
111✔
5647
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
111✔
5648
  SStorageAPI*                 pAPI = &pOperator->pTaskInfo->storageAPI;
111✔
5649
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
111✔
5650
  SExprSupp*                   pSup = &pOperator->exprSupp;
111✔
5651

5652
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
111!
5653

5654
  if (pOperator->status == OP_EXEC_DONE) {
111!
5655
    (*ppRes) = NULL;
×
5656
    return code;
×
5657
  } else if (pOperator->status == OP_RES_TO_RETURN) {
111✔
5658
    SSDataBlock* resBlock = NULL;
38✔
5659
    code = buildIntervalResult(pOperator, &resBlock);
38✔
5660
    QUERY_CHECK_CODE(code, lino, _end);
38!
5661
    if (resBlock != NULL) {
38✔
5662
      (*ppRes) = resBlock;
10✔
5663
      return code;
38✔
5664
    }
5665

5666
    setOperatorCompleted(pOperator);
28✔
5667
    clearFunctionContext(&pOperator->exprSupp);
28✔
5668
    clearStreamIntervalOperator(pInfo);
28✔
5669
    qDebug("stask:%s  ===stream===%s clear", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType));
28!
5670
    (*ppRes) = NULL;
28✔
5671
    return code;
28✔
5672
  } else {
5673
    SSDataBlock* resBlock = NULL;
73✔
5674
    code = buildIntervalResult(pOperator, &resBlock);
73✔
5675
    QUERY_CHECK_CODE(code, lino, _end);
73!
5676
    if (resBlock != NULL) {
73!
5677
      (*ppRes) = resBlock;
×
5678
      return code;
3✔
5679
    }
5680

5681
    resBlock = buildMidIntervalResult(pOperator);
73✔
5682
    if (resBlock != NULL) {
73✔
5683
      (*ppRes) = resBlock;
3✔
5684
      return code;
3✔
5685
    }
5686

5687
    if (pInfo->clearState) {
70✔
5688
      pInfo->clearState = false;
18✔
5689
      clearFunctionContext(&pOperator->exprSupp);
18✔
5690
      clearStreamIntervalOperator(pInfo);
18✔
5691
    }
5692
  }
5693

5694
  if (!pInfo->pUpdated) {
70✔
5695
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
67✔
5696
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
67!
5697
  }
5698
  if (!pInfo->pUpdatedMap) {
70✔
5699
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
67✔
5700
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
67✔
5701
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
67!
5702
  }
5703

5704
  while (1) {
57✔
5705
    if (isTaskKilled(pTaskInfo)) {
127!
5706
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
5707
      (*ppRes) = NULL;
×
5708
      return code;
3✔
5709
    }
5710

5711
    SSDataBlock* pBlock = NULL;
127✔
5712
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
127✔
5713
    QUERY_CHECK_CODE(code, lino, _end);
127!
5714

5715
    if (pBlock == NULL) {
127✔
5716
      pOperator->status = OP_RES_TO_RETURN;
49✔
5717
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
49!
5718
             pInfo->numOfDatapack);
5719
      pInfo->numOfDatapack = 0;
49✔
5720
      break;
49✔
5721
    }
5722
    pInfo->numOfDatapack++;
78✔
5723
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
78✔
5724
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
78✔
5725

5726
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
78✔
5727
      pInfo->binfo.pRes->info.type = pBlock->info.type;
11✔
5728
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
67!
5729
               pBlock->info.type == STREAM_CLEAR) {
65✔
5730
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
3✔
5731
      if (!delWins) {
3!
5732
        code = terrno;
×
5733
        QUERY_CHECK_CODE(code, lino, _end);
×
5734
      }
5735
      code =
5736
          doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, pInfo->pFinalPullDataMap);
3✔
5737
      QUERY_CHECK_CODE(code, lino, _end);
3!
5738

5739
      removeResults(delWins, pInfo->pUpdatedMap);
3✔
5740
      void* tmp = taosArrayAddAll(pInfo->pDelWins, delWins);
3✔
5741
      if (!tmp && taosArrayGetSize(delWins) > 0) {
3!
5742
        code = TSDB_CODE_OUT_OF_MEMORY;
×
5743
        QUERY_CHECK_CODE(code, lino, _end);
×
5744
      }
5745
      taosArrayDestroy(delWins);
3✔
5746

5747
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
3✔
5748
      if (pInfo->pDelRes->info.rows != 0) {
3!
5749
        // process the rest of the data
5750
        printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
3✔
5751
        if (pBlock->info.type == STREAM_CLEAR) {
3✔
5752
          pInfo->pDelRes->info.type = STREAM_CLEAR;
1✔
5753
        } else {
5754
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
2✔
5755
        }
5756
        (*ppRes) = pInfo->pDelRes;
3✔
5757
        return code;
3✔
5758
      }
5759
      continue;
16✔
5760
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
64!
5761
      (*ppRes) = pBlock;
×
5762
      return code;
×
5763
    } else if (pBlock->info.type == STREAM_PULL_OVER) {
64✔
5764
      code = processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins,
12✔
5765
                             pInfo->numOfChild, pOperator, &pInfo->recvPullover);
5766
      QUERY_CHECK_CODE(code, lino, _end);
12!
5767

5768
      if (pInfo->recvPullover) {
12✔
5769
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
5770
        QUERY_CHECK_CODE(code, lino, _end);
6!
5771

5772
        pInfo->clearState = true;
6✔
5773
        break;
6✔
5774
      }
5775
      continue;
6✔
5776
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
52✔
5777
      pAPI->stateStore.streamStateCommit(pInfo->pState);
10✔
5778
      doStreamIntervalSaveCheckpoint(pOperator);
10✔
5779
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
10✔
5780
      QUERY_CHECK_CODE(code, lino, _end);
10!
5781

5782
      continue;
10✔
5783
    } else if (pBlock->info.type == STREAM_MID_RETRIEVE) {
42✔
5784
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
12✔
5785
      if (!delWins) {
12!
5786
        code = terrno;
×
5787
        QUERY_CHECK_CODE(code, lino, _end);
×
5788
      }
5789
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, NULL);
12✔
5790
      QUERY_CHECK_CODE(code, lino, _end);
12!
5791

5792
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
5793
      QUERY_CHECK_CODE(code, lino, _end);
12!
5794

5795
      taosArrayDestroy(delWins);
12✔
5796
      pInfo->recvRetrive = true;
12✔
5797
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
12✔
5798
      QUERY_CHECK_CODE(code, lino, _end);
12!
5799

5800
      pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
12✔
5801
      pInfo->clearState = true;
12✔
5802
      break;
12✔
5803
    } else {
5804
      if (pBlock->info.type != STREAM_INVALID) {
30!
5805
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5806
        QUERY_CHECK_CODE(code, lino, _end);
×
5807
      }
5808
    }
5809

5810
    if (pInfo->scalarSupp.pExprInfo != NULL) {
41!
5811
      SExprSupp* pExprSup = &pInfo->scalarSupp;
×
5812
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
×
5813
      QUERY_CHECK_CODE(code, lino, _end);
×
5814
    }
5815
    code = setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
41✔
5816
    QUERY_CHECK_CODE(code, lino, _end);
41!
5817
    doStreamMidIntervalAggImpl(pOperator, pBlock, pInfo->pUpdatedMap);
41✔
5818
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
41✔
5819
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
41✔
5820
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
41✔
5821
  }
5822

5823
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
67✔
5824
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
67✔
5825

5826
  void*   pIte = NULL;
67✔
5827
  int32_t iter = 0;
67✔
5828
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,371✔
5829
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,304✔
5830
    if (!tmp) {
1,304!
5831
      code = terrno;
×
5832
      QUERY_CHECK_CODE(code, lino, _end);
×
5833
    }
5834
  }
5835

5836
  tSimpleHashCleanup(pInfo->pUpdatedMap);
67✔
5837
  pInfo->pUpdatedMap = NULL;
67✔
5838
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
67✔
5839

5840
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
67✔
5841
  pInfo->pUpdated = NULL;
67✔
5842
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
67✔
5843
  QUERY_CHECK_CODE(code, lino, _end);
67!
5844

5845
  SSDataBlock* resBlock = NULL;
67✔
5846
  code = buildIntervalResult(pOperator, &resBlock);
67✔
5847
  QUERY_CHECK_CODE(code, lino, _end);
67!
5848
  if (resBlock != NULL) {
67✔
5849
    (*ppRes) = resBlock;
31✔
5850
    return code;
31✔
5851
  }
5852

5853
  resBlock = buildMidIntervalResult(pOperator);
36✔
5854
  if (resBlock != NULL) {
36✔
5855
    (*ppRes) = resBlock;
15✔
5856
    return code;
15✔
5857
  }
5858

5859
  if (pInfo->clearState) {
21!
5860
    pInfo->clearState = false;
×
5861
    clearFunctionContext(&pOperator->exprSupp);
×
5862
    clearStreamIntervalOperator(pInfo);
×
5863
  }
5864

5865
_end:
21✔
5866
  if (code != TSDB_CODE_SUCCESS) {
21!
5867
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5868
    pTaskInfo->code = code;
×
5869
    T_LONG_JMP(pTaskInfo->env, code);
×
5870
  }
5871
  (*ppRes) = NULL;
21✔
5872
  return code;
21✔
5873
}
5874

5875
static SSDataBlock* doStreamMidIntervalAgg(SOperatorInfo* pOperator) {
×
5876
  SSDataBlock* pRes = NULL;
×
5877
  int32_t      code = doStreamMidIntervalAggNext(pOperator, &pRes);
×
5878
  return pRes;
×
5879
}
5880

5881
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
34,357✔
5882
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
34,357✔
5883
         getStreamOpName(pOperator->operatorType), pOperator->status);
5884
  setOperatorCompleted(pOperator);
34,358✔
5885
}
34,357✔
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