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

taosdata / TDengine / #3531

19 Nov 2024 10:42AM UTC coverage: 60.213% (-0.006%) from 60.219%
#3531

push

travis-ci

web-flow
Merge pull request #28777 from taosdata/fix/3.0/TD-32366

fix:TD-32366/stmt add geometry datatype check

118529 of 252344 branches covered (46.97%)

Branch coverage included in aggregate %.

7 of 48 new or added lines in 3 files covered. (14.58%)

2282 existing lines in 115 files now uncovered.

199096 of 275161 relevant lines covered (72.36%)

6067577.83 hits per line

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

68.65
/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,301✔
67
  int firstPos = 0, lastPos = num - 1, midPos = -1;
1,301✔
68
  int numOfRows = 0;
1,301✔
69

70
  if (num <= 0) return -1;
1,301✔
71
  if (order == TSDB_ORDER_DESC) {
1,143!
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,226✔
75
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
325✔
76
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;
195✔
77

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

81
      if (comparefn(pKey, keyList, midPos) < 0) {
144✔
82
        lastPos = midPos - 1;
45✔
83
      } else if (comparefn(pKey, keyList, midPos) > 0) {
99✔
84
        firstPos = midPos + 1;
38✔
85
      } else {
86
        break;
61✔
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;
61✔
118
}
119

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

130
  if (pData->window.skey > pos->window.ekey) {
42✔
131
    return 1;
36✔
132
  } else if (pData->window.ekey < pos->window.skey) {
6!
UNCOV
133
    return -1;
×
134
  }
135
  return 0;
6✔
136
}
137

138
static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
173✔
139
  int32_t size = taosArrayGetSize(pPullWins);
173✔
140
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
173✔
141
  if (index == -1) {
173✔
142
    index = 0;
138✔
143
  } else {
144
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
35✔
145
    if (code == 0) {
35✔
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) {
32!
153
      index++;
32✔
154
    }
155
  }
156
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
170!
157
    return terrno;
×
158
  }
159
  return TSDB_CODE_SUCCESS;
170✔
160
}
161

162
int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
2,869✔
163
  if (tSimpleHashGetSize(pStUpdated) > MAX_STREAM_HISTORY_RESULT) {
2,869!
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;
2,869✔
168
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
2,869✔
169
}
170

171
int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
6,257,126✔
172
  if (tSimpleHashGetSize(pUpdatedMap) > MAX_STREAM_HISTORY_RESULT) {
6,257,126!
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);
6,255,563✔
177
}
178

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

184
static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) {
153✔
185
  int32_t size = taosArrayGetSize(pWins);
153✔
186
  for (int32_t i = 0; i < size; i++) {
348✔
187
    SWinKey* pW = taosArrayGet(pWins, i);
195✔
188
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
195✔
189
    if (tmp) {
195!
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
}
153✔
197

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

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

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

226
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }
6,287,451✔
227

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

445
void destroyFlusedPos(void* pRes) {
×
446
  SRowBuffPos* pPos = (SRowBuffPos*)pRes;
×
447
  if (!pPos->needFree && !pPos->pRowBuff) {
×
448
    taosMemoryFreeClear(pPos->pKey);
×
449
    taosMemoryFree(pPos);
×
450
  }
451
}
×
452

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

458
void clearGroupResInfo(SGroupResInfo* pGroupResInfo) {
3,750✔
459
  if (pGroupResInfo->freeItem) {
3,750✔
460
    int32_t size = taosArrayGetSize(pGroupResInfo->pRows);
2,715✔
461
    for (int32_t i = pGroupResInfo->index; i < size; i++) {
2,715!
462
      void* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
×
463
      destroyFlusedPos(pPos);
×
464
    }
465
    pGroupResInfo->freeItem = false;
2,715✔
466
  }
467
  taosArrayDestroy(pGroupResInfo->pRows);
3,750✔
468
  pGroupResInfo->pRows = NULL;
3,750✔
469
  pGroupResInfo->index = 0;
3,750✔
470
}
3,750✔
471

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

488
  // it should be empty.
489
  void* pIte = NULL;
2,977✔
490
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
2,977!
491
    taosArrayDestroy(*(void**)pIte);
×
492
  }
493
  taosHashCleanup(pInfo->pPullDataMap);
2,977✔
494
  taosHashCleanup(pInfo->pFinalPullDataMap);
2,977✔
495
  taosArrayDestroy(pInfo->pPullWins);
2,977✔
496
  blockDataDestroy(pInfo->pPullDataRes);
2,977✔
497
  taosArrayDestroy(pInfo->pDelWins);
2,976✔
498
  blockDataDestroy(pInfo->pDelRes);
2,977✔
499
  blockDataDestroy(pInfo->pMidRetriveRes);
2,977✔
500
  blockDataDestroy(pInfo->pMidPulloverRes);
2,977✔
501
  if (pInfo->pUpdatedMap != NULL) {
2,976!
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) {
2,976!
509
    pInfo->stateStore.streamFileStateDestroy(pInfo->pState->pFileState);
2,977✔
510
  }
511
  taosArrayDestroy(pInfo->pMidPullDatas);
2,976✔
512

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

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

524
  blockDataDestroy(pInfo->pCheckpointRes);
2,977✔
525

526
  taosMemoryFreeClear(param);
2,975!
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,049✔
541
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;
1,049✔
542

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

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

552
bool hasSrcPrimaryKeyCol(SSteamOpBasicInfo* pInfo) { return pInfo->primaryPkIndex != -1; }
6,316,146✔
553

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

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

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

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

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

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

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

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

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

616
      pEntryInfo->numOfRes = 1;
52✔
617
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
143!
618
      code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
141✔
619
      QUERY_CHECK_CODE(code, lino, _end);
141!
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:
46✔
630
  if (code != TSDB_CODE_SUCCESS) {
48✔
631
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
632
  }
633
  return code;
48✔
634
}
635

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

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

649
  code = pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size, pWinCode);
6,279,546✔
650
  QUERY_CHECK_CODE(code, lino, _end);
6,334,423!
651

652
  *pResult = (SRowBuffPos*)value;
6,334,423✔
653
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
6,334,423✔
654

655
  // set time window for current result
656
  res->win = (*win);
6,334,423✔
657
  code = setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
6,334,423✔
658
  QUERY_CHECK_CODE(code, lino, _end);
6,260,767!
659

660
_end:
6,260,767✔
661
  if (code != TSDB_CODE_SUCCESS) {
6,260,767!
662
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
663
  }
664
  return code;
6,261,168✔
665
}
666

667
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup,
257,775✔
668
                           SStateStore* pStore) {
669
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
257,775✔
670
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
25✔
671
    if (!hasIntervalWindow(pState, &key, pStore)) {
25✔
672
      return true;
14✔
673
    }
674
    return false;
11✔
675
  }
676
  return false;
257,750✔
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) {
179✔
688
  int32_t code = TSDB_CODE_SUCCESS;
179✔
689
  int32_t lino = 0;
179✔
690
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
179✔
691
  QUERY_CHECK_NULL(childIds, code, lino, _end, terrno);
179!
692
  for (int32_t i = 0; i < size; i++) {
787✔
693
    void* tmp = taosArrayPush(childIds, &i);
608✔
694
    if (!tmp) {
608!
695
      code = terrno;
×
696
      QUERY_CHECK_CODE(code, lino, _end);
×
697
    }
698
  }
699
  code = taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
179✔
700
  QUERY_CHECK_CODE(code, lino, _end);
179!
701
_end:
179✔
702
  if (code != TSDB_CODE_SUCCESS) {
179!
703
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
704
  }
705
  return code;
179✔
706
}
707

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

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

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

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

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

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

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

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

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

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

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

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

813
            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
179✔
814
            if (pFinalCh) {
179✔
815
              int32_t tmpRes = taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
31✔
816
              qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
31!
817
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
31✔
818
              STimeWindow     nextWin = getFinalTimeWindow(winRes.ts, pInterval);
31✔
819
              SPullWindowInfo pull = {.window = nextWin,
31✔
820
                                      .groupId = winRes.groupId,
31✔
821
                                      .calWin.skey = nextWin.skey,
31✔
822
                                      .calWin.ekey = nextWin.skey};
31✔
823
              // add pull data request
824
              qDebug("===stream===prepare final retrive for delete window:%" PRId64 ",groupId:%" PRId64 ", size:%d",
31!
825
                     winRes.ts, winRes.groupId, numOfCh);
826
              if (IS_MID_INTERVAL_OP(pOperator)) {
31!
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) {
31!
835
                void* tmp = taosArrayPush(pInfo->pDelWins, &winRes);
31✔
836
                if (!tmp) {
31!
837
                  code = terrno;
×
838
                  QUERY_CHECK_CODE(code, lino, _end);
×
839
                }
840

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

844
                if (pInfo->destHasPrimaryKey) {
31!
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);
31!
849
              }
850
            }
851
          }
852
        }
853
      }
854
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
608✔
855
    }
856
  }
857
  if (pBeOver) {
442✔
858
    *pBeOver = res;
12✔
859
  }
860

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

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

884
        if (pInfo->destHasPrimaryKey) {
142!
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);
142!
889
      }
890
    } else {
UNCOV
891
      SArray* chArray = *(void**)chIds;
×
UNCOV
892
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
×
UNCOV
893
      qDebug("===stream===check final retrive %" PRId64 ",chid:%d", winKey->ts, index);
×
UNCOV
894
      if (index == -1) {
×
UNCOV
895
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
×
UNCOV
896
        code = taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
×
UNCOV
897
        QUERY_CHECK_CODE(code, lino, _end);
×
898
      }
899
    }
900
  }
901

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

909
static void clearFunctionContext(SExprSupp* pSup) {
2,602✔
910
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
17,197✔
911
    pSup->pCtx[i].saveHandle.currentPage = -1;
14,595✔
912
  }
913
}
2,602✔
914

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

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

930
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
10,225✔
931

932
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
6,275,266✔
933
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
6,270,959✔
934
    SResultRow*  pRow = NULL;
6,270,850✔
935
    code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
6,270,850✔
936
    QUERY_CHECK_CODE(code, lino, _end);
6,270,200!
937
    uint64_t groupId = ((SWinKey*)pPos->pKey)->groupId;
6,270,200✔
938
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
6,270,200✔
939
    // no results, continue to check the next one
940
    if (pRow->numOfRows == 0) {
6,269,010!
941
      pGroupResInfo->index += 1;
×
942
      continue;
×
943
    }
