groupoperator.c 46.8 KB
Newer Older
H
Haojun Liao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

16
#include "filter.h"
H
Haojun Liao 已提交
17
#include "function.h"
18
#include "os.h"
H
Haojun Liao 已提交
19 20 21 22 23
#include "tname.h"

#include "tdatablock.h"
#include "tmsg.h"

24
#include "executorInt.h"
H
Haojun Liao 已提交
25 26 27 28 29
#include "executorimpl.h"
#include "tcompare.h"
#include "thash.h"
#include "ttypes.h"

H
Haojun Liao 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
typedef struct SGroupbyOperatorInfo {
  SOptrBasicInfo binfo;
  SAggSupporter  aggSup;
  SArray*        pGroupCols;     // group by columns, SArray<SColumn>
  SArray*        pGroupColVals;  // current group column values, SArray<SGroupKeys>
  bool           isInit;         // denote if current val is initialized or not
  char*          keyBuf;         // group by keys for hash
  int32_t        groupKeyLen;    // total group by column width
  SGroupResInfo  groupResInfo;
  SExprSupp      scalarSup;
} SGroupbyOperatorInfo;

// The sort in partition may be needed later.
typedef struct SPartitionOperatorInfo {
  SOptrBasicInfo binfo;
  SArray*        pGroupCols;
  SArray*        pGroupColVals;  // current group column values, SArray<SGroupKeys>
  char*          keyBuf;         // group by keys for hash
  int32_t        groupKeyLen;    // total group by column width
  SHashObj*      pGroupSet;      // quick locate the window object for each result

  SDiskbasedBuf* pBuf;              // query result buffer based on blocked-wised disk file
  int32_t        rowCapacity;       // maximum number of rows for each buffer page
  int32_t*       columnOffset;      // start position for each column data
  SArray*        sortedGroupArray;  // SDataGroupInfo sorted by group id
  int32_t        groupIndex;        // group index
  int32_t        pageIndex;         // page index of current group
  SExprSupp      scalarSup;
} SPartitionOperatorInfo;

60
static void*    getCurrentDataGroupInfo(const SPartitionOperatorInfo* pInfo, SDataGroupInfo** pGroupInfo, int32_t len);
H
Haojun Liao 已提交
61
static int32_t* setupColumnOffset(const SSDataBlock* pBlock, int32_t rowCapacity);
62 63
static int32_t  setGroupResultOutputBuf(SOperatorInfo* pOperator, SOptrBasicInfo* binfo, int32_t numOfCols, char* pData,
                                        int16_t bytes, uint64_t groupId, SDiskbasedBuf* pBuf, SAggSupporter* pAggSup);
H
Haojun Liao 已提交
64
static SArray*  extractColumnInfo(SNodeList* pNodeList);
H
Haojun Liao 已提交
65

H
Haojun Liao 已提交
66
static void freeGroupKey(void* param) {
67
  SGroupKeys* pKey = (SGroupKeys*)param;
H
Haojun Liao 已提交
68 69 70
  taosMemoryFree(pKey->pData);
}

71
static void destroyGroupOperatorInfo(void* param) {
H
Haojun Liao 已提交
72
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*)param;
73 74 75 76
  if (pInfo == NULL) {
    return;
  }

77
  cleanupBasicInfo(&pInfo->binfo);
H
Haojun Liao 已提交
78 79
  taosMemoryFreeClear(pInfo->keyBuf);
  taosArrayDestroy(pInfo->pGroupCols);
H
Haojun Liao 已提交
80
  taosArrayDestroyEx(pInfo->pGroupColVals, freeGroupKey);
81
  cleanupExprSupp(&pInfo->scalarSup);
H
Haojun Liao 已提交
82 83 84

  cleanupGroupResInfo(&pInfo->groupResInfo);
  cleanupAggSup(&pInfo->aggSup);
D
dapan1121 已提交
85
  taosMemoryFreeClear(param);
H
Haojun Liao 已提交
86 87
}

wmmhello's avatar
wmmhello 已提交
88
static int32_t initGroupOptrInfo(SArray** pGroupColVals, int32_t* keyLen, char** keyBuf, const SArray* pGroupColList) {
H
Haojun Liao 已提交
89 90
  *pGroupColVals = taosArrayInit(4, sizeof(SGroupKeys));
  if ((*pGroupColVals) == NULL) {
H
Haojun Liao 已提交
91 92 93 94 95
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  int32_t numOfGroupCols = taosArrayGetSize(pGroupColList);
  for (int32_t i = 0; i < numOfGroupCols; ++i) {
5
54liuyao 已提交
96
    SColumn* pCol = (SColumn*)taosArrayGet(pGroupColList, i);
97
    (*keyLen) += pCol->bytes;  // actual data + null_flag
H
Haojun Liao 已提交
98

99
    SGroupKeys key = {0};
100 101
    key.bytes = pCol->bytes;
    key.type = pCol->type;
H
Haojun Liao 已提交
102
    key.isNull = false;
103
    key.pData = taosMemoryCalloc(1, pCol->bytes);
H
Haojun Liao 已提交
104 105 106 107
    if (key.pData == NULL) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }

H
Haojun Liao 已提交
108
    taosArrayPush((*pGroupColVals), &key);
H
Haojun Liao 已提交
109 110 111
  }

  int32_t nullFlagSize = sizeof(int8_t) * numOfGroupCols;
112
  (*keyLen) += nullFlagSize;
H
Haojun Liao 已提交
113

114
  (*keyBuf) = taosMemoryCalloc(1, (*keyLen));
H
Haojun Liao 已提交
115
  if ((*keyBuf) == NULL) {
H
Haojun Liao 已提交
116 117 118 119 120 121
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  return TSDB_CODE_SUCCESS;
}

122 123
static bool groupKeyCompare(SArray* pGroupCols, SArray* pGroupColVals, SSDataBlock* pBlock, int32_t rowIndex,
                            int32_t numOfGroupCols) {
H
Haojun Liao 已提交
124 125
  SColumnDataAgg* pColAgg = NULL;
  for (int32_t i = 0; i < numOfGroupCols; ++i) {
H
Haojun Liao 已提交
126
    SColumn*         pCol = taosArrayGet(pGroupCols, i);
H
Haojun Liao 已提交
127 128
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pCol->slotId);
    if (pBlock->pBlockAgg != NULL) {
129
      pColAgg = pBlock->pBlockAgg[pCol->slotId];  // TODO is agg data matched?
H
Haojun Liao 已提交
130 131 132 133
    }

    bool isNull = colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg);

H
Haojun Liao 已提交
134
    SGroupKeys* pkey = taosArrayGet(pGroupColVals, i);
H
Haojun Liao 已提交
135 136 137 138 139 140 141 142 143 144
    if (pkey->isNull && isNull) {
      continue;
    }

    if (isNull || pkey->isNull) {
      return false;
    }

    char* val = colDataGetData(pColInfoData, rowIndex);

wmmhello's avatar
wmmhello 已提交
145 146 147
    if (pkey->type == TSDB_DATA_TYPE_JSON) {
      int32_t dataLen = getJsonValueLen(val);

148
      if (memcmp(pkey->pData, val, dataLen) == 0) {
wmmhello's avatar
wmmhello 已提交
149 150 151 152 153
        continue;
      } else {
        return false;
      }
    } else if (IS_VAR_DATA_TYPE(pkey->type)) {
H
Haojun Liao 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
      int32_t len = varDataLen(val);
      if (len == varDataLen(pkey->pData) && memcmp(varDataVal(pkey->pData), varDataVal(val), len) == 0) {
        continue;
      } else {
        return false;
      }
    } else {
      if (memcmp(pkey->pData, val, pkey->bytes) != 0) {
        return false;
      }
    }
  }

  return true;
}

