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

taosdata / TDengine / #3809

01 Apr 2025 03:03AM UTC coverage: 34.048% (+0.02%) from 34.033%
#3809

push

travis-ci

happyguoxy
test:alter gcda dir

148452 of 599532 branches covered (24.76%)

Branch coverage included in aggregate %.

222312 of 489411 relevant lines covered (45.42%)

761122.82 hits per line

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

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

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

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

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

46
#define MAX_STREAM_HISTORY_RESULT 20000000
47

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

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

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

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

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

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

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

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

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

101
  return midPos;
×
102
}
103

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

114
  if (pData->window.skey > pos->window.ekey) {
×
115
    return 1;
×
116
  } else if (pData->window.ekey < pos->window.skey) {
×
117
    return -1;
×
118
  }
119
  return 0;
×
120
}
121

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

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

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

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

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

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

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

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

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

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

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

222
int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }
×
223

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

535
  blockDataDestroy(pInfo->pCheckpointRes);
16✔
536

537
  taosMemoryFreeClear(param);
16!
538
}
539

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

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

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

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

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

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

572
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
12!
573
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
×
574
    pBasic->primaryPkIndex = pScanInfo->basic.primaryPkIndex;
×
575
  }
576

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

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

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

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

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

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

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

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

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

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

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

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

663
  *pResult = (SRowBuffPos*)value;
1,363✔
664
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
1,363✔
665

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

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

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

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

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

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

727
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
374✔
728
  if (pBlock->info.rows <= 0) {
374!
729
    return;
374✔
730
  }
731
  blockDataCleanup(pBlock);
×
732
}
733

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

920
static void clearFunctionContext(SExprSupp* pSup) {
187✔
921
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
748✔
922
    pSup->pCtx[i].saveHandle.currentPage = -1;
561✔
923
  }
924
}
187✔
925

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

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

941
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
645✔
942

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

975
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
1,056!
976
      break;
×
977
    }
978
    pGroupResInfo->index += 1;
1,056✔
979

980
    for (int32_t j = 0; j < numOfExprs; ++j) {
4,224✔
981
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
3,168✔
982

983
      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
3,168✔
984

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

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

1013
    pBlock->info.rows += pRow->numOfRows;
1,056✔
1014
  }
1015

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

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

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

1032
  blockDataCleanup(pBlock);
1,330✔
1033
  taosArrayClear(pSessionKeys);
1,330✔
1034
  if (!hasRemainResults(pGroupResInfo)) {
1,330✔
1035
    return;
685✔
1036
  }
1037

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

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

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

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

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

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

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

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

1095
  int32_t     startPos = 0;
1,136✔
1096
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
1,136✔
1097
  STimeWindow nextWin = {0};
1,136✔
1098
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,136✔
1099
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
283✔
1100
  } else {
1101
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
853✔
1102
  }
1103
  while (1) {
228✔
1104
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
1,364✔
1105
    if (hasSrcPrimaryKeyCol(&pInfo->basic) && !IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData &&
1,364!
1106
        pSDataBlock->info.type != STREAM_PULL_DATA) {
×
1107
      pPkVal = colDataGetData(pPkColDataInfo, startPos);
×
1108
      pkLen = colDataGetRowLength(pPkColDataInfo, startPos);
×
1109
    }
1110

1111
    if ((!IS_FINAL_INTERVAL_OP(pOperator) && pInfo->ignoreExpiredData && pSDataBlock->info.type != STREAM_PULL_DATA &&
1,523!
1112
         checkExpiredData(&pInfo->stateStore, pInfo->pUpdateInfo, &pInfo->twAggSup, pSDataBlock->info.id.uid,
159✔
1113
                          nextWin.ekey, pPkVal, pkLen)) ||
1,363✔
1114
        !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
1,363!
1115
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
1✔
1116
      if (startPos < 0) {
1!
1117
        break;
1,136✔
1118
      }
1119
      qDebug("===stream===ignore expired data, window end ts:%" PRId64 ", maxts - wartermak:%" PRId64, nextWin.ekey,
×
1120
             pInfo->twAggSup.maxTs - pInfo->twAggSup.waterMark);
1121
      continue;
×
1122
    }
1123

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

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

1159
      if (ignore) {
465!
1160
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
×
1161
        if (startPos < 0) {
×
1162
          break;
×
1163
        }
1164
        continue;
×
1165
      }
1166
    }
1167

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

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

1181
    pResult = (SResultRow*)pResPos->pRowBuff;