944
    if (pBlock->info.id.groupId == 0) {
6,269,010✔
945
      pBlock->info.id.groupId = groupId;
474,910✔
946
      void*   tbname = NULL;
474,910✔
947
      int32_t winCode = TSDB_CODE_SUCCESS;
474,910✔
948
      code = pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname,
474,910✔
949
                                                    false, &winCode);
950
      QUERY_CHECK_CODE(code, lino, _end);
475,552!
951
      if (winCode != TSDB_CODE_SUCCESS) {
475,552✔
952
        pBlock->info.parTbName[0] = 0;
471,208✔
953
      } else {
954
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
4,344✔
955
      }
956
      pAPI->stateStore.streamStateFreeVal(tbname);
475,552✔
957
    } else {
958
      // current value belongs to different group, it can't be packed into one datablock
959
      if (pBlock->info.id.groupId != groupId) {
5,794,100✔
960
        break;
2,894✔
961
      }
962
    }
963

964
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
6,267,884✔
965
      break;
1,187✔
966
    }
967
    pGroupResInfo->index += 1;
6,266,697✔
968

969
    for (int32_t j = 0; j < numOfExprs; ++j) {
59,503,961✔
970
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
53,238,920✔
971

972
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
53,238,920✔
973

974
      if (pCtx[j].fpSet.finalize) {
53,237,593✔
975
        int32_t tmpRes = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
35,295,547✔
976
        if (TAOS_FAILED(tmpRes)) {
35,304,204!
977
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(tmpRes));
×
978
          QUERY_CHECK_CODE(code, lino, _end);
×
979
        }
980
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
17,942,046✔
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);
17,862,714✔
986
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
17,860,463✔
987
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
35,717,901✔
988
          code = colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
17,858,613✔
989
          QUERY_CHECK_CODE(code, lino, _end);
17,857,438!
990
        }
991
      }
992
    }
993

994
    pBlock->info.rows += pRow->numOfRows;
6,265,041✔
995
  }
996

997
  pBlock->info.dataLoad = 1;
7,201✔
998
  code = blockDataUpdateTsWindow(pBlock, 0);
7,201✔
999
  QUERY_CHECK_CODE(code, lino, _end);
10,225!
1000

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

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

1013
  blockDataCleanup(pBlock);
34,688✔
1014
  if (!hasRemainResults(pGroupResInfo)) {
34,688✔
1015
    return;
24,463✔
1016
  }
1017

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

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

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

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

1052
  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
33,316✔
1053
  tsCols = (int64_t*)pColDataInfo->pData;
33,316✔
1054

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

1062
  if (pSDataBlock->info.window.skey != tsCols[0] || pSDataBlock->info.window.ekey != tsCols[endRowId]) {
33,316!
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;
33,316✔
1076
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
33,316✔
1077
  STimeWindow nextWin = {0};
33,316✔
1078
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
33,316✔
1079
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
2,626✔
1080
  } else {
1081
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
30,690✔
1082
  }
1083
  while (1) {
6,244,586✔
1084
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
6,277,902✔
1085
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
6,276,803!
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 &&
6,277,682!
1092
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
1,735✔
1093
                          nextWin.ekey, pPkVal, pkLen)) ||
6,272,953✔
1094
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
6,275,921!
1095
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
10✔
1096
      if (startPos < 0) {
45✔
1097
        break;
33,316✔
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;
51✔
1102
    }
1103

1104
    if (IS_FINAL_INTERVAL_OP(pOperator) && pInfo->numOfChild > 0) {
6,272,969!
1105
      bool    ignore = true;
256,706✔
1106
      SWinKey winRes = {
256,706✔
1107
          .ts = nextWin.skey,
256,706✔
1108
          .groupId = groupId,
1109
      };
1110
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
256,706✔
1111
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore) && isClosed &&
256,706!
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;
256,706✔
1127
        SArray* chArray = NULL;
256,706✔
1128
        int32_t chId = 0;
256,706✔
1129
        if (chIds) {
256,706✔
1130
          chArray = *(void**)chIds;
301✔
1131
          chId = getChildIndex(pSDataBlock);
301✔
1132
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
301✔
1133
        }
1134
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
256,706✔
1135
          ignore = false;
256,591✔
1136
        }
1137
      }
1138

1139
      if (ignore) {
256,706✔
1140
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
115✔
1141
        if (startPos < 0) {
115✔
1142
          break;
83✔
1143
        }
1144
        continue;
32✔
1145
      }
1146
    }
1147

1148
    int32_t winCode = TSDB_CODE_SUCCESS;
6,272,854✔
1149
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
6,272,854✔
1150
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
1151
    QUERY_CHECK_CODE(code, lino, _end);
6,259,668!
1152

1153
    pResult = (SResultRow*)pResPos->pRowBuff;
6,259,668✔
1154

1155
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
6,259,668✔
1156
      forwardRows = 1;
256,591✔
1157
    } else {
1158
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
6,003,077✔
1159
                                             NULL, TSDB_ORDER_ASC);
1160
    }
1161

1162
    SWinKey key = {
6,254,711✔
1163
        .ts = pResult->win.skey,
6,254,711✔
1164
        .groupId = groupId,
1165
    };
1166

1167
    if (pInfo->destHasPrimaryKey && winCode == TSDB_CODE_SUCCESS && IS_NORMAL_INTERVAL_OP(pOperator)) {
6,254,711!
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) {
6,254,711!
1173
      code = saveWinResult(&key, pResPos, pUpdatedMap);
6,251,156✔
1174
      QUERY_CHECK_CODE(code, lino, _end);
6,326,867!
1175
    }
1176

1177
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
6,330,422✔
1178
      pResPos->beUpdated = true;
6,132✔
1179
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
6,132✔
1180
      QUERY_CHECK_CODE(code, lino, _end);
6,132!
1181
    }
1182

1183
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
6,330,422✔
1184
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
6,327,071✔
1185
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
6,327,071✔
1186
    QUERY_CHECK_CODE(code, lino, _end);
6,295,242!
1187
    key.ts = nextWin.skey;
6,295,242✔
1188

1189
    if (pInfo->delKey.ts > key.ts) {
6,295,242✔
1190
      pInfo->delKey = key;
1,549✔
1191
    }
1192
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
6,295,242✔
1193
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
6,295,242✔
1194
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
256,591✔
1195
    } else {
1196
      startPos =
1197
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
6,038,651✔
1198
    }
1199
    if (startPos < 0) {
6,277,742✔
1200
      break;
33,207✔
1201
    }
1202
  }
1203
_end:
33,316✔
1204
  if (code != TSDB_CODE_SUCCESS) {
33,316!
1205
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
1206
  }
1207
  return code;
33,316✔
1208
}
1209

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

1216
  if (pWin1->groupId > pWin2->groupId) {
83,476,997✔
1217
    return 1;
4,393,123✔
1218
  } else if (pWin1->groupId < pWin2->groupId) {
79,083,874✔
1219
    return -1;
3,684,654✔
1220
  }
1221

1222
  if (pWin1->ts > pWin2->ts) {
75,399,220✔
1223
    return 1;
38,023,396✔
1224
  } else if (pWin1->ts < pWin2->ts) {
37,375,824!
1225
    return -1;
37,405,406✔
1226
  }
1227

1228
  return 0;
×
1229
}
1230

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

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

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

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

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

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

1273
void* decodeSTimeWindow(void* buf, STimeWindow* pWin) {
×
1274
  buf = taosDecodeFixedI64(buf, &pWin->skey);
×
1275
  buf = taosDecodeFixedI64(buf, &pWin->ekey);
×
1276
  return buf;
×
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) {
50✔
1295
  int32_t tlen = 0;
50✔
1296
  int32_t size = taosArrayGetSize(pPullInfos);
50✔
1297
  tlen += taosEncodeFixedI32(buf, size);
50✔
1298
  for (int32_t i = 0; i < size; i++) {
50!
1299
    void* pItem = taosArrayGet(pPullInfos, i);
×
1300
    tlen += encodeSPullWindowInfo(buf, pItem);
×
1301
  }
1302
  return tlen;
50✔
1303
}
1304

1305
int32_t decodeSPullWindowInfoArray(void* buf, SArray* pPullInfos, void** ppBuf) {
11✔
1306
  int32_t code = TSDB_CODE_SUCCESS;
11✔
1307
  int32_t lino = 0;
11✔
1308
  int32_t size = 0;
11!
1309
  buf = taosDecodeFixedI32(buf, &size);
11✔
1310
  for (int32_t i = 0; i < size; i++) {
11!
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;
11✔
1320

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

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

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

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

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

1351
  // 3.pPullDataMap
1352
  int32_t size = taosHashGetSize(pInfo->pPullDataMap);
50✔
1353
  tlen += taosEncodeFixedI32(buf, size);
50✔
1354
  pIte = NULL;
50✔
1355
  keyLen = 0;
50✔
1356
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
50!
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);
50✔
1370

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

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

1382
  return tlen;
50✔
1383
}
1384

1385
void doStreamIntervalDecodeOpState(void* buf, int32_t len, SOperatorInfo* pOperator) {
11✔
1386
  int32_t                      code = TSDB_CODE_SUCCESS;
11✔
1387
  int32_t                      lino = 0;
11✔
1388
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
11✔
1389
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
11✔
1390
  if (!pInfo) {
11!
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);
11✔
1397
  void*   pCksum = POINTER_SHIFT(buf, dataLen);
11✔
1398
  if (taosCheckChecksum(buf, dataLen, *(uint32_t*)pCksum) != TSDB_CODE_SUCCESS) {
22!
1399
    code = TSDB_CODE_FAILED;
×
1400
    QUERY_CHECK_CODE(code, lino, _end);
×
1401
  }
1402

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

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

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

1423
  // 3.pPullDataMap
1424
  int32_t size = 0;
11✔
1425
  buf = taosDecodeFixedI32(buf, &size);
11!
1426
  for (int32_t i = 0; i < size; i++) {
11!
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);
11✔
1452
  QUERY_CHECK_CODE(code, lino, _end);
11!
1453

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

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

1463
void doStreamIntervalSaveCheckpoint(SOperatorInfo* pOperator) {
1,086✔
1464
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1,086✔
1465
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
1,086✔
1466
    int32_t len = doStreamIntervalEncodeOpState(NULL, 0, pOperator);
25✔
1467
    void*   buf = taosMemoryCalloc(1, len);
25✔
1468
    if (!buf) {
25!
1469
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_OUT_OF_MEMORY));
×
1470
      return;
×
1471
    }
1472
    void* pBuf = buf;