wmmhello's avatar
wmmhello 已提交
170
static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSDataBlock* pBlock, int32_t rowIndex) {
H
Haojun Liao 已提交
171 172
  SColumnDataAgg* pColAgg = NULL;

173 174
  size_t numOfGroupCols = taosArrayGetSize(pGroupCols);

H
Haojun Liao 已提交
175
  for (int32_t i = 0; i < numOfGroupCols; ++i) {
H
Haojun Liao 已提交
176
    SColumn*         pCol = taosArrayGet(pGroupCols, i);
H
Haojun Liao 已提交
177 178 179
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pCol->slotId);

    if (pBlock->pBlockAgg != NULL) {
180
      pColAgg = pBlock->pBlockAgg[pCol->slotId];  // TODO is agg data matched?
H
Haojun Liao 已提交
181 182
    }

H
Haojun Liao 已提交
183
    SGroupKeys* pkey = taosArrayGet(pGroupColVals, i);
H
Haojun Liao 已提交
184 185 186
    if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) {
      pkey->isNull = true;
    } else {
187
      pkey->isNull = false;
H
Haojun Liao 已提交
188
      char* val = colDataGetData(pColInfoData, rowIndex);
wmmhello's avatar
wmmhello 已提交
189
      if (pkey->type == TSDB_DATA_TYPE_JSON) {
190
        if (tTagIsJson(val)) {
wmmhello's avatar
wmmhello 已提交
191 192 193
          terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
          return;
        }
wmmhello's avatar
wmmhello 已提交
194 195 196
        int32_t dataLen = getJsonValueLen(val);
        memcpy(pkey->pData, val, dataLen);
      } else if (IS_VAR_DATA_TYPE(pkey->type)) {
H
Haojun Liao 已提交
197
        memcpy(pkey->pData, val, varDataTLen(val));
198
        ASSERT(varDataTLen(val) <= pkey->bytes);
H
Haojun Liao 已提交
199 200 201 202 203 204 205
      } else {
        memcpy(pkey->pData, val, pkey->bytes);
      }
    }
  }
}

wmmhello's avatar
wmmhello 已提交
206
static int32_t buildGroupKeys(void* pKey, const SArray* pGroupColVals) {
207
  ASSERT(pKey != NULL);
H
Haojun Liao 已提交
208 209 210 211 212 213 214 215 216 217 218 219
  size_t numOfGroupCols = taosArrayGetSize(pGroupColVals);

  char* isNull = (char*)pKey;
  char* pStart = (char*)pKey + sizeof(int8_t) * numOfGroupCols;
  for (int32_t i = 0; i < numOfGroupCols; ++i) {
    SGroupKeys* pkey = taosArrayGet(pGroupColVals, i);
    if (pkey->isNull) {
      isNull[i] = 1;
      continue;
    }

    isNull[i] = 0;
wmmhello's avatar
wmmhello 已提交
220 221 222 223 224
    if (pkey->type == TSDB_DATA_TYPE_JSON) {
      int32_t dataLen = getJsonValueLen(pkey->pData);
      memcpy(pStart, (pkey->pData), dataLen);
      pStart += dataLen;
    } else if (IS_VAR_DATA_TYPE(pkey->type)) {
H
Haojun Liao 已提交
225 226
      varDataCopy(pStart, pkey->pData);
      pStart += varDataTLen(pkey->pData);
227
      ASSERT(varDataTLen(pkey->pData) <= pkey->bytes);
H
Haojun Liao 已提交
228 229 230 231 232 233
    } else {
      memcpy(pStart, pkey->pData, pkey->bytes);
      pStart += pkey->bytes;
    }
  }

234
  return (int32_t)(pStart - (char*)pKey);
H
Haojun Liao 已提交
235 236 237 238 239
}

// assign the group keys or user input constant values if required
static void doAssignGroupKeys(SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t totalRows, int32_t rowIndex) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
240
    if (pCtx[i].functionId == -1) {  // select count(*),key from t group by key.
H
Haojun Liao 已提交
241 242 243
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[i]);

      SColumnInfoData* pColInfoData = pCtx[i].input.pData[0];
244
      // todo OPT all/all not NULL
H
Haojun Liao 已提交
245 246 247 248
      if (!colDataIsNull(pColInfoData, totalRows, rowIndex, NULL)) {
        char* dest = GET_ROWCELL_INTERBUF(pEntryInfo);
        char* data = colDataGetData(pColInfoData, rowIndex);

wmmhello's avatar
wmmhello 已提交
249 250 251 252
        if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
          int32_t dataLen = getJsonValueLen(data);
          memcpy(dest, data, dataLen);
        } else if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
253 254 255 256
          varDataCopy(dest, data);
        } else {
          memcpy(dest, data, pColInfoData->info.bytes);
        }
257
      } else {  // it is a NULL value
H
Haojun Liao 已提交
258
        pEntryInfo->isNullRes = 1;
H
Haojun Liao 已提交
259
      }
H
Haojun Liao 已提交
260 261

      pEntryInfo->numOfRes = 1;
H
Haojun Liao 已提交
262 263 264 265 266 267 268 269
    }
  }
}

static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
  SExecTaskInfo*        pTaskInfo = pOperator->pTaskInfo;
  SGroupbyOperatorInfo* pInfo = pOperator->info;

270
  SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx;
H
Haojun Liao 已提交
271 272 273 274 275 276
  int32_t         numOfGroupCols = taosArrayGetSize(pInfo->pGroupCols);
  //  if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) {
  // qError("QInfo:0x%"PRIx64" group by not supported on double/float columns, abort", GET_TASKID(pRuntimeEnv));
  //    return;
  //  }

H
Haojun Liao 已提交
277
  int32_t len = 0;
wmmhello's avatar
wmmhello 已提交
278
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
279

H
Haojun Liao 已提交
280 281 282 283
  int32_t num = 0;
  for (int32_t j = 0; j < pBlock->info.rows; ++j) {
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
    if (!pInfo->isInit) {
284
      recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
wmmhello's avatar
wmmhello 已提交
285
      if (terrno != TSDB_CODE_SUCCESS) {  // group by json error
286
        T_LONG_JMP(pTaskInfo->env, terrno);
wmmhello's avatar
wmmhello 已提交
287
      }
H
Haojun Liao 已提交
288 289 290 291 292
      pInfo->isInit = true;
      num++;
      continue;
    }

H
Haojun Liao 已提交
293
    bool equal = groupKeyCompare(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j, numOfGroupCols);
H
Haojun Liao 已提交
294 295 296 297 298
    if (equal) {
      num++;
      continue;
    }

H
Haojun Liao 已提交
299
    // The first row of a new block does not belongs to the previous existed group
300
    if (j == 0) {
H
Haojun Liao 已提交
301
      num++;
302
      recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
wmmhello's avatar
wmmhello 已提交
303
      if (terrno != TSDB_CODE_SUCCESS) {  // group by json error
304
        T_LONG_JMP(pTaskInfo->env, terrno);
wmmhello's avatar
wmmhello 已提交
305
      }
H
Haojun Liao 已提交
306 307 308
      continue;
    }

H
Haojun Liao 已提交
309
    len = buildGroupKeys(pInfo->keyBuf, pInfo->pGroupColVals);
310
    int32_t ret = setGroupResultOutputBuf(pOperator, &(pInfo->binfo), pOperator->exprSupp.numOfExprs, pInfo->keyBuf,
H
Haojun Liao 已提交
311
                                          len, pBlock->info.id.groupId, pInfo->aggSup.pResultBuf, &pInfo->aggSup);
H
Haojun Liao 已提交
312
    if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
313
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
H
Haojun Liao 已提交
314 315 316
    }

    int32_t rowIndex = j - num;
dengyihao's avatar
dengyihao 已提交
317 318
    applyAggFunctionOnPartialTuples(pTaskInfo, pCtx, NULL, rowIndex, num, pBlock->info.rows,
                                    pOperator->exprSupp.numOfExprs);
H
Haojun Liao 已提交
319 320

    // assign the group keys or user input constant values if required
321
    doAssignGroupKeys(pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.rows, rowIndex);
322
    recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
H
Haojun Liao 已提交
323 324 325 326
    num = 1;
  }

  if (num > 0) {
H
Haojun Liao 已提交
327
    len = buildGroupKeys(pInfo->keyBuf, pInfo->pGroupColVals);
328
    int32_t ret = setGroupResultOutputBuf(pOperator, &(pInfo->binfo), pOperator->exprSupp.numOfExprs, pInfo->keyBuf,
H
Haojun Liao 已提交
329
                                          len, pBlock->info.id.groupId, pInfo->aggSup.pResultBuf, &pInfo->aggSup);
H
Haojun Liao 已提交
330
    if (ret != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
331
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
H
Haojun Liao 已提交
332 333 334
    }

    int32_t rowIndex = pBlock->info.rows - num;
dengyihao's avatar
dengyihao 已提交
335 336
    applyAggFunctionOnPartialTuples(pTaskInfo, pCtx, NULL, rowIndex, num, pBlock->info.rows,
                                    pOperator->exprSupp.numOfExprs);
337
    doAssignGroupKeys(pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.rows, rowIndex);
H
Haojun Liao 已提交
338 339 340
  }
}