1,363✔
1182

1183
    if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,363✔
1184
      forwardRows = 1;
465✔
1185
    } else {
1186
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
898✔
1187
                                             NULL, TSDB_ORDER_ASC);
1188
    }
1189

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

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

1200
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
1,363!
1201
      code = saveWinResult(&key, pResPos, pUpdatedMap);
1,205✔
1202
      QUERY_CHECK_CODE(code, lino, _end);
1,205!
1203
    }
1204

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

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

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

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

1244
  if (pWin1->groupId > pWin2->groupId) {
2,150✔
1245
    return 1;
521✔
1246
  } else if (pWin1->groupId < pWin2->groupId) {
1,629✔
1247
    return -1;
472✔
1248
  }
1249

1250
  if (pWin1->ts > pWin2->ts) {
1,157✔
1251
    return 1;
583✔
1252
  } else if (pWin1->ts < pWin2->ts) {
574!
1253
    return -1;
574✔
1254
  }
1255

1256
  return 0;
×
1257
}
1258

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1413
  return tlen;
×
1414
}
1415

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1552
  // check if query task is closed or not
1553
  if (isTaskKilled(pTaskInfo)) {
1,330!
1554
    (*ppRes) = NULL;
×
1555
    return code;
×
1556
  }
1557

1558
  addNotifyEvent = IS_NORMAL_INTERVAL_OP(pOperator) &&
1,731✔
1559
                   BIT_FLAG_TEST_MASK(pTaskInfo->streamInfo.eventTypes, SNOTIFY_EVENT_WINDOW_CLOSE);
401!
1560
  if (IS_FINAL_INTERVAL_OP(pOperator)) {
1,330✔
1561
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
374✔
1562
    if (pInfo->pPullDataRes->info.rows != 0) {
374!
1563
      // process the rest of the data
1564
      printDataBlock(pInfo->pPullDataRes, getStreamOpName(opType), GET_TASKID(pTaskInfo));
×
1565
      (*ppRes) = pInfo->pPullDataRes;
×
1566
      return code;
×
1567
    }
1568
  }
1569

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

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

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

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

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

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

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

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

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

1647
  qDebug("stask:%s  %s status: %d", GET_TASKID(pTaskInfo), getStreamOpName(pOperator->operatorType), pOperator->status);
1,028!
1648

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

1661
    if (pInfo->recvGetAll) {
311!
1662
      pInfo->recvGetAll = false;
×
1663
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
×
1664
    }
1665

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1872
  if (pInfo->recvRetrive) {
89!
1873
    pInfo->recvRetrive = false;
×
1874
    printDataBlock(pInfo->pMidRetriveRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
1875
    (*ppRes) = pInfo->pMidRetriveRes;
×
1876
    return code;
×
1877
  }
1878

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

1890
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
16✔
1891
  if (pWinPhyNode->deleteMark <= 0) {
16!
1892
    return DEAULT_DELETE_MARK;
16✔
1893
  }
1894
  int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
×
1895
  deleteMark = TMAX(deleteMark, interval);
×
1896
  return deleteMark;
×
1897
}
1898

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

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

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

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

1926
static int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
16✔
1927
  int32_t size = 0;
16✔
1928
  for (int32_t i = 0; i < numOfCols; ++i) {
68✔
1929
    int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
52✔
1930
    size = TMAX(size, resSize);
52✔
1931
  }
1932
  return size;
16✔
1933
}
1934

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2202
  pGroupResInfo->freeItem = false;
×
2203
  taosArrayDestroy(pGroupResInfo->pRows);
×
2204
  pGroupResInfo->pRows = NULL;
×
2205
  pGroupResInfo->index = 0;
×
2206
}
×
2207

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

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

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

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

2243
  taosArrayDestroy(pInfo->historyWins);
×
2244
  blockDataDestroy(pInfo->pCheckpointRes);
×
2245
  tSimpleHashCleanup(pInfo->pPkDeleted);
×
2246
  destroyNonBlockAggSupptor(&pInfo->nbSup);
×
2247

2248
  taosMemoryFreeClear(param);
×
2249
}
2250

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

2259
  for (int32_t i = 0; i < numOfCols; ++i) {
×
2260
    pSup->pCtx[i].saveHandle.pBuf = NULL;
×
2261
  }
2262

2263
  return TSDB_CODE_SUCCESS;
×
2264
}
2265