25✔
1473
    len = doStreamIntervalEncodeOpState(&pBuf, len, pOperator);
25✔
1474
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
25✔
1475
                                          strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), buf, len);
1476
    taosMemoryFree(buf);
25✔
1477
    saveStreamOperatorStateComplete(&pInfo->basic);
25✔
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) {
34,537✔
1504
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
34,537✔
1505
  int32_t                      code = TSDB_CODE_SUCCESS;
34,537✔
1506
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
34,537✔
1507
  uint16_t                     opType = pOperator->operatorType;
34,537✔
1508

1509
  // check if query task is closed or not
1510
  if (isTaskKilled(pTaskInfo)) {
34,537!
1511
    (*ppRes) = NULL;
×
1512
    return code;
×
1513
  }
1514

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

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

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

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

1544
int32_t copyUpdateResult(SSHashObj** ppWinUpdated, SArray* pUpdated, __compar_fn_t compar) {
11,161✔
1545
  int32_t code = TSDB_CODE_SUCCESS;
11,161✔
1546
  int32_t lino = 0;
11,161✔
1547
  void*   pIte = NULL;
11,161✔
1548
  int32_t iter = 0;
11,161✔
1549
  while ((pIte = tSimpleHashIterate(*ppWinUpdated, pIte, &iter)) != NULL) {
482,130✔
1550
    void* tmp = taosArrayPush(pUpdated, pIte);
470,969✔
1551
    if (!tmp) {
470,969!
1552
      code = terrno;
×
1553
      QUERY_CHECK_CODE(code, lino, _end);
×
1554
    }
1555
  }
1556
  taosArraySort(pUpdated, compar);
11,161✔
1557
  tSimpleHashCleanup(*ppWinUpdated);
11,161✔
1558
  *ppWinUpdated = NULL;
11,161✔
1559

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

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

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

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

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

1591
    if (pInfo->recvGetAll) {
4,083✔
1592
      pInfo->recvGetAll = false;
61✔
1593
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
61✔
1594
    }
1595

1596
    if (pInfo->reCkBlock) {
4,083!
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);
4,083✔
1604
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
4,083✔
1605
      clearFunctionContext(&pOperator->exprSupp);
2,401✔
1606
      // semi interval operator clear disk buffer
1607
      clearStreamIntervalOperator(pInfo);
2,401✔
1608
      qDebug("===stream===clear semi operator");
2,401✔
1609
    }
1610
    (*ppRes) = NULL;
4,083✔
1611
    return code;
4,083✔
1612
  } else {
1613
    if (!IS_FINAL_INTERVAL_OP(pOperator)) {
7,751✔
1614
      SSDataBlock* resBlock = NULL;
5,316✔
1615
      code = buildIntervalResult(pOperator, &resBlock);
5,316✔
1616
      QUERY_CHECK_CODE(code, lino, _end);
5,316!
1617
      if (resBlock != NULL) {
5,316!
1618
        (*ppRes) = resBlock;
×
1619
        return code;
×
1620
      }
1621

1622
      if (pInfo->recvRetrive) {
5,316!
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) {
7,751✔
1632
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
6,491✔
1633
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
6,490!
1634
  }
1635
  if (!pInfo->pUpdatedMap) {
7,750✔
1636
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
6,490✔
1637
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
6,491✔
1638
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
6,490!
1639
  }
1640

1641
  while (1) {
21,857✔
1642
    if (isTaskKilled(pTaskInfo)) {
29,607!
1643
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
1644
      (*ppRes) = NULL;
×
1645
      return code;
1,260✔
1646
    }
1647

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

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

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

1664
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
23,553✔
1665
      pInfo->binfo.pRes->info.type = pBlock->info.type;
20,035✔
1666
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
3,518✔
1667
               pBlock->info.type == STREAM_CLEAR) {
3,334✔
1668
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
300✔
1669
      QUERY_CHECK_NULL(delWins, code, lino, _end, terrno);
300!
1670
      SHashObj* finalMap = IS_FINAL_INTERVAL_OP(pOperator) ? pInfo->pFinalPullDataMap : NULL;
300✔
1671
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap, finalMap);
300✔
1672
      QUERY_CHECK_CODE(code, lino, _end);
300!
1673

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

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

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

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

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

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

1752
    if (pInfo->scalarSupp.pExprInfo != NULL) {
20,669!
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);
20,669✔
1758
    QUERY_CHECK_CODE(code, lino, _end);
20,669!
1759

1760
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
20,669✔
1761
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
20,669!
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);
20,669✔
1767
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
20,669✔
1768
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
20,669✔
1769
  }
1770

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

1779
    if (pInfo->destHasPrimaryKey) {
1,880!
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,491✔
1785

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

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

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

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

1809
_end:
1,972✔
1810
  if (code != TSDB_CODE_SUCCESS) {
1,972!
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);
1,972✔
1816
  (*ppRes) = NULL;
1,972✔
1817
  return code;
1,972✔
1818
}
1819

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

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

1837
static TSKEY compareTs(void* pKey) {
18,859,022✔
1838
  SWinKey* pWinKey = (SWinKey*)pKey;
18,859,022✔
1839
  return pWinKey->ts;
18,859,022✔
1840
}
1841

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

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

1856
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
3,587✔
1857
  int32_t size = 0;
3,587✔
1858
  for (int32_t i = 0; i < numOfCols; ++i) {
163,358✔
1859
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
159,771✔
1860
    size = TMAX(size, resSize);
159,771✔
1861
  }
1862
  return size;
3,587✔
1863
}
1864

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

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

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

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

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

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

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

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

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

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

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

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

1969
  qInfo("copy state %p to %p", pTaskInfo->streamInfo.pState, pInfo->pState);
721!
1970

1971
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
721✔
1972

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

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

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

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

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

2000
  code = createSpecialDataBlock(STREAM_RETRIEVE, &pInfo->pPullDataRes);
721✔
2001
  QUERY_CHECK_CODE(code, lino, _error);
721!
2002

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

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

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

2031
  pInfo->dataVersion = 0;
721✔
2032
  pInfo->recvGetAll = false;
721✔
2033
  pInfo->recvPullover = false;
721✔
2034
  pInfo->recvRetrive = false;
721✔
2035

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

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

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

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

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

2089
  *pOptrInfo = pOperator;
721✔
2090
  return TSDB_CODE_SUCCESS;
721✔
2091

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

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

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

2127
  if (pInfo->pChildren != NULL) {
316✔
2128
    int32_t size = taosArrayGetSize(pInfo->pChildren);
15✔
2129
    for (int32_t i = 0; i < size; i++) {
67✔
2130
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
52✔
2131
      destroyOperator(pChild);
52✔
2132
    }
2133
    taosArrayDestroy(pInfo->pChildren);
15✔
2134
  }
2135

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

2143
  taosArrayDestroy(pInfo->historyWins);
316✔
2144
  blockDataDestroy(pInfo->pCheckpointRes);
316✔
2145
  tSimpleHashCleanup(pInfo->pPkDeleted);
316✔
2146

2147
  taosMemoryFreeClear(param);
316!
2148
}
2149

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

2158
  for (int32_t i = 0; i < numOfCols; ++i) {
6,108✔
2159
    pSup->pCtx[i].saveHandle.pBuf = NULL;
5,597✔
2160
  }
2161

2162
  return TSDB_CODE_SUCCESS;
511✔
2163
}
2164

2165
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
546✔
2166
  for (int i = 0; i < nums; i++) {
6,372✔
2167
    pDummy[i].functionId = pCtx[i].functionId;
5,826✔
2168
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
5,826✔
2169
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
5,826✔
2170
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
5,826✔
2171
  }
2172
}
546✔
2173

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

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

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

2211
static TSKEY sesionTs(void* pKey) {
953✔
2212
  SSessionKey* pWinKey = (SSessionKey*)pKey;
953✔
2213
  return pWinKey->win.skey;
953✔
2214
}
2215

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

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

2231
  pSup->stateStore = *pStore;
546✔
2232
  pSup->pSessionAPI = pApi;
546✔
2233

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

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

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

2261
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
546✔
2262
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
546✔
2263
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
546!
2264

2265
  for (int32_t i = 0; i < numOfOutput; ++i) {
6,372✔
2266
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
5,826✔
2267
  }
2268

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

2276
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
2,453✔
2277
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
2,453✔
2278
    return true;
2,016✔
2279
  }
2280
  return false;
437✔
2281
}
2282

2283
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
2,363✔
2284
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
2,363✔
2285
}
2286

2287
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
2,355✔
2288
                         SSessionKey* pKey) {
2289
  pKey->win.skey = startTs;
2,355✔
2290
  pKey->win.ekey = endTs;
2,355✔
2291
  pKey->groupId = groupId;
2,355✔
2292
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
2,355✔
2293
  if (code != TSDB_CODE_SUCCESS) {
2,355✔
2294
    SET_SESSION_WIN_KEY_INVALID(pKey);
655✔
2295
  }
2296
}
2,355✔
2297

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

2300
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
49,563✔
2301
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
49,563!
2302
    return true;
49,580✔
2303
  }
2304
  return false;
×
2305
}
2306

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

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

2322
  if (winCode == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->sessionWin.win)) {
1,480!
2323
    winCode = TSDB_CODE_FAILED;
×
2324
    clearOutputBuf(pAggSup->pState, pCurWin->pStatePos, &pAggSup->pSessionAPI->stateStore);
×
2325
  }
2326

2327
  if (winCode == TSDB_CODE_SUCCESS) {
1,480✔
2328
    pCurWin->isOutput = true;
544✔
2329
    if (pCurWin->pStatePos->needFree) {
544✔
2330
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
76✔
2331
    }
2332
  } else {
2333
    pCurWin->sessionWin.win.skey = startTs;
936✔
2334
    pCurWin->sessionWin.win.ekey = endTs;
936✔
2335
  }
2336
  qDebug("===stream===set session window buff .start:%" PRId64 ",end:%" PRId64 ",groupid:%" PRIu64,
1,480!
2337
         pCurWin->sessionWin.win.skey, pCurWin->sessionWin.win.ekey, pCurWin->sessionWin.groupId);
2338

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

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

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

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

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

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

2379
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
3,959✔
2380
  pAPI->streamStateReleaseBuf(pState, pPos, false);
3,959✔
2381
}
3,959✔
2382

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

2398
void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
2,823✔
2399
  *pHashKey = *pKey;
2,823✔
2400
  pHashKey->win.ekey = pKey->win.skey;
2,823✔
2401
}
2,823✔
2402