341 342 343 344
static SSDataBlock* buildGroupResultDataBlock(SOperatorInfo* pOperator) {
  SGroupbyOperatorInfo* pInfo = pOperator->info;

  SSDataBlock* pRes = pInfo->binfo.pRes;
345
  while (1) {
346
    doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
347
    doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
348

349
    if (!hasRemainResults(&pInfo->groupResInfo)) {
H
Haojun Liao 已提交
350
      setOperatorCompleted(pOperator);
351 352 353 354 355 356 357 358 359
      break;
    }

    if (pRes->info.rows > 0) {
      break;
    }
  }

  pOperator->resultInfo.totalRows += pRes->info.rows;
360
  return (pRes->info.rows == 0) ? NULL : pRes;
361 362
}

363
static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) {
H
Haojun Liao 已提交
364 365 366 367
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

368 369
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;

H
Haojun Liao 已提交
370 371
  SGroupbyOperatorInfo* pInfo = pOperator->info;
  if (pOperator->status == OP_RES_TO_RETURN) {
372
    return buildGroupResultDataBlock(pOperator);
H
Haojun Liao 已提交
373 374
  }

375 376 377
  int32_t order = TSDB_ORDER_ASC;
  int32_t scanFlag = MAIN_SCAN;

378
  int64_t        st = taosGetTimestampUs();
H
Haojun Liao 已提交
379 380 381
  SOperatorInfo* downstream = pOperator->pDownstream[0];

  while (1) {
382
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
383 384 385 386
    if (pBlock == NULL) {
      break;
    }

387 388
    int32_t code = getTableScanInfo(pOperator, &order, &scanFlag);
    if (code != TSDB_CODE_SUCCESS) {
389
      T_LONG_JMP(pTaskInfo->env, code);
390 391
    }

H
Haojun Liao 已提交
392
    // the pDataBlock are always the same one, no need to call this again
393
    setInputDataBlock(&pOperator->exprSupp, pBlock, order, scanFlag, true);
394

395
    // there is an scalar expression that needs to be calculated right before apply the group aggregation.
396
    if (pInfo->scalarSup.pExprInfo != NULL) {
397 398
      pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
                                              pInfo->scalarSup.numOfExprs, NULL);
399
      if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
400
        T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
401
      }
402 403
    }

H
Haojun Liao 已提交
404 405 406 407
    doHashGroupbyAgg(pOperator, pBlock);
  }

  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
408

409 410 411 412 413 414 415 416 417 418 419 420 421 422
#if 0
  if(pOperator->fpSet.encodeResultRow){
    char *result = NULL;
    int32_t length = 0;
    pOperator->fpSet.encodeResultRow(pOperator, &result, &length);
    SAggSupporter* pSup = &pInfo->aggSup;
    taosHashClear(pSup->pResultRowHashTable);
    pInfo->binfo.resultRowInfo.size = 0;
    pOperator->fpSet.decodeResultRow(pOperator, result);
    if(result){
      taosMemoryFree(result);
    }
  }
#endif
423
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, 0);
424

425
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
426
  return buildGroupResultDataBlock(pOperator);
H
Haojun Liao 已提交
427 428
}

5
54liuyao 已提交
429
SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, SExecTaskInfo* pTaskInfo) {
H
Haojun Liao 已提交
430 431 432 433 434 435
  SGroupbyOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SGroupbyOperatorInfo));
  SOperatorInfo*        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

H
Haojun Liao 已提交
436
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pAggNode->node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
437 438 439 440 441 442 443 444 445
  initBasicInfo(&pInfo->binfo, pResBlock);

  int32_t    numOfScalarExpr = 0;
  SExprInfo* pScalarExprInfo = NULL;
  if (pAggNode->pExprs != NULL) {
    pScalarExprInfo = createExprInfo(pAggNode->pExprs, NULL, &numOfScalarExpr);
  }

  pInfo->pGroupCols = extractColumnInfo(pAggNode->pGroupKeys);
446 447 448 449
  int32_t code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
450

H
Haojun Liao 已提交
451
  initResultSizeInfo(&pOperator->resultInfo, 4096);
H
Haojun Liao 已提交
452 453
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);

H
Haojun Liao 已提交
454
  code = initGroupOptrInfo(&pInfo->pGroupColVals, &pInfo->groupKeyLen, &pInfo->keyBuf, pInfo->pGroupCols);
H
Haojun Liao 已提交
455 456 457 458
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
459 460
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pAggNode->pAggFuncs, pAggNode->pGroupKeys, &num);
L
Liu Jicong 已提交
461 462
  code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, pInfo->groupKeyLen, pTaskInfo->id.str,
                    pTaskInfo->streamInfo.pState);
463 464 465 466
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

467 468 469 470 471
  code = filterInitFromNode((SNode*)pAggNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

472
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
473
  setOperatorInfo(pOperator, "GroupbyAggOperator", 0, true, OP_NOT_OPENED, pInfo, pTaskInfo);
H
Haojun Liao 已提交
474

dengyihao's avatar
dengyihao 已提交
475 476
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, hashGroupbyAggregate, NULL, destroyGroupOperatorInfo,
                                         optrDefaultBufFn, NULL);
H
Haojun Liao 已提交
477
  code = appendDownstream(pOperator, &downstream, 1);
478 479 480 481
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
482 483
  return pOperator;

484
_error:
H
Haojun Liao 已提交
485
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
H
Haojun Liao 已提交
486 487 488
  if (pInfo != NULL) {
    destroyGroupOperatorInfo(pInfo);
  }
H
Haojun Liao 已提交
489 490
  taosMemoryFreeClear(pOperator);
  return NULL;
491 492
}