2266
void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
×
2267
  for (int i = 0; i < nums; i++) {
×
2268
    pDummy[i].functionId = pCtx[i].functionId;
×
2269
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
×
2270
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
×
2271
    pDummy[i].fpSet.init = pCtx[i].fpSet.init;
×
2272
  }
2273
}
×
2274

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

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

2305
  pBasic->pTsDataState = pScanInfo->basic.pTsDataState;
×
2306

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

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

2321
static TSKEY sesionTs(void* pKey) {
×
2322
  SSessionKey* pWinKey = (SSessionKey*)pKey;
×
2323
  return pWinKey->win.skey;
×
2324
}
2325

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

2335
  pSup->gap = gap;
×
2336
  pSup->stateKeySize = keySize;
×
2337
  pSup->stateKeyType = keyType;
×
2338
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
×
2339
  QUERY_CHECK_NULL(pSup->pDummyCtx, code, lino, _end, terrno);
×
2340

2341
  pSup->stateStore = *pStore;
×
2342
  pSup->pSessionAPI = pApi;
×
2343

2344
  initDummyFunction(pSup->pDummyCtx, pExpSup->pCtx, numOfOutput);
×
2345
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
×
2346
  QUERY_CHECK_NULL(pSup->pState, code, lino, _end, terrno);
×
2347

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

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

2371
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
2372
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
×
2373
  QUERY_CHECK_NULL(pSup->pResultRows, code, lino, _end, terrno);
×
2374

2375
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
2376
    pExpSup->pCtx[i].saveHandle.pState = pSup->pState;
×
2377
  }
2378

2379
  pSup->pCur = NULL;
×
2380

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

2388
bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
×
2389
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
×
2390
    return true;
×
2391
  }
2392
  return false;
×
2393
}
2394

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

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

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

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

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

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

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

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

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

2465
  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
×
2466
}
2467

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

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

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

2489
void releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI) {
×
2490
  pAPI->streamStateReleaseBuf(pState, pPos, false);
×
2491
}
×
2492

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

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

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

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

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

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

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

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

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

2600
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
×
2601
  code = applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
×
2602

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2784
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
×
2785
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
×
2786
  SColumnInfoData* pEndTsCol = NULL;
×
2787
  if (hasEndTs) {
×
2788
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
×
2789
  } else {
2790
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
×
2791
  }
2792

2793
  TSKEY* endTsCols = (int64_t*)pEndTsCol->pData;
×
2794

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

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

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

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

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

2842
    code = compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap, NULL, NULL);
×
2843
    QUERY_CHECK_CODE(code, lino, _end);
×
2844

2845
    code = saveSessionOutputBuf(pAggSup, &winInfo);
×
2846
    QUERY_CHECK_CODE(code, lino, _end);
×
2847

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

2864
    i += winRows;
×
2865
  }
2866

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

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

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

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

2910
  if (pWin1->groupId > pWin2->groupId) {
×
2911
    return 1;
×
2912
  } else if (pWin1->groupId < pWin2->groupId) {
×
2913
    return -1;
×
2914
  }
2915

2916
  if (pWin1->win.skey > pWin2->win.skey) {
×
2917
    return 1;
×
2918
  } else if (pWin1->win.skey < pWin2->win.skey) {
×
2919
    return -1;
×
2920
  }
2921

2922
  return 0;
×
2923
}
2924

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

2930
  QUERY_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
2931
  QUERY_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
2932

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

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

2941
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
×
2942
  colDataSetNULL(pUidCol, pBlock->info.rows);
×
2943

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

2948
  SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
×
2949
  colDataSetNULL(pCalStCol, pBlock->info.rows);
×
2950

2951
  SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
×
2952
  colDataSetNULL(pCalEdCol, pBlock->info.rows);
×
2953

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

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

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

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

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

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

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

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

3034
_end:
×
3035
  if ((*Ite) == NULL) {
×
3036
    tSimpleHashClear(pStDeleted);
×
3037
  }
3038

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

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

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

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

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

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

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

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

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

3106
          code = compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true, NULL, NULL);
×
3107
          QUERY_CHECK_CODE(code, lino, _end);
×
3108

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

3121
      code = saveSessionOutputBuf(pAggSup, &parentWin);
×
3122
      QUERY_CHECK_CODE(code, lino, _end);
×
3123
    }
3124
  }
3125

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

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

3157
static int32_t closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
×
3158
  int32_t code = TSDB_CODE_SUCCESS;
×
3159
  int32_t lino = 0;
×
3160

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

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

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

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

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

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

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

3239
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
×
3240

3241
  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