2403
void removeSessionDeleteResults(SSHashObj* pHashMap, SArray* pWins) {
4,141✔
2404
  if (tSimpleHashGetSize(pHashMap) == 0) {
4,141✔
2405
    return;
3,619✔
2406
  }
2407
  int32_t size = taosArrayGetSize(pWins);
522✔
2408
  for (int32_t i = 0; i < size; i++) {
1,086✔
2409
    SResultWindowInfo* pWin = taosArrayGet(pWins, i);
564✔
2410
    if (!pWin) continue;
564!
2411
    SSessionKey key = {0};
564✔
2412
    getSessionHashKey(&pWin->sessionWin, &key);
564✔
2413
    int32_t tmpRes = tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
564✔
2414
    qTrace("%s at line %d res:%d", __func__, __LINE__, tmpRes);
564!
2415
  }
2416
}
2417

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

2437
int32_t updateSessionWindowInfo(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo, TSKEY* pStartTs,
1,453✔
2438
                                TSKEY* pEndTs, uint64_t groupId, int32_t rows, int32_t start, int64_t gap,
2439
                                SSHashObj* pResultRows, SSHashObj* pStUpdated, SSHashObj* pStDeleted,
2440
                                int32_t* pWinRos) {
2441
  int32_t code = TSDB_CODE_SUCCESS;
1,453✔
2442
  int32_t lino = 0;
1,453✔
2443
  for (int32_t i = start; i < rows; ++i) {
3,448✔
2444
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
2,036!
2445
      (*pWinRos) = i - start;
41✔
2446
      goto _end;
41✔
2447
    }
2448
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
1,995✔
2449
      if (pStDeleted && pWinInfo->isOutput) {
17!
2450
        code = saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
12✔
2451
        QUERY_CHECK_CODE(code, lino, _end);
12!
2452
      }
2453
      removeSessionResult(pAggSup, pStUpdated, pResultRows, &pWinInfo->sessionWin);
17✔
2454
      pWinInfo->sessionWin.win.skey = pStartTs[i];
17✔
2455
    }
2456
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
1,995✔
2457
    if (pEndTs) {
1,995!
2458
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
1,995✔
2459
    }
2460
    memcpy(pWinInfo->pStatePos->pKey, &pWinInfo->sessionWin, sizeof(SSessionKey));
1,995✔
2461
  }
2462
  (*pWinRos) = rows - start;
1,412✔
2463

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

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

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

2489
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
3,245✔
2490
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
3,245✔
2491

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

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

2507
void setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
4,833✔
2508
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
4,833✔
2509
  if (pVal) {
4,833✔
2510
    SResultWindowInfo* pWin = pVal;
173✔
2511
    pWinInfo->isOutput = pWin->isOutput;
173✔
2512
  }
2513
}
4,833✔
2514

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2663
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,420✔
2664
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
1,420✔
2665
  SColumnInfoData* pEndTsCol = NULL;
1,420✔
2666
  if (hasEndTs) {
1,420✔
2667
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
198✔
2668
  } else {
2669
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
1,222✔
2670
  }
2671

2672
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
1,420✔
2673

2674
  void*            pPkVal = NULL;
1,420✔
2675
  int32_t          pkLen = 0;
1,420✔
2676
  SColumnInfoData* pPkColDataInfo = NULL;
1,420✔
2677
  if (hasSrcPrimaryKeyCol(&pInfo->basic)) {
1,420✔
2678
    pPkColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->basic.primaryPkIndex);
99✔
2679
  }
2680

2681
  for (int32_t i = 0; i < rows;) {
2,879✔
2682
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData) {
1,461!
2683
      pPkVal = colDataGetData(pPkColDataInfo, i);
×
2684
      pkLen = colDataGetRowLength(pPkColDataInfo, i);
×
2685
    }
2686
    if (!IS_FINAL_SESSION_OP(pOperator) && pInfo->ignoreExpiredData &&
1,538✔
2687
        checkExpiredData(&pInfo->streamAggSup.stateStore, pInfo->streamAggSup.pUpdateInfo, &pInfo->twAggSup,
77✔
2688
                         pSDataBlock->info.id.uid, endTsCols[i], pPkVal, pkLen)) {
77✔
2689
      i++;
8✔
2690
      continue;
8✔
2691
    }
2692
    SResultWindowInfo winInfo = {0};
1,453✔
2693
    code = setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo);
1,453✔
2694
    QUERY_CHECK_CODE(code, lino, _end);
1,455!
2695

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

2705
    int64_t winDelta = 0;
1,453✔
2706
    if (addGap) {
1,453✔
2707
      winDelta = pAggSup->gap;
1,192✔
2708
    }
2709
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
1,453✔
2710
                              pOperator, winDelta);
2711
    QUERY_CHECK_CODE(code, lino, _end);
1,453!
2712

2713
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL);
1,453✔
2714
    QUERY_CHECK_CODE(code, lino, _end);
1,453✔
2715

2716
    code = saveSessionOutputBuf(pAggSup, &winInfo);
1,451✔
2717
    QUERY_CHECK_CODE(code, lino, _end);
1,451!
2718

2719
    if (pInfo->destHasPrimaryKey && winInfo.isOutput && IS_NORMAL_SESSION_OP(pOperator)) {
1,451!
2720
      code = saveDeleteRes(pInfo->pPkDeleted, winInfo.sessionWin);
×
2721
      QUERY_CHECK_CODE(code, lino, _end);
×
2722
    }
2723
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
1,451✔
2724
      code = saveResult(winInfo, pStUpdated);
1,015✔
2725
      QUERY_CHECK_CODE(code, lino, _end);
1,015!
2726
    }
2727
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,451✔
2728
      winInfo.pStatePos->beUpdated = true;
326✔
2729
      SSessionKey key = {0};
326✔
2730
      getSessionHashKey(&winInfo.sessionWin, &key);
326✔
2731
      code = tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
326✔
2732
      QUERY_CHECK_CODE(code, lino, _end);
326!
2733
    }
2734

2735
    i += winRows;
1,451✔
2736
  }
2737

2738
_end:
1,418✔
2739
  if (code != TSDB_CODE_SUCCESS) {
1,420✔
2740
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
2!
2741
  }
2742
}
1,420✔
2743

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

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

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

2781
  if (pWin1->groupId > pWin2->groupId) {
716✔
2782
    return 1;
127✔
2783
  } else if (pWin1->groupId < pWin2->groupId) {
589✔
2784
    return -1;
136✔
2785
  }
2786

2787
  if (pWin1->win.skey > pWin2->win.skey) {
453✔
2788
    return 1;
257✔
2789
  } else if (pWin1->win.skey < pWin2->win.skey) {
196!
2790
    return -1;
196✔
2791
  }
2792

2793
  return 0;
×
2794
}
2795

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

2802
  blockDataCleanup(pBlock);
6,262✔
2803
  int32_t size = tSimpleHashGetSize(pStDeleted);
6,262✔
2804
  if (size == 0) {
6,262✔
2805
    return;
6,020✔
2806
  }
2807
  code = blockDataEnsureCapacity(pBlock, size);
242✔
2808
  QUERY_CHECK_CODE(code, lino, _end);
242!
2809

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

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

2824
    SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
278✔
2825
    colDataSetNULL(pUidCol, pBlock->info.rows);
278!
2826

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

2831
    SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
278✔
2832
    colDataSetNULL(pCalStCol, pBlock->info.rows);
278!
2833

2834
    SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
278✔
2835
    colDataSetNULL(pCalEdCol, pBlock->info.rows);
278!
2836

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

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

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

2860
_end:
242✔
2861
  if ((*Ite) == NULL) {
242!
2862
    tSimpleHashClear(pStDeleted);
242✔
2863
  }
2864

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

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

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

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

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

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

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

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

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

2931
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL);
29✔
2932
          QUERY_CHECK_CODE(code, lino, _end);
29!
2933

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

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

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

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

2982
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
2,396✔
2983
  int32_t code = TSDB_CODE_SUCCESS;
2,396✔
2984
  int32_t lino = 0;
2,396✔
2985

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

3001
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
100✔
3002
  int32_t code = TSDB_CODE_SUCCESS;
100✔
3003
  int32_t lino = 0;
100✔
3004
  void*   pIte = NULL;
100✔
3005
  int32_t iter = 0;
100✔
3006
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
149✔
3007
    SResultWindowInfo* pWinInfo = pIte;
49✔
3008
    if (!pWinInfo->pStatePos->beUpdated) {
49✔
3009
      continue;
3✔
3010
    }
3011
    pWinInfo->pStatePos->beUpdated = false;
46✔
3012
    code = saveResult(*pWinInfo, pStUpdated);
46✔
3013
    QUERY_CHECK_CODE(code, lino, _end);
46!
3014
  }
3015

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

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

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

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

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

3062
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
1,737✔
3063

3064
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
3,778✔
3065
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
2,201✔
3066
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
2,201✔
3067
    SResultRow*        pRow = NULL;
2,201✔
3068
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
2,201✔
3069

3070
    if (pBlock->info.id.groupId == 0) {
2,201✔
3071
      pBlock->info.id.groupId = pKey->groupId;
1,914✔
3072

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

3079
      if (winCode != TSDB_CODE_SUCCESS) {
1,914✔
3080
        pBlock->info.parTbName[0] = 0;
835✔
3081
      } else {
3082
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
1,079✔
3083
      }
3084
      pAPI->stateStore.streamStateFreeVal(tbname);
1,914✔
3085
    } else {
3086
      // current value belongs to different group, it can't be packed into one datablock
3087
      if (pBlock->info.id.groupId != pKey->groupId) {
287✔
3088
        break;
160✔
3089
      }
3090
    }
3091

3092
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
2,041✔
3093
    QUERY_CHECK_CODE(code, lino, _end);
2,041!
3094

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

3102
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
2,041!
3103
      break;
×
3104
    }
3105

3106
    pGroupResInfo->index += 1;
2,041✔
3107

3108
    for (int32_t j = 0; j < numOfExprs; ++j) {
29,156✔
3109
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
27,115✔
3110

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

3132
    pBlock->info.dataLoad = 1;
2,041✔
3133
    pBlock->info.rows += pRow->numOfRows;
2,041✔
3134
  }
3135
  code = blockDataUpdateTsWindow(pBlock, 0);
1,737✔
3136
  QUERY_CHECK_CODE(code, lino, _end);
1,737!
3137

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

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

3152
  blockDataCleanup(pBlock);