H
Haojun Liao 已提交
493 494
static void doHashPartition(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
  SPartitionOperatorInfo* pInfo = pOperator->info;
dengyihao's avatar
dengyihao 已提交
495 496
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;

H
Haojun Liao 已提交
497
  for (int32_t j = 0; j < pBlock->info.rows; ++j) {
498
    recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
H
Haojun Liao 已提交
499 500
    int32_t len = buildGroupKeys(pInfo->keyBuf, pInfo->pGroupColVals);

501
    SDataGroupInfo* pGroupInfo = NULL;
502
    void*           pPage = getCurrentDataGroupInfo(pInfo, &pGroupInfo, len);
503 504 505
    if (pPage == NULL) {
      T_LONG_JMP(pTaskInfo->env, terrno);
    }
H
Haojun Liao 已提交
506

507 508 509 510 511
    pGroupInfo->numOfRows += 1;

    // group id
    if (pGroupInfo->groupId == 0) {
      pGroupInfo->groupId = calcGroupId(pInfo->keyBuf, len);
H
Haojun Liao 已提交
512 513
    }

514
    // number of rows
515
    int32_t* rows = (int32_t*)pPage;
H
Haojun Liao 已提交
516

517
    size_t numOfCols = pOperator->exprSupp.numOfExprs;
518
    for (int32_t i = 0; i < numOfCols; ++i) {
519
      SExprInfo* pExpr = &pOperator->exprSupp.pExprInfo[i];
520
      int32_t    slotId = pExpr->base.pParam[0].pCol->slotId;
521 522

      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
H
Haojun Liao 已提交
523

H
Haojun Liao 已提交
524 525
      int32_t bytes = pColInfoData->info.bytes;
      int32_t startOffset = pInfo->columnOffset[i];
H
Haojun Liao 已提交
526

527
      int32_t* columnLen = NULL;
528
      int32_t  contentLen = 0;
H
Haojun Liao 已提交
529 530

      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
wafwerar's avatar
wafwerar 已提交
531
        int32_t* offset = (int32_t*)((char*)pPage + startOffset);
532 533
        columnLen = (int32_t*)((char*)pPage + startOffset + sizeof(int32_t) * pInfo->rowCapacity);
        char* data = (char*)((char*)columnLen + sizeof(int32_t));
H
Haojun Liao 已提交
534 535 536 537

        if (colDataIsNull_s(pColInfoData, j)) {
          offset[(*rows)] = -1;
          contentLen = 0;
538
        } else if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
wmmhello's avatar
wmmhello 已提交
539
          offset[*rows] = (*columnLen);
540
          char*   src = colDataGetData(pColInfoData, j);
wmmhello's avatar
wmmhello 已提交
541 542 543 544
          int32_t dataLen = getJsonValueLen(src);

          memcpy(data + (*columnLen), src, dataLen);
          int32_t v = (data + (*columnLen) + dataLen - (char*)pPage);
545
          ASSERT(v > 0);
wmmhello's avatar
wmmhello 已提交
546 547

          contentLen = dataLen;
H
Haojun Liao 已提交
548 549 550 551
        } else {
          offset[*rows] = (*columnLen);
          char* src = colDataGetData(pColInfoData, j);
          memcpy(data + (*columnLen), src, varDataTLen(src));
552
          int32_t v = (data + (*columnLen) + varDataTLen(src) - (char*)pPage);
553
          ASSERT(v > 0);
554

H
Haojun Liao 已提交
555 556
          contentLen = varDataTLen(src);
        }
H
Haojun Liao 已提交
557
      } else {
wafwerar's avatar
wafwerar 已提交
558
        char* bitmap = (char*)pPage + startOffset;
559 560
        columnLen = (int32_t*)((char*)pPage + startOffset + BitmapLen(pInfo->rowCapacity));
        char* data = (char*)columnLen + sizeof(int32_t);
H
Haojun Liao 已提交
561 562 563

        bool isNull = colDataIsNull_f(pColInfoData->nullbitmap, j);
        if (isNull) {
H
Haojun Liao 已提交
564
          colDataSetNull_f(bitmap, (*rows));
H
Haojun Liao 已提交
565
        } else {
H
Haojun Liao 已提交
566
          memcpy(data + (*columnLen), colDataGetData(pColInfoData, j), bytes);
567
          ASSERT((data + (*columnLen) + bytes - (char*)pPage) <= getBufPageSize(pInfo->pBuf));
H
Haojun Liao 已提交
568
        }
H
Haojun Liao 已提交
569
        contentLen = bytes;
H
Haojun Liao 已提交
570
      }
H
Haojun Liao 已提交
571 572

      (*columnLen) += contentLen;
573
      ASSERT(*columnLen >= 0);
H
Haojun Liao 已提交
574 575
    }

H
Haojun Liao 已提交
576 577
    (*rows) += 1;

H
Haojun Liao 已提交
578 579 580
    setBufPageDirty(pPage, true);
    releaseBufPage(pInfo->pBuf, pPage);
  }
H
Haojun Liao 已提交
581 582 583 584 585 586
}

void* getCurrentDataGroupInfo(const SPartitionOperatorInfo* pInfo, SDataGroupInfo** pGroupInfo, int32_t len) {
  SDataGroupInfo* p = taosHashGet(pInfo->pGroupSet, pInfo->keyBuf, len);

  void* pPage = NULL;
587
  if (p == NULL) {  // it is a new group
H
Haojun Liao 已提交
588 589 590 591 592 593 594
    SDataGroupInfo gi = {0};
    gi.pPageList = taosArrayInit(100, sizeof(int32_t));
    taosHashPut(pInfo->pGroupSet, pInfo->keyBuf, len, &gi, sizeof(SDataGroupInfo));

    p = taosHashGet(pInfo->pGroupSet, pInfo->keyBuf, len);

    int32_t pageId = 0;
595
    pPage = getNewBufPage(pInfo->pBuf, &pageId);
596 597 598
    if (pPage == NULL) {
      return pPage;
    }
H
Haojun Liao 已提交
599

600
    taosArrayPush(p->pPageList, &pageId);
601
    *(int32_t*)pPage = 0;
H
Haojun Liao 已提交
602 603 604
  } else {
    int32_t* curId = taosArrayGetLast(p->pPageList);
    pPage = getBufPage(pInfo->pBuf, *curId);
605 606 607 608
    if (pPage == NULL) {
      qError("failed to get buffer, code:%s", tstrerror(terrno));
      return pPage;
    }
H
Haojun Liao 已提交
609

610
    int32_t* rows = (int32_t*)pPage;
H
Haojun Liao 已提交
611
    if (*rows >= pInfo->rowCapacity) {
612 613 614
      // release buffer
      releaseBufPage(pInfo->pBuf, pPage);

H
Haojun Liao 已提交
615 616
      // add a new page for current group
      int32_t pageId = 0;
617
      pPage = getNewBufPage(pInfo->pBuf, &pageId);
618 619 620 621 622
      if (pPage == NULL) {
        qError("failed to get new buffer, code:%s", tstrerror(terrno));
        return NULL;
      }

H
Haojun Liao 已提交
623
      taosArrayPush(p->pPageList, &pageId);
624
      memset(pPage, 0, getBufPageSize(pInfo->pBuf));
H
Haojun Liao 已提交
625 626
    }
  }
H
Haojun Liao 已提交
627

H
Haojun Liao 已提交
628 629 630 631 632 633 634 635 636 637 638 639 640 641
  *pGroupInfo = p;
  return pPage;
}

uint64_t calcGroupId(char* pData, int32_t len) {
  T_MD5_CTX context;
  tMD5Init(&context);
  tMD5Update(&context, (uint8_t*)pData, len);
  tMD5Final(&context);

  // NOTE: only extract the initial 8 bytes of the final MD5 digest
  uint64_t id = 0;
  memcpy(&id, context.digest, sizeof(uint64_t));
  return id;
H
Haojun Liao 已提交
642 643
}

H
Haojun Liao 已提交
644
int32_t* setupColumnOffset(const SSDataBlock* pBlock, int32_t rowCapacity) {
645
  size_t   numOfCols = taosArrayGetSize(pBlock->pDataBlock);
646
  int32_t* offset = taosMemoryCalloc(numOfCols, sizeof(int32_t));
H
Haojun Liao 已提交
647

648 649
  offset[0] = sizeof(int32_t) +
              sizeof(uint64_t);  // the number of rows in current page, ref to SSDataBlock paged serialization format
H
Haojun Liao 已提交
650

651
  for (int32_t i = 0; i < numOfCols - 1; ++i) {
H
Haojun Liao 已提交
652 653 654 655
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);

    int32_t bytes = pColInfoData->info.bytes;
    int32_t payloadLen = bytes * rowCapacity;
656

H
Haojun Liao 已提交
657 658 659 660 661 662 663 664 665 666 667 668
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
      // offset segment + content length + payload
      offset[i + 1] = rowCapacity * sizeof(int32_t) + sizeof(int32_t) + payloadLen + offset[i];
    } else {
      // bitmap + content length + payload
      offset[i + 1] = BitmapLen(rowCapacity) + sizeof(int32_t) + payloadLen + offset[i];
    }
  }

  return offset;
}

5
54liuyao 已提交
669
static void clearPartitionOperator(SPartitionOperatorInfo* pInfo) {
670 671 672 673
  int32_t size = taosArrayGetSize(pInfo->sortedGroupArray);
  for (int32_t i = 0; i < size; i++) {
    SDataGroupInfo* pGp = taosArrayGet(pInfo->sortedGroupArray, i);
    taosArrayDestroy(pGp->pPageList);
5
54liuyao 已提交
674
  }
675
  taosArrayClear(pInfo->sortedGroupArray);
5
54liuyao 已提交
676 677 678
  clearDiskbasedBuf(pInfo->pBuf);
}

679 680 681
static int compareDataGroupInfo(const void* group1, const void* group2) {
  const SDataGroupInfo* pGroupInfo1 = group1;
  const SDataGroupInfo* pGroupInfo2 = group2;
682 683

  if (pGroupInfo1->groupId == pGroupInfo2->groupId) {
684
    ASSERT(0);
685 686 687
    return 0;
  }

688
  return (pGroupInfo1->groupId < pGroupInfo2->groupId) ? -1 : 1;
689 690
}