×
3242
    SResultWindowInfo* pWinInfo = taosArrayGet(pGroupResInfo->pRows, i);
×
3243
    SRowBuffPos*       pPos = pWinInfo->pStatePos;
×
3244
    SResultRow*        pRow = NULL;
×
3245
    SSessionKey*       pKey = (SSessionKey*)pPos->pKey;
×
3246

3247
    if (pBlock->info.id.groupId == 0) {
×
3248
      pBlock->info.id.groupId = pKey->groupId;
×
3249

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

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

3269
    code = pAPI->stateStore.streamStateGetByPos(pState, pPos, (void**)&pRow);
×
3270
    QUERY_CHECK_CODE(code, lino, _end);
×
3271

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

3286
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
×
3287
      break;
×
3288
    }
3289

3290
    pGroupResInfo->index += 1;
×
3291

3292
    for (int32_t j = 0; j < numOfExprs; ++j) {
×
3293
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;
×
3294

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

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

3323
    pBlock->info.dataLoad = 1;
×
3324
    pBlock->info.rows += pRow->numOfRows;
×
3325
  }
3326
  code = blockDataUpdateTsWindow(pBlock, 0);
×
3327
  QUERY_CHECK_CODE(code, lino, _end);
×
3328

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

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

3344
  blockDataCleanup(pBlock);
×
3345
  taosArrayClear(pSessionKeys);
×
3346
  if (!hasRemainResults(pGroupResInfo)) {
×
3347
    cleanupGroupResInfo(pGroupResInfo);
×
3348
    goto _end;
×
3349
  }
3350

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

3356
  if (pBlock->info.rows == 0) {
×
3357
    cleanupGroupResInfo(pGroupResInfo);
×
3358
  }
3359

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

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

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

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

3415
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
×
3416
  QUERY_CHECK_CODE(code, lino, _end);
×
3417

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3539
  return tlen;
×
3540
}
3541

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3686
    if (pInfo->recvGetAll) {
×
3687
      pInfo->recvGetAll = false;
×
3688
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
×
3689
    }
3690

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

3698
    setStreamOperatorCompleted(pOperator);
×
3699
    (*ppRes) = NULL;
×
3700
    return code;
×
3701
  }
3702

3703
  SOperatorInfo* downstream = pOperator->pDownstream[0];
×
3704
  if (!pInfo->pUpdated) {
×
3705
    pInfo->pUpdated = taosArrayInit(16, sizeof(SResultWindowInfo));
×
3706
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
×
3707
  }
3708
  if (!pInfo->pStUpdated) {
×
3709
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
3710
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
×
3711
    QUERY_CHECK_NULL(pInfo->pStUpdated, code, lino, _end, terrno);
×
3712
  }
3713
  while (1) {
×
3714
    SSDataBlock* pBlock = NULL;
×
3715
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
×
3716
    QUERY_CHECK_CODE(code, lino, _end);
×
3717

3718
    if (pBlock == NULL) {
×
3719
      break;
×
3720
    }
3721
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
×
3722
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
×
3723

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

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

3741
        code = rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
×
3742
        QUERY_CHECK_CODE(code, lino, _end);
×
3743
      }
3744
      code = copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
×
3745
      QUERY_CHECK_CODE(code, lino, _end);
×
3746

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

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

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

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

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

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

3817
  code = closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
×
3818
  QUERY_CHECK_CODE(code, lino, _end);
×
3819

3820
  code = closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
×
3821
  QUERY_CHECK_CODE(code, lino, _end);
×
3822

3823
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
×
3824
  QUERY_CHECK_CODE(code, lino, _end);
×
3825

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

3842
  SSDataBlock* opRes = NULL;
×
3843
  code = buildSessionResult(pOperator, &opRes);
×
3844
  QUERY_CHECK_CODE(code, lino, _end);
×
3845
  if (opRes) {
×
3846
    (*ppRes) = opRes;
×
3847
    return code;
×
3848
  }
3849

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

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

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

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

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

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

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

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

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

3926
  SStreamScanInfo* pScanInfo = downstream->info;
×
3927
  pAggSup->pUpdateInfo = pScanInfo->pUpdateInfo;
×
3928
}
3929

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

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

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

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

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

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

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

3988
  QUERY_CHECK_CODE(code, lino, _end);
×
3989

3990
  int32_t      num = (size - sizeof(TSKEY)) / sizeof(SSessionKey);
×
3991
  SSessionKey* pSeKeyBuf = (SSessionKey*)pBuf;