6,020✔
3153
  if (!hasRemainResults(pGroupResInfo)) {
6,020✔
3154
    cleanupGroupResInfo(pGroupResInfo);
4,283✔
3155
    goto _end;
4,283✔
3156
  }
3157

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

3163
  if (pBlock->info.rows == 0) {
1,737!
3164
    cleanupGroupResInfo(pGroupResInfo);
×
3165
  }
3166

3167
_end:
1,737✔
3168
  if (code != TSDB_CODE_SUCCESS) {
6,020!
3169
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
3170
  }
3171
}
6,020✔
3172

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

3186
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
3,586✔
3187
  if (pBInfo->pRes->info.rows > 0) {
3,586✔
3188
    printDataBlock(pBInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
894✔
3189
    (*ppRes) = pBInfo->pRes;
894✔
3190
    return code;
894✔
3191
  }
3192
  (*ppRes) = NULL;
2,692✔
3193
  return code;
2,692✔
3194
}
3195

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

3211
  if (pSeKey->groupId == 0) {
40✔
3212
    goto _end;
9✔
3213
  }
3214
  uint64_t preGpId = pSeKey->groupId;
31✔
3215
  for (int32_t i = size - 2; i >= 0; i--) {
117✔
3216
    pWinInfo = taosArrayGet(pAllWins, i);
86✔
3217
    pSeKey = &pWinInfo->sessionWin;
86✔
3218
    if (preGpId != pSeKey->groupId) {
86✔
3219
      void* tmp = taosArrayPush(pMaxWins, pSeKey);
67✔
3220
      if (!tmp) {
67!
3221
        code = terrno;
×
3222
        QUERY_CHECK_CODE(code, lino, _end);
×
3223
      }
3224
      preGpId = pSeKey->groupId;
67✔
3225
    }
3226
  }
3227

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

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

3242
void* decodeSSessionKey(void* buf, SSessionKey* key) {
×
3243
  buf = decodeSTimeWindow(buf, &key->win);
×
3244
  buf = taosDecodeFixedU64(buf, &key->groupId);
×
3245
  return buf;
×
3246
}
3247

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

3255
void* decodeSResultWindowInfo(void* buf, SResultWindowInfo* key, int32_t outLen) {
×
3256
  buf = taosDecodeFixedBool(buf, &key->isOutput);
×
3257
  buf = decodeSSessionKey(buf, &key->sessionWin);
×
3258
  return buf;
×
3259
}
3260

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

3267
  void* pData = (buf == NULL) ? NULL : *buf;
×
3268

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

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

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

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

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

3306
  return tlen;
×
3307
}
3308

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

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

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

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

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

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

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

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

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

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

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

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

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

3445
    if (pInfo->recvGetAll) {
778✔
3446
      pInfo->recvGetAll = false;
43✔
3447
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
43✔
3448
    }
3449

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

3457
    setStreamOperatorCompleted(pOperator);
778✔
3458
    (*ppRes) = NULL;
778✔
3459
    return code;
778✔
3460
  }
3461

3462
  SOperatorInfo* downstream = pOperator->pDownstream[0];
2,642✔
3463
  if (!pInfo->pUpdated) {
2,642✔
3464
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
2,396✔
3465
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
2,396!
3466
  }
3467
  if (!pInfo->pStUpdated) {
2,642✔
3468
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,372✔
3469
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
2,372✔
3470
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
2,372!
3471
  }
3472
  while (1) {
1,552✔
3473
    SSDataBlock* pBlock = NULL;
4,194✔
3474
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
4,194✔
3475
    QUERY_CHECK_CODE(code, lino, _end);
4,194!
3476

3477
    if (pBlock == NULL) {
4,194✔
3478
      break;
2,396✔
3479
    }
3480
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
1,798✔
3481
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
1,798✔
3482

3483
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
1,798✔
3484
        pBlock->info.type == STREAM_CLEAR) {
1,657✔
3485
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
241✔
3486
      QUERY_CHECK_NULL(pWins, code, lino, _end, terrno);
241!
3487
      // gap must be 0
3488
      code = doDeleteTimeWindows(pAggSup, pBlock, pWins);
241✔
3489
      QUERY_CHECK_CODE(code, lino, _end);
241!
3490

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

3500
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
30✔
3501
        QUERY_CHECK_CODE(code, lino, _end);
30!
3502
      }
3503
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
241✔
3504
      QUERY_CHECK_CODE(code, lino, _end);
241!
3505

3506
      if (pInfo->destHasPrimaryKey && IS_NORMAL_SESSION_OP(pOperator)) {
241!
3507
        code = copyDeleteWindowInfo(pWins, pInfo->pPkDeleted);
×
3508
        QUERY_CHECK_CODE(code, lino, _end);
×
3509
      }
3510
      taosArrayDestroy(pWins);
241✔
3511
      continue;
378✔
3512
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,557✔
3513
      pInfo->recvGetAll = true;
89✔
3514
      code = getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
89✔
3515
      QUERY_CHECK_CODE(code, lino, _end);
89!
3516
      continue;
89✔
3517
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
1,468✔
3518
      (*ppRes) = pBlock;
246✔
3519
      return code;
246✔
3520
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,222✔
3521
      pAggSup->stateStore.streamStateCommit(pAggSup->pState);
48✔
3522
      doStreamSessionSaveCheckpoint(pOperator);
48✔
3523
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
48✔
3524
      QUERY_CHECK_CODE(code, lino, _end);
48!
3525

3526
      continue;
48✔
3527
    } else {
3528
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,174!
3529
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3530
        QUERY_CHECK_CODE(code, lino, _end);
×
3531
      }
3532
    }
3533

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

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

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

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

3576
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
2,396✔
3577
  QUERY_CHECK_CODE(code, lino, _end);
2,396!
3578

3579
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
2,396✔
3580
  QUERY_CHECK_CODE(code, lino, _end);
2,396!
3581

3582
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
2,396✔
3583
  QUERY_CHECK_CODE(code, lino, _end);
2,396!
3584

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

3601
  SSDataBlock* opRes = NULL;
2,396✔
3602
  code = buildSessionResult(pOperator, &opRes);
2,396✔
3603
  QUERY_CHECK_CODE(code, lino, _end);
2,396!
3604
  if (opRes) {
2,396✔
3605
    (*ppRes) = opRes;
778✔
3606
    return code;
778✔
3607
  }
3608

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

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

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

3646
void resetWinRange(STimeWindow* winRange) {
80✔
3647
  winRange->skey = INT64_MIN;
80✔
3648
  winRange->ekey = INT64_MAX;
80✔
3649
}
80✔
3650

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

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

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

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

3680
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
113✔
3681
    reloadAggSupFromDownStream(downstream->pDownstream[0], pAggSup);
32✔
3682
    return;
32✔
3683
  }
3684

3685
  SStreamScanInfo* pScanInfo = downstream->info;
81✔
3686
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
81✔
3687
}
3688

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

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

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

3722
  SOperatorInfo* downstream = pOperator->pDownstream[0];
×
3723
  if (downstream->fpSet.reloadStreamStateFn) {
×
3724
    downstream->fpSet.reloadStreamStateFn(downstream);
×
3725
  }
3726
  reloadAggSupFromDownStream(downstream, &pInfo->streamAggSup);
×
3727

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

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

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

3747
  QUERY_CHECK_CODE(code, lino, _end);
48!
3748

3749
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
48✔
3750
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
48✔
3751

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

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

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

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

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

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

3807
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
316✔
3808
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
3809
  QRY_PARAM_CHECK(pOptrInfo);
316!
3810

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

3822
  pOperator->pTaskInfo = pTaskInfo;
315✔
3823

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

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

3838
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
315✔
3839
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
316!
3840
  pInfo->binfo.pRes = pResBlock;
316✔
3841

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

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

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

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

3866
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
316✔
3867
  QUERY_CHECK_CODE(code, lino, _error);
316!
3868

3869
  if (pSessionNode->window.pTsEnd) {
316!
3870
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
316✔
3871
  }
3872

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

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

3896
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
316✔
3897
  QUERY_CHECK_CODE(code, lino, _error);
316!
3898

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

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

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

3933
    code = appendDownstream(pOperator, &downstream, 1);
264✔
3934
    QUERY_CHECK_CODE(code, lino, _error);
264!
3935
  }
3936

3937
  *pOptrInfo = pOperator;
316✔
3938
  return TSDB_CODE_SUCCESS;
316✔
3939

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

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

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

3968
  removeSessionResults(pAggSup, pMapUpdate, pWins);
309✔
3969
  code = copyDeleteWindowInfo(pWins, pMapDelete);
309✔
3970
  QUERY_CHECK_CODE(code, lino, _end);
309!
3971

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

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

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

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

4001
  {
4002
    SSDataBlock* opRes = NULL;
270✔
4003
    code = buildSessionResult(pOperator, &opRes);
270✔
4004
    QUERY_CHECK_CODE(code, lino, _end);
270!
4005
    if (opRes) {
270✔
4006
      (*ppRes) = opRes;
18✔
4007
      return code;
99✔
4008
    }
4009

4010
    if (pInfo->clearState) {
252✔
4011
      clearFunctionContext(&pOperator->exprSupp);
30✔
4012
      // semi session operator clear disk buffer
4013
      clearStreamSessionOperator(pInfo);
30✔
4014
    }
4015

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

4032
  SOperatorInfo* downstream = pOperator->pDownstream[0];
171✔
4033
  if (!pInfo->pUpdated) {
171✔
4034
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
155✔
4035
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
155!
4036
  }
4037
  if (!pInfo->pStUpdated) {
171✔
4038
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
155✔
4039
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
155✔
4040
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
155!
4041
  }
4042
  while (1) {
147✔
4043
    SSDataBlock* pBlock = NULL;
318✔
4044
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
318✔
4045
    QUERY_CHECK_CODE(code, lino, _end);
318!
4046

4047
    if (pBlock == NULL) {
318✔
4048
      pOperator->status = OP_RES_TO_RETURN;
125✔
4049
      break;
125✔
4050
    }
4051
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
193✔
4052
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
193✔
4053

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

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

4091
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
155✔
4092
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
155✔
4093

4094
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
155✔
4095
  QUERY_CHECK_CODE(code, lino, _end);
155!
4096

4097
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
155✔
4098

4099
  if (pInfo->isHistoryOp) {
155!
4100
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
×
4101
    QUERY_CHECK_CODE(code, lino, _end);
×
4102
  }
4103

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

4109
  SSDataBlock* opRes = NULL;
155✔
4110
  code = buildSessionResult(pOperator, &opRes);
155✔
4111
  QUERY_CHECK_CODE(code, lino, _end);
155!
4112
  if (opRes) {
155✔
4113
    (*ppRes) = opRes;
111✔
4114
    return code;
111✔
4115
  }
4116

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

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

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

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

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

4152
  SStorageAPI*                   pAPI = &pTaskInfo->storageAPI;
119✔
4153
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
119✔
4154
  pOperator->operatorType = pPhyNode->type;
119✔
4155
  pInfo->pOperator = pOperator;
119✔
4156

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

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

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

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

4198
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
119✔
4199
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
104✔
4200
  }
4201

4202
  *pOptrInfo = pOperator;
119✔
4203
  return code;
119✔
4204

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

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

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

4251
  taosArrayDestroy(pInfo->historyWins);
156✔
4252
  blockDataDestroy(pInfo->pCheckpointRes);
156✔
4253
  tSimpleHashCleanup(pInfo->pPkDeleted);
156✔
4254

4255
  taosMemoryFreeClear(param);
156!
4256
}
4257