H
Haojun Liao 已提交
691 692
static SSDataBlock* buildPartitionResult(SOperatorInfo* pOperator) {
  SPartitionOperatorInfo* pInfo = pOperator->info;
dengyihao's avatar
dengyihao 已提交
693 694
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;

695 696
  SDataGroupInfo* pGroupInfo =
      (pInfo->groupIndex != -1) ? taosArrayGet(pInfo->sortedGroupArray, pInfo->groupIndex) : NULL;
697
  if (pInfo->groupIndex == -1 || pInfo->pageIndex >= taosArrayGetSize(pGroupInfo->pPageList)) {
H
Haojun Liao 已提交
698
    // try next group data
699 700
    ++pInfo->groupIndex;
    if (pInfo->groupIndex >= taosArrayGetSize(pInfo->sortedGroupArray)) {
H
Haojun Liao 已提交
701
      setOperatorCompleted(pOperator);
5
54liuyao 已提交
702
      clearPartitionOperator(pInfo);
H
Haojun Liao 已提交
703 704 705
      return NULL;
    }

706
    pGroupInfo = taosArrayGet(pInfo->sortedGroupArray, pInfo->groupIndex);
H
Haojun Liao 已提交
707 708 709 710
    pInfo->pageIndex = 0;
  }

  int32_t* pageId = taosArrayGet(pGroupInfo->pPageList, pInfo->pageIndex);
711
  void*    page = getBufPage(pInfo->pBuf, *pageId);
712 713 714 715
  if (page == NULL) {
    qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo));
    T_LONG_JMP(pTaskInfo->env, terrno);
  }
dengyihao's avatar
dengyihao 已提交
716

717
  blockDataEnsureCapacity(pInfo->binfo.pRes, pInfo->rowCapacity);
H
Haojun Liao 已提交
718
  blockDataFromBuf1(pInfo->binfo.pRes, page, pInfo->rowCapacity);
H
Haojun Liao 已提交
719 720

  pInfo->pageIndex += 1;
721
  releaseBufPage(pInfo->pBuf, page);
H
Haojun Liao 已提交
722

723
  pInfo->binfo.pRes->info.dataLoad = 1;
724
  blockDataUpdateTsWindow(pInfo->binfo.pRes, 0);
H
Haojun Liao 已提交
725
  pInfo->binfo.pRes->info.id.groupId = pGroupInfo->groupId;
726 727

  pOperator->resultInfo.totalRows += pInfo->binfo.pRes->info.rows;
H
Haojun Liao 已提交
728 729 730
  return pInfo->binfo.pRes;
}

731
static SSDataBlock* hashPartition(SOperatorInfo* pOperator) {
H
Haojun Liao 已提交
732 733
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
734 735
  }

736 737 738
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;

  SPartitionOperatorInfo* pInfo = pOperator->info;
739
  SSDataBlock*            pRes = pInfo->binfo.pRes;
740

H
Haojun Liao 已提交
741
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
742 743
    blockDataCleanup(pRes);
    return buildPartitionResult(pOperator);
H
Haojun Liao 已提交
744 745
  }

746
  int64_t        st = taosGetTimestampUs();
H
Haojun Liao 已提交
747
  SOperatorInfo* downstream = pOperator->pDownstream[0];
H
Haojun Liao 已提交
748

H
Haojun Liao 已提交
749
  while (1) {
750
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
751 752 753
    if (pBlock == NULL) {
      break;
    }
H
Haojun Liao 已提交
754

755
    // there is an scalar expression that needs to be calculated right before apply the group aggregation.
756
    if (pInfo->scalarSup.pExprInfo != NULL) {
757 758
      pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
                                              pInfo->scalarSup.numOfExprs, NULL);
759
      if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
760
        T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
761 762 763
      }
    }

wmmhello's avatar
wmmhello 已提交
764
    terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
765
    doHashPartition(pOperator, pBlock);
wmmhello's avatar
wmmhello 已提交
766
    if (terrno != TSDB_CODE_SUCCESS) {  // group by json error
767
      T_LONG_JMP(pTaskInfo->env, terrno);
wmmhello's avatar
wmmhello 已提交
768
    }
H
Haojun Liao 已提交
769 770
  }

771
  SArray* groupArray = taosArrayInit(taosHashGetSize(pInfo->pGroupSet), sizeof(SDataGroupInfo));
772 773

  void* pGroupIter = taosHashIterate(pInfo->pGroupSet, NULL);
774 775 776 777 778 779 780 781 782 783 784
  while (pGroupIter != NULL) {
    SDataGroupInfo* pGroupInfo = pGroupIter;
    taosArrayPush(groupArray, pGroupInfo);
    pGroupIter = taosHashIterate(pInfo->pGroupSet, pGroupIter);
  }

  taosArraySort(groupArray, compareDataGroupInfo);
  pInfo->sortedGroupArray = groupArray;
  pInfo->groupIndex = -1;
  taosHashClear(pInfo->pGroupSet);

785 786
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;

H
Haojun Liao 已提交
787
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
788 789 790 791
  blockDataEnsureCapacity(pRes, 4096);
  return buildPartitionResult(pOperator);
}

792
static void destroyPartitionOperatorInfo(void* param) {
H
Haojun Liao 已提交
793
  SPartitionOperatorInfo* pInfo = (SPartitionOperatorInfo*)param;
794
  cleanupBasicInfo(&pInfo->binfo);
H
Haojun Liao 已提交
795
  taosArrayDestroy(pInfo->pGroupCols);
796

797
  for (int i = 0; i < taosArrayGetSize(pInfo->pGroupColVals); i++) {
wmmhello's avatar
wmmhello 已提交
798 799 800
    SGroupKeys key = *(SGroupKeys*)taosArrayGet(pInfo->pGroupColVals, i);
    taosMemoryFree(key.pData);
  }
801

H
Haojun Liao 已提交
802
  taosArrayDestroy(pInfo->pGroupColVals);
H
Haojun Liao 已提交
803
  taosMemoryFree(pInfo->keyBuf);
dengyihao's avatar
dengyihao 已提交
804 805 806 807 808 809

  int32_t size = taosArrayGetSize(pInfo->sortedGroupArray);
  for (int32_t i = 0; i < size; i++) {
    SDataGroupInfo* pGp = taosArrayGet(pInfo->sortedGroupArray, i);
    taosArrayDestroy(pGp->pPageList);
  }
810
  taosArrayDestroy(pInfo->sortedGroupArray);
D
dapan1121 已提交
811 812 813 814 815 816 817 818

  void* pGroupIter = taosHashIterate(pInfo->pGroupSet, NULL);
  while (pGroupIter != NULL) {
    SDataGroupInfo* pGroupInfo = pGroupIter;
    taosArrayDestroy(pGroupInfo->pPageList);
    pGroupIter = taosHashIterate(pInfo->pGroupSet, pGroupIter);
  }

wmmhello's avatar
wmmhello 已提交
819
  taosHashCleanup(pInfo->pGroupSet);
H
Haojun Liao 已提交
820
  taosMemoryFree(pInfo->columnOffset);
821

822
  cleanupExprSupp(&pInfo->scalarSup);
H
Haojun Liao 已提交
823
  destroyDiskbasedBuf(pInfo->pBuf);
D
dapan1121 已提交
824
  taosMemoryFreeClear(param);
H
Haojun Liao 已提交
825 826
}

827 828
SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNode* pPartNode,
                                           SExecTaskInfo* pTaskInfo) {
H
Haojun Liao 已提交
829
  SPartitionOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SPartitionOperatorInfo));
830
  SOperatorInfo*          pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
831
  if (pInfo == NULL || pOperator == NULL) {
dengyihao's avatar
dengyihao 已提交
832 833
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    pTaskInfo->code = terrno;
H
Haojun Liao 已提交
834 835
    goto _error;
  }
836

837
  int32_t    numOfCols = 0;
838 839 840 841
  SExprInfo* pExprInfo = createExprInfo(pPartNode->pTargets, NULL, &numOfCols);
  pInfo->pGroupCols = extractPartitionColInfo(pPartNode->pPartitionKeys);

  if (pPartNode->pExprs != NULL) {
842
    int32_t    num = 0;
843
    SExprInfo* pExprInfo1 = createExprInfo(pPartNode->pExprs, NULL, &num);
844
    int32_t    code = initExprSupp(&pInfo->scalarSup, pExprInfo1, num);
845
    if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
846 847
      terrno = code;
      pTaskInfo->code = terrno;
848 849
      goto _error;
    }
850
  }