×
3992

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

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

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

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

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

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

4048
int32_t createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
×
4049
                                           SReadHandle* pHandle, SOperatorInfo** pOptrInfo) {
4050
  QRY_PARAM_CHECK(pOptrInfo);
×
4051

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

4063
  pOperator->pTaskInfo = pTaskInfo;
×
4064

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

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

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

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

4087
  code = initBasicInfoEx(&pInfo->binfo, pExpSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
×
4088
  QUERY_CHECK_CODE(code, lino, _error);
×
4089

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

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

4107
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
×
4108
  QUERY_CHECK_CODE(code, lino, _error);
×
4109

4110
  if (pSessionNode->window.pTsEnd) {
×
4111
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
×
4112
  }
4113

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

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

4137
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
×
4138
  QUERY_CHECK_CODE(code, lino, _error);
×
4139

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

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

4164
  code = initStreamBasicInfo(&pInfo->basic, pOperator);
×
4165
  QUERY_CHECK_CODE(code, lino, _error);
×
4166

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

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

4190
    code = appendDownstream(pOperator, &downstream, 1);
×
4191
    QUERY_CHECK_CODE(code, lino, _error);
×
4192
  }
4193

4194
  *pOptrInfo = pOperator;
×
4195
  return TSDB_CODE_SUCCESS;
×
4196

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

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

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

4225
  removeSessionResults(pAggSup, pMapUpdate, pWins);
×
4226
  code = copyDeleteWindowInfo(pWins, pMapDelete);
×
4227
  QUERY_CHECK_CODE(code, lino, _end);
×
4228

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

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

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

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

4258
  {
4259
    SSDataBlock* opRes = NULL;
×
4260
    code = buildSessionResult(pOperator, &opRes);
×
4261
    QUERY_CHECK_CODE(code, lino, _end);
×
4262
    if (opRes) {
×
4263
      (*ppRes) = opRes;
×
4264
      return code;
×
4265
    }
4266

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

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

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

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

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

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

4348
  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
×
4349
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
×
4350

4351
  code = copyUpdateResult(&pInfo->pStUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
×
4352
  QUERY_CHECK_CODE(code, lino, _end);
×
4353

4354
  removeSessionDeleteResults(pInfo->pStDeleted, pInfo->pUpdated);
×
4355

4356
  if (pInfo->isHistoryOp) {
×
4357
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
×
4358
    QUERY_CHECK_CODE(code, lino, _end);
×
4359
  }
4360

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

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

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

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

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

4395
int32_t createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
×
4396
                                                SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle,
4397
                                                SOperatorInfo** pOptrInfo) {
4398
  QRY_PARAM_CHECK(pOptrInfo);
×
4399

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

4409
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
×
4410
  pInfo->pOperator = pOperator;
×
4411

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

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

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

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

4451
  if (!IS_FINAL_SESSION_OP(pOperator) || numOfChild == 0) {
×
4452
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
×
4453
  }
4454

4455
  *pOptrInfo = pOperator;
×
4456
  return code;
×
4457

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

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

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

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

4506
  taosArrayDestroy(pInfo->historyWins);
×
4507
  blockDataDestroy(pInfo->pCheckpointRes);
×
4508
  tSimpleHashCleanup(pInfo->pPkDeleted);
×
4509
  destroyNonBlockAggSupptor(&pInfo->nbSup);
×
4510

4511
  taosMemoryFreeClear(param);
×
4512
}
4513

4514
bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
×
4515
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
×
4516
    return true;
×
4517
  }
4518
  return false;
×
4519
}
4520

4521
bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
×
4522
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
×
4523
}
4524

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

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

4541
void getNextStateWin(const SStreamAggSupporter* pAggSup, SStateWindowInfo* pNextWin, bool asc) {
×
4542
  SStreamStateCur* pCur = NULL;
×
4543

4544
  if (pAggSup == NULL || pNextWin == NULL) {
×
4545
    return;
×
4546
  }
4547

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

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

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

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

4596
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
×
4597
  getNextStateWin(pAggSup, pNextWin, true);
×
4598

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

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

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

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

4645
  if (winCode == TSDB_CODE_SUCCESS) {
×
4646
    pCurWin->winInfo.isOutput = true;
×
4647
    if (pCurWin->winInfo.pStatePos->needFree) {
×
4648
      pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
×
4649
    }
4650
  } else if (pKeyData) {
×
4651
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
×
4652
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
×
4653
    } else {
4654
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
×
4655
    }
4656
  }