4258
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
1,826✔
4259
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
1,826✔
4260
    return true;
612✔
4261
  }
4262
  return false;
1,214✔
4263
}
4264

4265
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
3,008✔
4266
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
3,008!
4267
}
4268

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

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

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

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

4310
  qDebug("===stream===get state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
55!
4311
         pCurWin->winInfo.sessionWin.win.ekey);
4312

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

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

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

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

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

4378
  if (winCode == TSDB_CODE_SUCCESS) {
1,570✔
4379
    pCurWin->winInfo.isOutput = true;
990✔
4380
    if (pCurWin->winInfo.pStatePos->needFree) {
990✔
4381
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
5✔
4382
    }
4383
  } else if (pKeyData) {
580!
4384
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
580!
4385
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
4✔
4386
    } else {
4387
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
576✔
4388
    }
4389
  }
4390

4391
  qDebug("===stream===set state cur win buff. skey:%" PRId64 ", endkey:%" PRId64, pCurWin->winInfo.sessionWin.win.skey,
1,570!
4392
         pCurWin->winInfo.sessionWin.win.ekey);
4393

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

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

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

4460
_end:
1,570✔
4461
  if (code != TSDB_CODE_SUCCESS) {
1,570!
4462
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4463
  }
4464
  return code;
1,570✔
4465
}
4466

4467
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
1,547✔
4468
                                 SSHashObj* pStDeleted) {
4469
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
1,547✔
4470
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;
1,547✔
4471

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

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

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

4499
  int32_t rows = pSDataBlock->info.rows;
1,547✔
4500
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
1,547✔
4501
  QUERY_CHECK_CODE(code, lino, _end);
1,547!
4502

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

4519
    releaseOutputBuf(pAggSup->pState, nextWin.winInfo.pStatePos, &pAPI->stateStore);
1,570✔
4520

4521
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
1,570✔
4522
    code = updateStateWindowInfo(pAggSup, &curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
1,570✔
4523
                                 pAggSup->pResultRows, pSeUpdated, pStDeleted, &winRows);
4524
    QUERY_CHECK_CODE(code, lino, _end);
1,570!
4525

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

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

4539
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
1,561✔
4540
                              pOperator, 0);
4541
    QUERY_CHECK_CODE(code, lino, _end);
1,561!
4542

4543
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
1,561✔
4544
    QUERY_CHECK_CODE(code, lino, _end);
1,561!
4545

4546
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
1,561!
4547
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
×
4548
      QUERY_CHECK_CODE(code, lino, _end);
×
4549
    }
4550

4551
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,561✔
4552
      code = saveResult(curWin.winInfo, pSeUpdated);
1,380✔
4553
      QUERY_CHECK_CODE(code, lino, _end);
1,380!
4554
    }
4555

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

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

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

4578
  void* pData = (buf == NULL) ? NULL : *buf;
2✔
4579

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

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

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

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

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

4617
  return tlen;
2✔
4618
}
4619

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

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

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

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

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

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

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

4675
  if (ppBuf) {
×
4676
    (*ppBuf) = buf;
×
4677
  }
4678

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

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

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

4710
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
2,228✔
4711
  if (pInfo->pDelRes->info.rows > 0) {
2,228✔
4712
    printDataBlock(pInfo->pDelRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
105✔
4713
    (*ppRes) = pInfo->pDelRes;
105✔
4714
    return code;
105✔
4715
  }
4716

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

4727
static int32_t doStreamStateAggNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
2,408✔
4728
  if (pOperator->status == OP_EXEC_DONE) {
2,408!
4729
    (*ppRes) = NULL;
×
4730
    return TSDB_CODE_SUCCESS;
×
4731
  }
4732

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

4749
    if (pInfo->recvGetAll) {
673✔
4750
      pInfo->recvGetAll = false;
2✔
4751
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
2✔
4752
    }
4753

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

4761
    setStreamOperatorCompleted(pOperator);
673✔
4762
    (*ppRes) = NULL;
673✔
4763
    return code;
673✔
4764
  }
4765

4766
  SOperatorInfo* downstream = pOperator->pDownstream[0];
1,570✔
4767
  if (!pInfo->pUpdated) {
1,570✔
4768
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
1,390✔
4769
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
1,390!
4770
  }
4771
  if (!pInfo->pSeUpdated) {
1,570✔
4772
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
1,375✔
4773
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
1,375✔
4774
    QUERY_CHECK_NULL(pInfo->pSeUpdated, code, lino, _end, terrno);
1,375!
4775
  }
4776
  while (1) {
1,858✔
4777
    SSDataBlock* pBlock = NULL;
3,428✔
4778
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
3,428✔
4779
    QUERY_CHECK_CODE(code, lino, _end);
3,428!
4780

4781
    if (pBlock == NULL) {
3,428✔
4782
      break;
1,390✔
4783
    }
4784
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
2,038✔
4785
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
2,038✔
4786

4787
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
2,038✔
4788
        pBlock->info.type == STREAM_CLEAR) {
1,795✔
4789
      bool add = pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator);
267!
4790
      code = deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted,
267✔
4791
                                   pInfo->pPkDeleted, add);
4792
      QUERY_CHECK_CODE(code, lino, _end);
267!
4793
      continue;
311✔
4794
    } else if (pBlock->info.type == STREAM_GET_ALL) {
1,771✔
4795
      pInfo->recvGetAll = true;
9✔
4796
      code = getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
9✔
4797
      QUERY_CHECK_CODE(code, lino, _end);
9!
4798
      continue;
9✔
4799
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
1,762✔
4800
      (*ppRes) = pBlock;
180✔
4801
      return code;
180✔
4802
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
1,582✔
4803
      pInfo->streamAggSup.stateStore.streamStateCommit(pInfo->streamAggSup.pState);
35✔
4804
      doStreamStateSaveCheckpoint(pOperator);
35✔
4805
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
35✔
4806
      QUERY_CHECK_CODE(code, lino, _end);
35!
4807

4808
      continue;
35✔
4809
    } else {
4810
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
1,547!
4811
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4812
        QUERY_CHECK_CODE(code, lino, _end);
×
4813
      }
4814
    }
4815

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

4830
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
1,390✔
4831
  QUERY_CHECK_CODE(code, lino, _end);
1,390!
4832

4833
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
1,390✔
4834
  QUERY_CHECK_CODE(code, lino, _end);
1,390!
4835

4836
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
1,390✔
4837

4838
  if (pInfo->isHistoryOp) {
1,390✔
4839
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
31✔
4840
    QUERY_CHECK_CODE(code, lino, _end);
31!
4841
  }
4842
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
1,390!
4843
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
×
4844
    QUERY_CHECK_CODE(code, lino, _end);
×
4845
  }
4846

4847
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
1,390✔
4848
  pInfo->pUpdated = NULL;
1,390✔
4849
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
1,390✔
4850
  QUERY_CHECK_CODE(code, lino, _end);
1,390!
4851

4852
  SSDataBlock* resBlock = NULL;
1,390✔
4853
  code = buildStateResult(pOperator, &resBlock);
1,390✔
4854
  QUERY_CHECK_CODE(code, lino, _end);
1,390!
4855
  if (resBlock != NULL) {
1,390✔
4856
    (*ppRes) = resBlock;
673✔
4857
    return code;
673✔
4858
  }
4859

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

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

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

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

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

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

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

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

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

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

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

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

4976
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
55!
4977
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
55✔
4978
      QUERY_CHECK_CODE(code, lino, _end);
55!
4979
    }
4980
  }
4981
  taosMemoryFreeClear(pBuf);
31!
4982

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

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

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

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

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

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

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

5032
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
156✔
5033
  QUERY_CHECK_CODE(code, lino, _error);
156!
5034

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

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

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

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

5063
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
156✔
5064
  QUERY_CHECK_CODE(code, lino, _error);
156!
5065

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

5078
  if (pHandle) {
156!
5079
    pInfo->isHistoryOp = pHandle->fillHistory;
156✔
5080
  }
5081

5082
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
156✔
5083
  QUERY_CHECK_CODE(code, lino, _error);
156!
5084

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

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

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

5112
  code = appendDownstream(pOperator, &downstream, 1);
156✔
5113
  QUERY_CHECK_CODE(code, lino, _error);
156!
5114

5115
  *pOptrInfo = pOperator;
156✔
5116
  return TSDB_CODE_SUCCESS;
156✔
5117

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

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

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

5146
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
20,829✔
5147

5148
  if (pOperator->status == OP_EXEC_DONE) {
20,829✔
5149
    (*ppRes) = NULL;
669✔
5150
    return code;
669✔
5151
  }
5152

5153
  if (pOperator->status == OP_RES_TO_RETURN) {
20,160✔
5154
    SSDataBlock* resBlock = NULL;
5,938✔
5155
    code = buildIntervalResult(pOperator, &resBlock);
5,938✔
5156
    QUERY_CHECK_CODE(code, lino, _end);
5,938!
5157
    if (resBlock != NULL) {
5,938✔
5158
      (*ppRes) = resBlock;
2,384✔
5159
      return code;
5,938✔
5160
    }
5161

5162
    if (pInfo->recvGetAll) {
3,554✔
5163
      pInfo->recvGetAll = false;
151✔
5164
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
151✔
5165
    }
5166

5167
    if (pInfo->reCkBlock) {
3,554✔
5168
      pInfo->reCkBlock = false;
77✔
5169
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
77✔
5170
      (*ppRes) = pInfo->pCheckpointRes;
77✔
5171
      return code;
77✔
5172
    }
5173

5174
    setStreamOperatorCompleted(pOperator);
3,477✔
5175
    (*ppRes) = NULL;
3,477✔
5176
    return code;
3,477✔
5177
  }