H
Haojun Liao 已提交
851 852 853 854

  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
  pInfo->pGroupSet = taosHashInit(100, hashFn, false, HASH_NO_LOCK);
  if (pInfo->pGroupSet == NULL) {
dengyihao's avatar
dengyihao 已提交
855 856
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    pTaskInfo->code = terrno;
H
Haojun Liao 已提交
857 858 859
    goto _error;
  }

860
  uint32_t defaultPgsz = 0;
861
  uint32_t defaultBufsz = 0;
H
Haojun Liao 已提交
862

H
Haojun Liao 已提交
863
  pInfo->binfo.pRes = createDataBlockFromDescNode(pPartNode->node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
864
  getBufferPgSize(pInfo->binfo.pRes->info.rowSize, &defaultPgsz, &defaultBufsz);
865

wafwerar's avatar
wafwerar 已提交
866 867 868 869 870 871
  if (!osTempSpaceAvailable()) {
    terrno = TSDB_CODE_NO_AVAIL_DISK;
    pTaskInfo->code = terrno;
    qError("Create partition operator info failed since %s", terrstr(terrno));
    goto _error;
  }
H
Haojun Liao 已提交
872

wafwerar's avatar
wafwerar 已提交
873
  int32_t code = createDiskbasedBuf(&pInfo->pBuf, defaultPgsz, defaultBufsz, pTaskInfo->id.str, tsTempDir);
H
Haojun Liao 已提交
874
  if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
875 876
    terrno = code;
    pTaskInfo->code = code;
H
Haojun Liao 已提交
877 878 879
    goto _error;
  }

H
Haojun Liao 已提交
880 881
  pInfo->rowCapacity = blockDataGetCapacityInRow(pInfo->binfo.pRes, getBufPageSize(pInfo->pBuf));
  pInfo->columnOffset = setupColumnOffset(pInfo->binfo.pRes, pInfo->rowCapacity);
882
  code = initGroupOptrInfo(&pInfo->pGroupColVals, &pInfo->groupKeyLen, &pInfo->keyBuf, pInfo->pGroupCols);
H
Haojun Liao 已提交
883
  if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
884 885
    terrno = code;
    pTaskInfo->code = code;
H
Haojun Liao 已提交
886 887
    goto _error;
  }
H
Haojun Liao 已提交
888

L
Liu Jicong 已提交
889 890
  setOperatorInfo(pOperator, "PartitionOperator", QUERY_NODE_PHYSICAL_PLAN_PARTITION, false, OP_NOT_OPENED, pInfo,
                  pTaskInfo);
891 892
  pOperator->exprSupp.numOfExprs = numOfCols;
  pOperator->exprSupp.pExprInfo = pExprInfo;
893

dengyihao's avatar
dengyihao 已提交
894 895
  pOperator->fpSet =
      createOperatorFpSet(optrDummyOpenFn, hashPartition, NULL, destroyPartitionOperatorInfo, optrDefaultBufFn, NULL);
H
Haojun Liao 已提交
896

H
Haojun Liao 已提交
897
  code = appendDownstream(pOperator, &downstream, 1);
dengyihao's avatar
dengyihao 已提交
898 899 900 901 902 903
  if (code != TSDB_CODE_SUCCESS) {
    terrno = code;
    pTaskInfo->code = code;
    goto _error;
  }

904 905
  return pOperator;

906
_error:
H
Haojun Liao 已提交
907 908 909
  if (pInfo != NULL) {
    destroyPartitionOperatorInfo(pInfo);
  }
H
Haojun Liao 已提交
910
  taosMemoryFreeClear(pOperator);
911
  return NULL;
912 913
}

914 915 916
int32_t setGroupResultOutputBuf(SOperatorInfo* pOperator, SOptrBasicInfo* binfo, int32_t numOfCols, char* pData,
                                int16_t bytes, uint64_t groupId, SDiskbasedBuf* pBuf, SAggSupporter* pAggSup) {
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
917
  SResultRowInfo* pResultRowInfo = &binfo->resultRowInfo;
918
  SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx;
919 920 921 922 923

  SResultRow* pResultRow =
      doSetResultOutBufByKey(pBuf, pResultRowInfo, (char*)pData, bytes, true, groupId, pTaskInfo, false, pAggSup);
  assert(pResultRow != NULL);

924
  setResultRowInitCtx(pResultRow, pCtx, numOfCols, pOperator->exprSupp.rowEntryInfoOffset);
925
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
926
}
927 928 929

uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t rowId) {
  if (pExprSup->pExprInfo != NULL) {
930 931
    int32_t code =
        projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
932 933 934 935 936
    if (code != TSDB_CODE_SUCCESS) {
      qError("calaculate group id error, code:%d", code);
    }
  }
  recordNewGroupKeys(pParSup->pGroupCols, pParSup->pGroupColVals, pBlock, rowId);
937
  int32_t  len = buildGroupKeys(pParSup->keyBuf, pParSup->pGroupColVals);
938 939 940 941
  uint64_t groupId = calcGroupId(pParSup->keyBuf, len);
  return groupId;
}

942
static bool hasRemainPartion(SStreamPartitionOperatorInfo* pInfo) { return pInfo->parIte != NULL; }
5
54liuyao 已提交
943
static bool hasRemainTbName(SStreamPartitionOperatorInfo* pInfo) { return pInfo->pTbNameIte != NULL; }
944 945 946

static SSDataBlock* buildStreamPartitionResult(SOperatorInfo* pOperator) {
  SStreamPartitionOperatorInfo* pInfo = pOperator->info;
947
  SSDataBlock*                  pDest = pInfo->binfo.pRes;
948
  ASSERT(hasRemainPartion(pInfo));
949 950
  SPartitionDataInfo* pParInfo = (SPartitionDataInfo*)pInfo->parIte;
  blockDataCleanup(pDest);
951
  int32_t      rows = taosArrayGetSize(pParInfo->rowIds);
952 953 954 955
  SSDataBlock* pSrc = pInfo->pInputDataBlock;
  for (int32_t i = 0; i < rows; i++) {
    int32_t rowIndex = *(int32_t*)taosArrayGet(pParInfo->rowIds, i);
    for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; j++) {
956
      int32_t          slotId = pOperator->exprSupp.pExprInfo[j].base.pParam[0].pCol->slotId;
957 958
      SColumnInfoData* pSrcCol = taosArrayGet(pSrc->pDataBlock, slotId);
      SColumnInfoData* pDestCol = taosArrayGet(pDest->pDataBlock, j);
959 960
      bool             isNull = colDataIsNull(pSrcCol, pSrc->info.rows, rowIndex, NULL);
      char*            pSrcData = colDataGetData(pSrcCol, rowIndex);
961 962 963
      colDataAppend(pDestCol, pDest->info.rows, pSrcData, isNull);
    }
    pDest->info.rows++;
5
54liuyao 已提交
964 965 966 967 968 969 970
  }
  pDest->info.parTbName[0] = 0;
  if (pInfo->tbnameCalSup.numOfExprs > 0) {
    void* tbname = NULL;
    if (streamStateGetParName(pOperator->pTaskInfo->streamInfo.pState, pParInfo->groupId, &tbname) == 0) {
      memcpy(pDest->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
      tdbFree(tbname);
971
    }
972
  }
973 974
  taosArrayDestroy(pParInfo->rowIds);
  pParInfo->rowIds = NULL;
H
Haojun Liao 已提交
975 976
  pDest->info.dataLoad = 1;

977
  blockDataUpdateTsWindow(pDest, pInfo->tsColIndex);
H
Haojun Liao 已提交
978
  pDest->info.id.groupId = pParInfo->groupId;
979 980
  pOperator->resultInfo.totalRows += pDest->info.rows;
  pInfo->parIte = taosHashIterate(pInfo->pPartitions, pInfo->parIte);
981
  ASSERT(pDest->info.rows > 0);
982 983 984 985
  printDataBlock(pDest, "stream partitionby");
  return pDest;
}