4657

4658
  *pWinCode = winCode;
×
4659

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

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

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

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

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

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

4728
  if (tSimpleHashGet(pResults, &checkKey, sizeof(SSessionKey)) != NULL) {
×
4729
    return true;
×
4730
  }
4731
  return false;
×
4732
}
4733

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

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

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

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

4768
  int32_t rows = pSDataBlock->info.rows;
×
4769
  code = blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
×
4770
  QUERY_CHECK_CODE(code, lino, _end);
×
4771

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

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

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

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

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

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

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

4836
    code = saveSessionOutputBuf(pAggSup, &curWin.winInfo);
×
4837
    QUERY_CHECK_CODE(code, lino, _end);
×
4838

4839
    if (pInfo->destHasPrimaryKey && curWin.winInfo.isOutput && IS_NORMAL_STATE_OP(pOperator)) {
×
4840
      code = saveDeleteRes(pInfo->pPkDeleted, curWin.winInfo.sessionWin);
×
4841
      QUERY_CHECK_CODE(code, lino, _end);
×
4842
    }
4843

4844
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
×
4845
      code = saveResult(curWin.winInfo, pSeUpdated);
×
4846
      QUERY_CHECK_CODE(code, lino, _end);
×
4847
    }
4848

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

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

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

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

4879
  void* pData = (buf == NULL) ? NULL : *buf;
×
4880

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

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

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

4905
  // 4.dataVersion
4906
  tlen += taosEncodeFixedI64(buf, pInfo->dataVersion);
×
4907

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

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

4921
  return tlen;
×
4922
}
4923

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

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

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

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

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

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

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

4981
  if (ppBuf) {
×
4982
    (*ppBuf) = buf;
×
4983
  }
4984

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

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

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

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

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

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

5058
  code = removeOutdatedNotifyEvents(&pInfo->twAggSup, pNotifySup, pNotifyEventStat);
×
5059
  QUERY_CHECK_CODE(code, lino, _end);
×
5060

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

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

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

5091
    if (pInfo->recvGetAll) {
×
5092
      pInfo->recvGetAll = false;
×
5093
      resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
×
5094
    }
5095

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

5103
    setStreamOperatorCompleted(pOperator);
×
5104
    (*ppRes) = NULL;
×
5105
    return code;
×
5106
  }
5107

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

5123
    if (pBlock == NULL) {
×
5124
      break;
×
5125
    }
5126
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "recv", GET_TASKID(pTaskInfo));
×
5127
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
×
5128

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

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

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

5172
  code = closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
×
5173
  QUERY_CHECK_CODE(code, lino, _end);
×
5174

5175
  code = copyUpdateResult(&pInfo->pSeUpdated, pInfo->pUpdated, sessionKeyCompareAsc);
×
5176
  QUERY_CHECK_CODE(code, lino, _end);
×
5177

5178
  removeSessionDeleteResults(pInfo->pSeDeleted, pInfo->pUpdated);
×
5179

5180
  if (pInfo->isHistoryOp) {
×
5181
    code = getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
×
5182
    QUERY_CHECK_CODE(code, lino, _end);
×
5183
  }
5184
  if (pInfo->destHasPrimaryKey && IS_NORMAL_STATE_OP(pOperator)) {
×
5185
    code = copyDeleteSessionKey(pInfo->pPkDeleted, pInfo->pSeDeleted);
×
5186
    QUERY_CHECK_CODE(code, lino, _end);
×
5187
  }
5188

5189
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
×
5190
  pInfo->pUpdated = NULL;
×
5191
  code = blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
×
5192
  QUERY_CHECK_CODE(code, lino, _end);
×
5193

5194
  SSDataBlock* resBlock = NULL;
×
5195
  code = buildStateResult(pOperator, &resBlock);
×
5196
  QUERY_CHECK_CODE(code, lino, _end);
×
5197
  if (resBlock != NULL) {
×
5198
    (*ppRes) = resBlock;
×
5199
    return code;
×
5200
  }
5201

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

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

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

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

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

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

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

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

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

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

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

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

5318
    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
×
5319
      code = saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
×
5320
      QUERY_CHECK_CODE(code, lino, _end);
×
5321
    }
5322
  }
5323
  taosMemoryFreeClear(pBuf);
×
5324

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

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

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

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

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

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

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

5374
  code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
×
5375
  QUERY_CHECK_CODE(code, lino, _error);
×
5376

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

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

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