5178

5179
  SOperatorInfo* downstream = pOperator->pDownstream[0];
14,222✔
5180

5181
  if (!pInfo->pUpdated) {
14,222✔
5182
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
11,887✔
5183
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
11,888!
5184
  }
5185

5186
  if (!pInfo->pUpdatedMap) {
14,223✔
5187
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
11,888✔
5188
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
11,888✔
5189
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
11,888!
5190
  }
5191

5192
  while (1) {
15,608✔
5193
    SSDataBlock* pBlock = NULL;
29,831✔
5194
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
29,831✔
5195
    QUERY_CHECK_CODE(code, lino, _end);
29,831!
5196

5197
    if (pBlock == NULL) {
29,831✔
5198
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
11,888✔
5199
             pInfo->numOfDatapack);
5200
      pInfo->numOfDatapack = 0;
11,888✔
5201
      break;
11,888✔
5202
    }
5203

5204
    pInfo->numOfDatapack++;
17,943✔
5205
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
17,943✔
5206
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
17,943✔
5207

5208
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
17,943✔
5209
        pBlock->info.type == STREAM_CLEAR) {
17,641✔
5210
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
1,137✔
5211
      QUERY_CHECK_CODE(code, lino, _end);
1,137!
5212
      continue;
2,961✔
5213
    } else if (pBlock->info.type == STREAM_GET_ALL) {
16,806✔
5214
      pInfo->recvGetAll = true;
859✔
5215
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
859✔
5216
      QUERY_CHECK_CODE(code, lino, _end);
859!
5217
      continue;
859✔
5218
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE || pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
15,947✔
5219
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
2,335✔
5220
      (*ppRes) = pBlock;
2,335✔
5221
      return code;
2,335✔
5222
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
13,612✔
5223
      pAPI->stateStore.streamStateCommit(pInfo->pState);
965✔
5224
      doStreamIntervalSaveCheckpoint(pOperator);
965✔
5225
      pInfo->reCkBlock = true;
965✔
5226
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
965✔
5227
      QUERY_CHECK_CODE(code, lino, _end);
965!
5228

5229
      continue;
965✔
5230
    } else {
5231
      if (pBlock->info.type != STREAM_NORMAL && pBlock->info.type != STREAM_INVALID) {
12,647!
5232
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5233
        QUERY_CHECK_CODE(code, lino, _end);
×
5234
      }
5235
    }
5236

5237
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
12,647✔
5238
      // set input version
5239
      pTaskInfo->version = pBlock->info.version;
7,394✔
5240
    }
5241

5242
    if (pInfo->scalarSupp.pExprInfo != NULL) {
12,647✔
5243
      SExprSupp* pExprSup = &pInfo->scalarSupp;
13✔
5244
      code = projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
13✔
5245
      QUERY_CHECK_CODE(code, lino, _end);
13!
5246
    }
5247

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

5259
    code = doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap, pInfo->pDeletedMap);
12,647✔
5260
    if (code == TSDB_CODE_STREAM_INTERNAL_ERROR) {
12,647!
5261
      pOperator->status = OP_RES_TO_RETURN;
×
5262
      code = TSDB_CODE_SUCCESS;
×
5263
      break;
×
5264
    }
5265
    QUERY_CHECK_CODE(code, lino, _end);
12,647!
5266
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
12,647✔
5267
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
12,647✔
5268
  }
5269
  pOperator->status = OP_RES_TO_RETURN;
11,888✔
5270
  if (!pInfo->destHasPrimaryKey) {
11,888!
5271
    removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
11,888✔
5272
  }
5273
  code = closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
11,888✔
5274
                                   pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5275
  QUERY_CHECK_CODE(code, lino, _end);
11,888!
5276

5277
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
11,888!
5278
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
×
5279
    QUERY_CHECK_CODE(code, lino, _end);
×
5280
  }
5281

5282
  void*   pIte = NULL;
11,888✔
5283
  int32_t iter = 0;
11,888✔
5284
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5,814,986✔
5285
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
5,803,098✔
5286
    if (!tmp) {
5,803,098!
5287
      code = terrno;
×
5288
      QUERY_CHECK_CODE(code, lino, _end);
×
5289
    }
5290
  }
5291
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
11,888✔
5292

5293
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
11,888✔
5294
  pInfo->pUpdated = NULL;
11,888✔
5295
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
11,888✔
5296
  QUERY_CHECK_CODE(code, lino, _end);
11,888!
5297

5298
  tSimpleHashCleanup(pInfo->pUpdatedMap);
11,888✔
5299
  pInfo->pUpdatedMap = NULL;
11,888✔
5300

5301
  code = buildIntervalResult(pOperator, ppRes);
11,888✔
5302
  QUERY_CHECK_CODE(code, lino, _end);
11,888!
5303

5304
  return code;
11,888✔
5305

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

5317
static int32_t createStreamSingleIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
2,320✔
5318
                                                      SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5319
  QRY_PARAM_CHECK(pOptrInfo);
2,320!
5320

5321
  int32_t code = TSDB_CODE_SUCCESS;
2,320✔
5322
  int32_t lino = 0;
2,320✔
5323
  int32_t numOfCols = 0;
2,320✔
5324

5325
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
2,320✔
5326
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
2,320✔
5327
  if (pInfo == NULL || pOperator == NULL) {
2,320!
5328
    code = terrno;
×
5329
    QUERY_CHECK_CODE(code, lino, _error);
×
5330
  }
5331

5332
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
2,320✔
5333

5334
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
2,320✔
5335
  QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
2,320!
5336
  initBasicInfo(&pInfo->binfo, pResBlock);
2,320✔
5337

5338
  pInfo->interval = (SInterval){
2,320✔
5339
      .interval = pIntervalPhyNode->interval,
2,320✔
5340
      .sliding = pIntervalPhyNode->sliding,
2,320✔
5341
      .intervalUnit = pIntervalPhyNode->intervalUnit,
2,320✔
5342
      .slidingUnit = pIntervalPhyNode->slidingUnit,
2,320✔
5343
      .offset = pIntervalPhyNode->offset,
2,320✔
5344
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
2,320✔
5345
  };
5346

5347
  pInfo->twAggSup =
2,320✔
5348
      (STimeWindowAggSupp){.waterMark = pIntervalPhyNode->window.watermark,
2,320✔
5349
                           .calTrigger = pIntervalPhyNode->window.triggerType,
2,320✔
5350
                           .maxTs = INT64_MIN,
5351
                           .minTs = INT64_MAX,
5352
                           .deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
2,320✔
5353

5354
  pOperator->pTaskInfo = pTaskInfo;
2,320✔
5355
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
2,320✔
5356

5357
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2,320✔
5358
  pInfo->ignoreExpiredDataSaved = false;
2,320✔
5359

5360
  SExprSupp* pSup = &pOperator->exprSupp;
2,320✔
5361
  pSup->hasWindowOrGroup = true;
2,320✔
5362

5363
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2,320✔
5364
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5365

5366
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
2,320✔
5367
  initResultSizeInfo(&pOperator->resultInfo, 4096);
2,320✔
5368

5369
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
2,320✔
5370
  QUERY_CHECK_NULL(pInfo->pState, code, lino, _error, terrno);
2,320!
5371
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2,320✔
5372
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1, pInfo->primaryTsIndex);
2,320✔
5373

5374
  size_t     keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
2,320✔
5375
  SExprInfo* pExprInfo = NULL;
2,320✔
5376
  code = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &pExprInfo, &numOfCols);
2,320✔
5377
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5378
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str, pInfo->pState,
2,320✔
5379
                    &pTaskInfo->storageAPI.functionStore);
5380
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5381

5382
  if (pIntervalPhyNode->window.pExprs != NULL) {
2,320✔
5383
    int32_t    numOfScalar = 0;
1✔
5384
    SExprInfo* pScalarExprInfo = NULL;
1✔
5385

5386
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
1✔
5387
    QUERY_CHECK_CODE(code, lino, _error);
1!
5388

5389
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1✔
5390
    QUERY_CHECK_CODE(code, lino, _error);
1!
5391
  }
5392

5393
  pInfo->invertible = false;
2,320✔
5394
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
2,320✔
5395
  QUERY_CHECK_NULL(pInfo->pDelWins, code, lino, _error, terrno);
2,320!
5396
  pInfo->delIndex = 0;
2,320✔
5397

5398
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
2,320✔
5399
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5400

5401
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2,320✔
5402

5403
  pInfo->pPhyNode = NULL;  // create new child
2,320✔
5404
  pInfo->pPullDataMap = NULL;
2,320✔
5405
  pInfo->pFinalPullDataMap = NULL;
2,320✔
5406
  pInfo->pPullWins = NULL;  // SPullWindowInfo
2,320✔
5407
  pInfo->pullIndex = 0;
2,320✔
5408
  pInfo->pPullDataRes = NULL;
2,320✔
5409
  pInfo->numOfChild = 0;
2,320✔
5410
  pInfo->delKey.ts = INT64_MAX;
2,320✔
5411
  pInfo->delKey.groupId = 0;
2,320✔
5412
  pInfo->numOfDatapack = 0;
2,320✔
5413
  pInfo->pUpdated = NULL;
2,320✔
5414
  pInfo->pUpdatedMap = NULL;
2,320✔
5415
  int32_t funResSize = getMaxFunResSize(pSup, numOfCols);
2,320✔
5416

5417
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
2,320✔
5418
  pInfo->pState->pFileState = NULL;
2,320✔
5419

5420
  // used for backward compatibility of function's result info
5421
  pInfo->pState->pResultRowStore.resultRowGet = getResultRowFromBuf;
2,320✔
5422
  pInfo->pState->pResultRowStore.resultRowPut = putResultRowToBuf;
2,320✔
5423
  pInfo->pState->pExprSupp = &pOperator->exprSupp;
2,320✔
5424

5425
  code = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
2,320✔
5426
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
2,320✔
5427
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo), pHandle->checkpointId, STREAM_STATE_BUFF_HASH,
2,320✔
5428
      &pInfo->pState->pFileState);
2,320✔
5429
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5430

5431
  pInfo->pOperator = pOperator;
2,320✔
5432
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
2,320✔
5433
                  pInfo, pTaskInfo);
5434
  pOperator->fpSet =
5435
      createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAggNext, NULL, destroyStreamFinalIntervalOperatorInfo,
2,320✔
5436
                          optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5437
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
2,320✔
5438