5
54liuyao 已提交
986 987 988
void appendCreateTableRow(SStreamState* pState, SExprSupp* pTableSup, SExprSupp* pTagSup, int64_t groupId,
                          SSDataBlock* pSrcBlock, int32_t rowId, SSDataBlock* pDestBlock) {
  void* pValue = NULL;
5
54liuyao 已提交
989
  if (streamStateGetParName(pState, groupId, &pValue) != 0) {
5
54liuyao 已提交
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
    SSDataBlock* pTmpBlock = blockCopyOneRow(pSrcBlock, rowId);
    if (pTableSup->numOfExprs > 0) {
      projectApplyFunctions(pTableSup->pExprInfo, pDestBlock, pTmpBlock, pTableSup->pCtx, pTableSup->numOfExprs, NULL);
      SColumnInfoData* pTbCol = taosArrayGet(pDestBlock->pDataBlock, UD_TABLE_NAME_COLUMN_INDEX);
      void* pData = colDataGetVarData(pTbCol, pDestBlock->info.rows - 1);
      char* tbName = pSrcBlock->info.parTbName;
      memset(tbName, 0, TSDB_TABLE_NAME_LEN);
      int32_t len = TMIN(varDataLen(pData), TSDB_TABLE_NAME_LEN - 1);
      memcpy(tbName, varDataVal(pData), len);
      streamStatePutParName(pState, groupId, tbName);
      pDestBlock->info.rows--;
    } else {
      void* pTbNameCol = taosArrayGet(pDestBlock->pDataBlock, UD_TABLE_NAME_COLUMN_INDEX);
      colDataAppendNULL(pTbNameCol, pDestBlock->info.rows);
      pSrcBlock->info.parTbName[0] = 0;
    }

    if (pTagSup->numOfExprs > 0) {
      projectApplyFunctions(pTagSup->pExprInfo, pDestBlock, pTmpBlock, pTagSup->pCtx, pTagSup->numOfExprs, NULL);
      pDestBlock->info.rows--;
    }

    void* pGpIdCol = taosArrayGet(pDestBlock->pDataBlock, UD_GROUPID_COLUMN_INDEX);
    colDataAppend(pGpIdCol, pDestBlock->info.rows, (const char*)&groupId, false);
  
    pDestBlock->info.rows++;
    blockDataDestroy(pTmpBlock);
  }
  streamStateReleaseBuf(pState, NULL, pValue);
}

static SSDataBlock* buildStreamCreateTableResult(SOperatorInfo* pOperator) {
  SStreamPartitionOperatorInfo* pInfo = pOperator->info;
  if ( (pInfo->tbnameCalSup.numOfExprs == 0 && pInfo->tagCalSup.numOfExprs == 0) || taosHashGetSize(pInfo->pPartitions) == 0) {
    return NULL;
  }
  blockDataCleanup(pInfo->pCreateTbRes);
  blockDataEnsureCapacity(pInfo->pCreateTbRes, taosHashGetSize(pInfo->pPartitions));
  SSDataBlock* pSrc = pInfo->pInputDataBlock;

  while (pInfo->pTbNameIte != NULL) {
    SPartitionDataInfo* pParInfo = (SPartitionDataInfo*)pInfo->pTbNameIte;
    int32_t rowId = *(int32_t*) taosArrayGet(pParInfo->rowIds, 0);
    appendCreateTableRow(pOperator->pTaskInfo->streamInfo.pState, &pInfo->tbnameCalSup, &pInfo->tagCalSup,
                          pParInfo->groupId, pSrc, rowId, pInfo->pCreateTbRes);
    pInfo->pTbNameIte = taosHashIterate(pInfo->pPartitions, pInfo->pTbNameIte);
  }
  return pInfo->pCreateTbRes->info.rows > 0 ? pInfo->pCreateTbRes : NULL;
}

1040 1041 1042 1043
static void doStreamHashPartitionImpl(SStreamPartitionOperatorInfo* pInfo, SSDataBlock* pBlock) {
  pInfo->pInputDataBlock = pBlock;
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
    recordNewGroupKeys(pInfo->partitionSup.pGroupCols, pInfo->partitionSup.pGroupColVals, pBlock, i);
1044 1045 1046
    int32_t             keyLen = buildGroupKeys(pInfo->partitionSup.keyBuf, pInfo->partitionSup.pGroupColVals);
    SPartitionDataInfo* pParData =
        (SPartitionDataInfo*)taosHashGet(pInfo->pPartitions, pInfo->partitionSup.keyBuf, keyLen);
1047 1048 1049 1050 1051 1052 1053
    if (pParData) {
      taosArrayPush(pParData->rowIds, &i);
    } else {
      SPartitionDataInfo newParData = {0};
      newParData.groupId = calcGroupId(pInfo->partitionSup.keyBuf, keyLen);
      newParData.rowIds = taosArrayInit(64, sizeof(int32_t));
      taosArrayPush(newParData.rowIds, &i);
1054
      taosHashPut(pInfo->pPartitions, pInfo->partitionSup.keyBuf, keyLen, &newParData, sizeof(SPartitionDataInfo));
1055 1056 1057 1058 1059 1060 1061 1062 1063
    }
  }
}

static SSDataBlock* doStreamHashPartition(SOperatorInfo* pOperator) {
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

1064
  SExecTaskInfo*                pTaskInfo = pOperator->pTaskInfo;
1065
  SStreamPartitionOperatorInfo* pInfo = pOperator->info;
5
54liuyao 已提交
1066 1067 1068 1069 1070 1071 1072 1073 1074
  SSDataBlock*                  pCtRes = NULL;

  if (hasRemainTbName(pInfo)) {
    pCtRes = buildStreamCreateTableResult(pOperator);
    if (pCtRes != NULL) {
      return pCtRes;
    }
  }

1075 1076 1077 1078
  if (hasRemainPartion(pInfo)) {
    return buildStreamPartitionResult(pOperator);
  }

1079
  int64_t        st = taosGetTimestampUs();
1080 1081 1082 1083 1084
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  {
    pInfo->pInputDataBlock = NULL;
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
1085
      setOperatorCompleted(pOperator);
1086 1087 1088 1089 1090 1091 1092 1093 1094
      return NULL;
    }
    printDataBlock(pBlock, "stream partitionby recv");
    switch (pBlock->info.type) {
      case STREAM_NORMAL:
      case STREAM_PULL_DATA:
      case STREAM_INVALID:
        pInfo->binfo.pRes->info.type = pBlock->info.type;
        break;
1095 1096 1097
      case STREAM_DELETE_DATA: {
        copyDataBlock(pInfo->pDelRes, pBlock);
        pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
5
54liuyao 已提交
1098
        printDataBlock(pInfo->pDelRes, "stream partitionby delete");
1099
        return pInfo->pDelRes;
1100
      } break;
1101
      default:
5
54liuyao 已提交
1102
        ASSERTS(pBlock->info.type == STREAM_CREATE_CHILD_TABLE, "invalid SSDataBlock type");
1103 1104 1105 1106 1107
        return pBlock;
    }

    // there is an scalar expression that needs to be calculated right before apply the group aggregation.
    if (pInfo->scalarSup.pExprInfo != NULL) {
1108 1109
      pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
                                              pInfo->scalarSup.numOfExprs, NULL);
1110 1111 1112 1113 1114 1115 1116 1117
      if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
        longjmp(pTaskInfo->env, pTaskInfo->code);
      }
    }
    taosHashClear(pInfo->pPartitions);
    doStreamHashPartitionImpl(pInfo, pBlock);
  }
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
1118

1119
  pInfo->parIte = taosHashIterate(pInfo->pPartitions, NULL);
5
54liuyao 已提交
1120 1121 1122 1123 1124
  pInfo->pTbNameIte = taosHashIterate(pInfo->pPartitions, NULL);
  pCtRes = buildStreamCreateTableResult(pOperator);
  if (pCtRes != NULL) {
    return pCtRes;
  }
1125 1126 1127 1128 1129 1130 1131 1132
  return buildStreamPartitionResult(pOperator);
}