5400
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
×
5401
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
×
5402
  QUERY_CHECK_NULL(pInfo->pSeDeleted, code, lino, _error, terrno);
×
5403
  pInfo->pDelIterator = NULL;
×
5404

5405
  code = createSpecialDataBlock(STREAM_DELETE_RESULT, &pInfo->pDelRes);
×
5406
  QUERY_CHECK_CODE(code, lino, _error);
×
5407

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

5420
  if (pHandle) {
×
5421
    pInfo->isHistoryOp = (pHandle->fillHistory == STREAM_HISTORY_OPERATOR);
×
5422
  }
5423

5424
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
×
5425
  QUERY_CHECK_CODE(code, lino, _error);
×
5426

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

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

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

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

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

5471
  code = appendDownstream(pOperator, &downstream, 1);
×
5472
  QUERY_CHECK_CODE(code, lino, _error);
×
5473

5474
  pInfo->trueForLimit = pStateNode->trueForLimit;
×
5475

5476
  *pOptrInfo = pOperator;
×
5477
  return TSDB_CODE_SUCCESS;
×
5478

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

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

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

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

5509
  if (pOperator->status == OP_EXEC_DONE) {
37!
5510
    (*ppRes) = NULL;
×
5511
    return code;
×
5512
  }
5513

5514
  if (pOperator->status == OP_RES_TO_RETURN) {
37✔
5515
    SSDataBlock* resBlock = NULL;
17✔
5516
    code = buildIntervalResult(pOperator, &resBlock);
17✔
5517
    QUERY_CHECK_CODE(code, lino, _end);
17!
5518
    if (resBlock != NULL) {
17✔
5519
      (*ppRes) = resBlock;
10✔
5520
      return code;
17✔
5521
    }
5522

5523
    if (pInfo->recvGetAll) {
7!
5524
      pInfo->recvGetAll = false;
×
5525
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
×
5526
    }
5527

5528
    if (pInfo->reCkBlock) {
7!
5529
      pInfo->reCkBlock = false;
×
5530
      printDataBlock(pInfo->pCheckpointRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5531
      (*ppRes) = pInfo->pCheckpointRes;
×
5532
      return code;
×
5533
    }
5534

5535
    setStreamOperatorCompleted(pOperator);
7✔
5536
    (*ppRes) = NULL;
7✔
5537
    return code;
7✔
5538
  }
5539

5540
  SOperatorInfo* downstream = pOperator->pDownstream[0];
20✔
5541

5542
  if (!pInfo->pUpdated) {
20✔
5543
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
10✔
5544
    QUERY_CHECK_NULL(pInfo->pUpdated, code, lino, _end, terrno);
10!
5545
  }
5546

5547
  if (!pInfo->pUpdatedMap) {
20✔
5548
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
10✔
5549
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
10✔
5550
    QUERY_CHECK_NULL(pInfo->pUpdatedMap, code, lino, _end, terrno);
10!
5551
  }
5552

5553
  while (1) {
117✔
5554
    SSDataBlock* pBlock = NULL;
137✔
5555
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
137✔
5556
    QUERY_CHECK_CODE(code, lino, _end);
137!
5557

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

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

5569
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
127!
5570
        pBlock->info.type == STREAM_CLEAR) {
127!
5571
      code = doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap, NULL);
×
5572
      QUERY_CHECK_CODE(code, lino, _end);
×
5573
      continue;
×
5574
    } else if (pBlock->info.type == STREAM_GET_ALL) {
127!
5575
      pInfo->recvGetAll = true;
×
5576
      code = getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
×
5577
      QUERY_CHECK_CODE(code, lino, _end);
×
5578
      continue;
×
5579
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
127✔
5580
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
10✔
5581
      (*ppRes) = pBlock;
10✔
5582
      return code;
10✔
5583
    } else if (pBlock->info.type == STREAM_DROP_CHILD_TABLE) {
117!
5584
      doDeleteWindowByGroupId(pOperator, pBlock);
×
5585
      printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
×
5586
      (*ppRes) = pBlock;
×
5587
      return code;
×
5588
    } else if (pBlock->info.type == STREAM_CHECKPOINT) {
117!
5589
      pAPI->stateStore.streamStateCommit(pInfo->pState);
×
5590
      doStreamIntervalSaveCheckpoint(pOperator);
×
5591
      pInfo->reCkBlock = true;
×
5592
      code = copyDataBlock(pInfo->pCheckpointRes, pBlock);
×
5593
      QUERY_CHECK_CODE(code, lino, _end);
×
5594

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

5603
    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
117!
5604
      // set input version
5605
      pTaskInfo->version = pBlock->info.version;
117✔
5606
    }