5439
  pInfo->recvGetAll = false;
2,320✔
5440

5441
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
2,320✔
5442
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5443

5444
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
2,320✔
5445
  pInfo->pDeletedMap = tSimpleHashInit(4096, hashFn);
2,320✔
5446
  QUERY_CHECK_NULL(pInfo->pDeletedMap, code, lino, _error, terrno);
2,320!
5447
  pInfo->destHasPrimaryKey = pIntervalPhyNode->window.destHasPrimaryKey;
2,320✔
5448

5449
  // for stream
5450
  void*   buff = NULL;
2,320✔
5451
  int32_t len = 0;
2,320✔
5452
  int32_t res = pAPI->stateStore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_CHECKPOINT_NAME,
2,320✔
5453
                                                    strlen(STREAM_INTERVAL_OP_CHECKPOINT_NAME), &buff, &len);
5454
  if (res == TSDB_CODE_SUCCESS) {
2,320✔
5455
    doStreamIntervalDecodeOpState(buff, len, pOperator);
8✔
5456
    taosMemoryFree(buff);
8✔
5457
  }
5458

5459
  pInfo->basic.primaryPkIndex = -1;
2,320✔
5460
  code = initIntervalDownStream(downstream, pPhyNode->type, pInfo, &pInfo->basic);
2,320✔
5461
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5462

5463
  code = appendDownstream(pOperator, &downstream, 1);
2,320✔
5464
  QUERY_CHECK_CODE(code, lino, _error);
2,320!
5465

5466
  *pOptrInfo = pOperator;
2,320✔
5467
  return TSDB_CODE_SUCCESS;
2,320✔
5468

5469
_error:
×
5470
  if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
×
5471
  destroyOperatorAndDownstreams(pOperator, &downstream, 1);
×
5472
  pTaskInfo->code = code;
×
5473
  return code;
×
5474
}
5475

5476
int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
2,344✔
5477
                                         SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
5478
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
2,344✔
5479
  if (pIntervalPhyNode->window.triggerType == STREAM_TRIGGER_FORCE_WINDOW_CLOSE) {
2,344✔
5480
    return createStreamIntervalSliceOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
24✔
5481
  } else {
5482
    return createStreamSingleIntervalOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle, pOptrInfo);
2,320✔
5483
  }
5484
  return TSDB_CODE_SUCCESS;
5485
}
5486

5487
static void doStreamMidIntervalAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pUpdatedMap) {
37✔
5488
  int32_t                      code = TSDB_CODE_SUCCESS;
37✔
5489
  int32_t                      lino = 0;
37✔
5490
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperator->info;
37✔
5491
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
37✔
5492

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

5505
  int32_t     startPos = 0;
37✔
5506
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCol);
37✔
5507
  STimeWindow nextWin = getFinalTimeWindow(ts, &pInfo->interval);
37✔
5508

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

5531
    if (!inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,284!
5532
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCol, startPos, nextWin.ekey, &nextWin);
×
5533
      if (startPos < 0) {
×
5534
        break;
×
5535
      }
5536
      continue;
×
5537
    }
5538

5539
    int32_t winCode = TSDB_CODE_SUCCESS;
1,284✔
5540
    code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
1,284✔
5541
                                pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->stateStore, &winCode);
5542
    QUERY_CHECK_CODE(code, lino, _end);
1,284!
5543

5544
    pResult = (SResultRow*)pResPos->pRowBuff;
1,284✔
5545

5546
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
1,284!
5547
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,284✔
5548
      QUERY_CHECK_CODE(code, lino, _end);
1,284!
5549
    }
5550

5551
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
1,284!
5552
      code = tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
×
5553
      QUERY_CHECK_CODE(code, lino, _end);
×
5554
    }
5555

5556
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
1,284✔
5557
    code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos,
1,284✔
5558
                                           forwardRows, pSDataBlock->info.rows, numOfOutput);
1,284✔
5559
    QUERY_CHECK_CODE(code, lino, _end);
1,284!
5560
    key.ts = nextWin.skey;
1,284✔
5561

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

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

5585
_end:
37✔
5586
  if (code != TSDB_CODE_SUCCESS) {
37!
5587
    qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
×
5588
  }
5589
}
37✔
5590

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

5611
static SSDataBlock* buildMidIntervalResult(SOperatorInfo* pOperator) {
107✔
5612
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
107✔
5613
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
107✔
5614
  uint16_t                     opType = pOperator->operatorType;
107✔
5615

5616
  if (pInfo->recvPullover) {
107✔
5617
    pInfo->recvPullover = false;
6✔
5618
    printDataBlock(pInfo->pMidPulloverRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
6✔
5619
    return pInfo->pMidPulloverRes;
6✔
5620
  }
5621

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

5630
  if (pInfo->recvRetrive) {
101✔
5631
    pInfo->recvRetrive = false;
12✔
5632
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
12✔
5633
    return pInfo->pMidRetriveRes;
12✔
5634
  }
5635

5636
  return NULL;
89✔
5637
}
5638

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

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

5650
  if (pOperator->status == OP_EXEC_DONE) {
106!
5651
    (*ppRes) = NULL;
×
5652
    return code;
×
5653
  } else if (pOperator->status == OP_RES_TO_RETURN) {
106✔
5654
    SSDataBlock* resBlock = NULL;
34✔
5655
    code = buildIntervalResult(pOperator, &resBlock);
34✔
5656
    QUERY_CHECK_CODE(code, lino, _end);
34!
5657
    if (resBlock != NULL) {
34✔
5658
      (*ppRes) = resBlock;
6✔
5659
      return code;
34✔
5660
    }
5661

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

5677
    resBlock = buildMidIntervalResult(pOperator);
72✔
5678
    if (resBlock != NULL) {
72✔
5679
      (*ppRes) = resBlock;
3✔
5680
      return code;
3✔
5681
    }
5682

5683
    if (pInfo->clearState) {
69✔
5684
      pInfo->clearState = false;
18✔
5685
      clearFunctionContext(&pOperator->exprSupp);
18✔
5686
      clearStreamIntervalOperator(pInfo);
18✔
5687
    }
5688
  }
5689

5690
  if (!pInfo->pUpdated) {
69✔
5691
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
66✔
5692
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
66!
5693
  }
5694
  if (!pInfo->pUpdatedMap) {
69✔
5695
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
66✔
5696
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
66✔
5697
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
66!
5698
  }
5699

5700
  while (1) {
53✔
5701
    if (isTaskKilled(pTaskInfo)) {
122!
5702
      qInfo("===stream=== %s task is killed, code %s", GET_TASKID(pTaskInfo), tstrerror(pTaskInfo->code));
×
5703
      (*ppRes) = NULL;
×
5704
      return code;
3✔
5705
    }
5706

5707
    SSDataBlock* pBlock = NULL;
122✔
5708
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
122✔
5709
    QUERY_CHECK_CODE(code, lino, _end);
122!
5710

5711
    if (pBlock == NULL) {
122✔
5712
      pOperator->status = OP_RES_TO_RETURN;
48✔
5713
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64, getStreamOpName(pOperator->operatorType),
48!
5714
             pInfo->numOfDatapack);
5715
      pInfo->numOfDatapack = 0;
48✔
5716
      break;
48✔
5717
    }
5718
    pInfo->numOfDatapack++;
74✔
5719
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
74✔
5720
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
74✔
5721

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

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

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

5764
      if (pInfo->recvPullover) {
12✔
5765
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
6✔
5766
        QUERY_CHECK_CODE(code, lino, _end);
6!
5767

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

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

5788
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
12✔
5789
      QUERY_CHECK_CODE(code, lino, _end);
12!
5790

5791
      taosArrayDestroy(delWins);
12✔
5792
      pInfo->recvRetrive = true;
12✔
5793
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
12✔
5794
      QUERY_CHECK_CODE(code, lino, _end);
12!
5795

5796
      pInfo->pMidRetriveRes->info.type = STREAM_MID_RETRIEVE;
12✔
5797
      pInfo->clearState = true;
12✔
5798
      break;
12✔
5799
    } else {
5800
      if (pBlock->info.type != STREAM_INVALID) {
26!
5801
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
5802
        QUERY_CHECK_CODE(code, lino, _end);
×
5803
      }
5804
    }
5805

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

5819
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
66✔
5820
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
66✔
5821

5822
  void*   pIte = NULL;
66✔
5823
  int32_t iter = 0;
66✔
5824
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
1,350✔
5825
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
1,284✔
5826
    if (!tmp) {
1,284!
5827
      code = terrno;
×
5828
      QUERY_CHECK_CODE(code, lino, _end);
×
5829
    }
5830
  }
5831

5832
  tSimpleHashCleanup(pInfo->pUpdatedMap);
66✔
5833
  pInfo->pUpdatedMap = NULL;
66✔
5834
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
66✔
5835

5836
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
66✔
5837
  pInfo->pUpdated = NULL;
66✔
5838
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
66✔
5839
  QUERY_CHECK_CODE(code, lino, _end);
66!
5840

5841
  SSDataBlock* resBlock = NULL;
66✔
5842
  code = buildIntervalResult(pOperator, &resBlock);
66✔
5843
  QUERY_CHECK_CODE(code, lino, _end);
66!
5844
  if (resBlock != NULL) {
66✔
5845
    (*ppRes) = resBlock;
31✔
5846
    return code;
31✔
5847
  }
5848

5849
  resBlock = buildMidIntervalResult(pOperator);
35✔
5850
  if (resBlock != NULL) {
35✔
5851
    (*ppRes) = resBlock;
15✔
5852
    return code;
15✔
5853
  }
5854

5855
  if (pInfo->clearState) {
20!
5856
    pInfo->clearState = false;
×
5857
    clearFunctionContext(&pOperator->exprSupp);
×
5858
    clearStreamIntervalOperator(pInfo);
×
5859
  }
5860

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

5871
static SSDataBlock* doStreamMidIntervalAgg(SOperatorInfo* pOperator) {
×
5872
  SSDataBlock* pRes = NULL;
×
5873
  int32_t      code = doStreamMidIntervalAggNext(pOperator, &pRes);
×
5874
  return pRes;
×
5875
}
5876

5877
void setStreamOperatorCompleted(SOperatorInfo* pOperator) {
14,746✔
5878
  qDebug("stask:%s  %s status: %d. set completed", GET_TASKID(pOperator->pTaskInfo),
14,746✔
5879
         getStreamOpName(pOperator->operatorType), pOperator->status);
5880
  setOperatorCompleted(pOperator);
14,746✔
5881
}
14,746✔
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