static void destroyStreamPartitionOperatorInfo(void* param) {
  SStreamPartitionOperatorInfo* pInfo = (SStreamPartitionOperatorInfo*)param;
  cleanupBasicInfo(&pInfo->binfo);
  taosArrayDestroy(pInfo->partitionSup.pGroupCols);

1133
  for (int i = 0; i < taosArrayGetSize(pInfo->partitionSup.pGroupColVals); i++) {
1134 1135 1136 1137 1138 1139 1140
    SGroupKeys key = *(SGroupKeys*)taosArrayGet(pInfo->partitionSup.pGroupColVals, i);
    taosMemoryFree(key.pData);
  }
  taosArrayDestroy(pInfo->partitionSup.pGroupColVals);

  taosMemoryFree(pInfo->partitionSup.keyBuf);
  cleanupExprSupp(&pInfo->scalarSup);
L
Liu Jicong 已提交
1141 1142
  cleanupExprSupp(&pInfo->tbnameCalSup);
  cleanupExprSupp(&pInfo->tagCalSup);
1143
  blockDataDestroy(pInfo->pDelRes);
1144
  taosHashCleanup(pInfo->pPartitions);
5
54liuyao 已提交
1145
  blockDataDestroy(pInfo->pCreateTbRes);
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
  taosMemoryFreeClear(param);
}

void initParDownStream(SOperatorInfo* downstream, SPartitionBySupporter* pParSup, SExprSupp* pExpr) {
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
    return;
  }
  SStreamScanInfo* pScanInfo = downstream->info;
  pScanInfo->partitionSup = *pParSup;
  pScanInfo->pPartScalarSup = pExpr;
5
54liuyao 已提交
1156
  if (!pScanInfo->igCheckUpdate && !pScanInfo->pUpdateInfo) {
5
54liuyao 已提交
1157 1158
    pScanInfo->pUpdateInfo = updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, 0);
  }
1159 1160
}

5
54liuyao 已提交
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
SSDataBlock* buildCreateTableBlock(SExprSupp* tbName, SExprSupp* tag) {
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
  pBlock->info.hasVarCol = false;
  pBlock->info.id.groupId = 0;
  pBlock->info.rows = 0;
  pBlock->info.type = STREAM_CREATE_CHILD_TABLE;
  pBlock->info.watermark = INT64_MIN;

  pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
  SColumnInfoData infoData = {0};
  infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
  if (tbName->numOfExprs > 0) {
    infoData.info.bytes = tbName->pExprInfo->base.resSchema.bytes;
  } else {
    infoData.info.bytes = 1;
  }
  pBlock->info.rowSize += infoData.info.bytes;
  // sub table name
  taosArrayPush(pBlock->pDataBlock, &infoData);

  SColumnInfoData gpIdData = {0};
  gpIdData.info.type = TSDB_DATA_TYPE_UBIGINT;
  gpIdData.info.bytes = 8;
  pBlock->info.rowSize += gpIdData.info.bytes;
  // group id
  taosArrayPush(pBlock->pDataBlock, &gpIdData);

  for (int32_t i = 0; i < tag->numOfExprs; i++) {
    SColumnInfoData tagCol = {0};
    tagCol.info.type = tag->pExprInfo[i].base.resSchema.type;
    tagCol.info.bytes = tag->pExprInfo[i].base.resSchema.bytes;
    tagCol.info.precision = tag->pExprInfo[i].base.resSchema.precision;
    // tag info
    taosArrayPush(pBlock->pDataBlock, &tagCol);
    pBlock->info.rowSize += tagCol.info.bytes;
  }

  return pBlock;
}

1201 1202
SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPartitionPhysiNode* pPartNode,
                                                 SExecTaskInfo* pTaskInfo) {
1203 1204 1205 1206 1207 1208
  SStreamPartitionOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamPartitionOperatorInfo));
  SOperatorInfo*                pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
  int32_t code = TSDB_CODE_SUCCESS;
1209
  pInfo->partitionSup.pGroupCols = extractPartitionColInfo(pPartNode->part.pPartitionKeys);
1210

1211
  if (pPartNode->part.pExprs != NULL) {
1212
    int32_t    num = 0;
1213
    SExprInfo* pCalExprInfo = createExprInfo(pPartNode->part.pExprs, NULL, &num);
1214 1215 1216 1217 1218 1219
    code = initExprSupp(&pInfo->scalarSup, pCalExprInfo, num);
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

5
54liuyao 已提交
1220
  pInfo->tbnameCalSup.numOfExprs = 0;
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
  if (pPartNode->pSubtable != NULL) {
    SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo));
    if (pSubTableExpr == NULL) {
      code = TSDB_CODE_OUT_OF_MEMORY;
      goto _error;
    }
    pInfo->tbnameCalSup.pExprInfo = pSubTableExpr;
    createExprFromOneNode(pSubTableExpr, pPartNode->pSubtable, 0);
    code = initExprSupp(&pInfo->tbnameCalSup, pSubTableExpr, 1);
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

5
54liuyao 已提交
1235
  pInfo->tagCalSup.numOfExprs = 0;
L
Liu Jicong 已提交
1236 1237
  if (pPartNode->pTags != NULL) {
    int32_t    numOfTags;
5
54liuyao 已提交
1238
    SExprInfo* pTagExpr = createExpr(pPartNode->pTags, &numOfTags);
L
Liu Jicong 已提交
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
    if (pTagExpr == NULL) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      goto _error;
    }
    if (initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags) != 0) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      goto _error;
    }
  }

5
54liuyao 已提交
1249 1250 1251 1252 1253 1254
  if (pInfo->tbnameCalSup.numOfExprs != 0 || pInfo->tagCalSup.numOfExprs != 0) {
    pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup);
  } else {
    pInfo->pCreateTbRes = NULL;
  }

1255
  int32_t keyLen = 0;
1256 1257
  code = initGroupOptrInfo(&pInfo->partitionSup.pGroupColVals, &keyLen, &pInfo->partitionSup.keyBuf,
                           pInfo->partitionSup.pGroupCols);
1258 1259 1260 1261 1262
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
  pInfo->partitionSup.needCalc = true;

H
Haojun Liao 已提交
1263
  pInfo->binfo.pRes = createDataBlockFromDescNode(pPartNode->part.node.pOutputDataBlockDesc);
1264
  if (pInfo->binfo.pRes == NULL) {
1265 1266
    goto _error;
  }
1267 1268 1269

  blockDataEnsureCapacity(pInfo->binfo.pRes, 4096);

1270
  pInfo->parIte = NULL;
5
54liuyao 已提交
1271
  pInfo->pTbNameIte = NULL;
1272
  pInfo->pInputDataBlock = NULL;
1273

1274
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
1275 1276 1277
  pInfo->pPartitions = taosHashInit(1024, hashFn, false, HASH_NO_LOCK);
  pInfo->tsColIndex = 0;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
1278

1279
  int32_t    numOfCols = 0;
1280
  SExprInfo* pExprInfo = createExprInfo(pPartNode->part.pTargets, NULL, &numOfCols);
1281

L
Liu Jicong 已提交
1282 1283
  setOperatorInfo(pOperator, "StreamPartitionOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION, false, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
1284 1285
  pOperator->exprSupp.numOfExprs = numOfCols;
  pOperator->exprSupp.pExprInfo = pExprInfo;
dengyihao's avatar
dengyihao 已提交
1286 1287
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamHashPartition, NULL,
                                         destroyStreamPartitionOperatorInfo, optrDefaultBufFn, NULL);
1288 1289 1290 1291 1292

  initParDownStream(downstream, &pInfo->partitionSup, &pInfo->scalarSup);
  code = appendDownstream(pOperator, &downstream, 1);
  return pOperator;

1293
_error:
1294
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
1295
  destroyStreamPartitionOperatorInfo(pInfo);
1296 1297 1298
  taosMemoryFreeClear(pOperator);
  return NULL;
}
H
Haojun Liao 已提交
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331

SArray* extractColumnInfo(SNodeList* pNodeList) {
  size_t  numOfCols = LIST_LENGTH(pNodeList);
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

  for (int32_t i = 0; i < numOfCols; ++i) {
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pNodeList, i);

    if (nodeType(pNode->pExpr) == QUERY_NODE_COLUMN) {
      SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;

      SColumn c = extractColumnFromColumnNode(pColNode);
      taosArrayPush(pList, &c);
    } else if (nodeType(pNode->pExpr) == QUERY_NODE_VALUE) {
      SValueNode* pValNode = (SValueNode*)pNode->pExpr;
      SColumn     c = {0};
      c.slotId = pNode->slotId;
      c.colId = pNode->slotId;
      c.type = pValNode->node.type;
      c.bytes = pValNode->node.resType.bytes;
      c.scale = pValNode->node.resType.scale;
      c.precision = pValNode->node.resType.precision;

      taosArrayPush(pList, &c);
    }
  }

  return pList;
}