5607

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

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

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

5643
  if (pInfo->destHasPrimaryKey && IS_NORMAL_INTERVAL_OP(pOperator)) {
10!
5644
    code = copyIntervalDeleteKey(pInfo->pDeletedMap, pInfo->pDelWins);
×
5645
    QUERY_CHECK_CODE(code, lino, _end);
×
5646
  }
5647

5648
  void*   pIte = NULL;
10✔
5649
  int32_t iter = 0;
10✔
5650
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
60✔
5651
    void* tmp = taosArrayPush(pInfo->pUpdated, pIte);
50✔
5652
    if (!tmp) {
50!
5653
      code = terrno;
×
5654
      QUERY_CHECK_CODE(code, lino, _end);
×
5655
    }
5656
  }
5657
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
10✔
5658

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

5664
  tSimpleHashCleanup(pInfo->pUpdatedMap);
10✔
5665
  pInfo->pUpdatedMap = NULL;
10✔
5666

5667
  code = buildIntervalResult(pOperator, ppRes);
10✔
5668
  QUERY_CHECK_CODE(code, lino, _end);
10!
5669

5670
  return code;
10✔
5671

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

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

5688
  int32_t code = TSDB_CODE_SUCCESS;
3✔
5689
  int32_t lino = 0;
3✔
5690
  int32_t numOfCols = 0;
3✔
5691

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

5699
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;
3✔
5700

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

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

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

5723
  pOperator->pTaskInfo = pTaskInfo;
3✔
5724
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
3✔
5725

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

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

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

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

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

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

5751
  if (pIntervalPhyNode->window.pExprs != NULL) {
3!
5752
    int32_t    numOfScalar = 0;
×
5753
    SExprInfo* pScalarExprInfo = NULL;
×
5754

5755
    code = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalar);
×
5756
    QUERY_CHECK_CODE(code, lino, _error);
×
5757

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

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

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

5770
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
3✔
5771

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

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

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

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

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

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

5811
  pInfo->recvGetAll = false;
3✔
5812

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

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

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

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

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

5838
  *pOptrInfo = pOperator;
3✔
5839
  return TSDB_CODE_SUCCESS;
3✔
5840

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

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

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

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

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

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

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

5905
    pResult = (SResultRow*)pResPos->pRowBuff;
×
5906

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

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

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

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

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

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

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

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

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

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

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

5997
  return NULL;
×
5998
}
5999

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

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

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

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

6038
    resBlock = buildMidIntervalResult(pOperator);
×
6039
    if (resBlock != NULL) {
×
6040
      (*ppRes) = resBlock;
×
6041
      return code;
×
6042
    }
6043

6044
    if (pInfo->clearState) {
×
6045
      pInfo->clearState = false;
×
6046
      clearFunctionContext(&pOperator->exprSupp);
×
6047
      clearStreamIntervalOperator(pInfo);
×
6048
    }
6049
  }
6050

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

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

6068
    SSDataBlock* pBlock = NULL;
×
6069
    code = downstream->fpSet.getNextFn(downstream, &pBlock);
×
6070
    QUERY_CHECK_CODE(code, lino, _end);
×
6071

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

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

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

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

6125
      if (pInfo->recvPullover) {
×
6126
        code = copyDataBlock(pInfo->pMidPulloverRes, pBlock);
×
6127
        QUERY_CHECK_CODE(code, lino, _end);
×
6128

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

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

6149
      code = addMidRetriveWindow(delWins, pInfo->pPullDataMap, pInfo->numOfChild);
×
6150
      QUERY_CHECK_CODE(code, lino, _end);
×
6151

6152
      taosArrayDestroy(delWins);
×
6153
      pInfo->recvRetrive = true;
×
6154
      code = copyDataBlock(pInfo->pMidRetriveRes, pBlock);
×
6155
      QUERY_CHECK_CODE(code, lino, _end);
×
6156

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

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

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

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

6193
  tSimpleHashCleanup(pInfo->pUpdatedMap);
×
6194
  pInfo->pUpdatedMap = NULL;
×
6195
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
×
6196

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

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

6210
  resBlock = buildMidIntervalResult(pOperator);
×
6211
  if (resBlock != NULL) {
×
6212
    (*ppRes) = resBlock;
×
6213
    return code;
×
6214
  }
6215

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

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

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

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