builtinsimpl.c 184.8 KB
Newer Older
H
Haojun Liao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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/>.
 */

#include "builtinsimpl.h"
17
#include "cJSON.h"
18
#include "function.h"
X
Xiaoyu Wang 已提交
19
#include "query.h"
20
#include "querynodes.h"
21
#include "streamState.h"
G
Ganlin Zhao 已提交
22
#include "tcompare.h"
H
Haojun Liao 已提交
23
#include "tdatablock.h"
24
#include "tdigest.h"
25
#include "tfunctionInt.h"
X
Xiaoyu Wang 已提交
26
#include "tglobal.h"
27
#include "thistogram.h"
28
#include "tpercentile.h"
H
Haojun Liao 已提交
29

X
Xiaoyu Wang 已提交
30 31 32 33
#define HISTOGRAM_MAX_BINS_NUM 1000
#define MAVG_MAX_POINTS_NUM    1000
#define TAIL_MAX_POINTS_NUM    100
#define TAIL_MAX_OFFSET        100
G
Ganlin Zhao 已提交
34

X
Xiaoyu Wang 已提交
35
#define UNIQUE_MAX_RESULT_SIZE (1024 * 1024 * 10)
G
Ganlin Zhao 已提交
36
#define MODE_MAX_RESULT_SIZE   UNIQUE_MAX_RESULT_SIZE
37

X
Xiaoyu Wang 已提交
38 39 40 41 42
#define HLL_BUCKET_BITS 14  // The bits of the bucket
#define HLL_DATA_BITS   (64 - HLL_BUCKET_BITS)
#define HLL_BUCKETS     (1 << HLL_BUCKET_BITS)
#define HLL_BUCKET_MASK (HLL_BUCKETS - 1)
#define HLL_ALPHA_INF   0.721347520444481703680  // constant for 0.5/ln(2)
G
Ganlin Zhao 已提交
43

L
Liu Jicong 已提交
44 45 46 47
// typedef struct SMinmaxResInfo {
//   bool      assign;  // assign the first value or not
//   int64_t   v;
//   STuplePos tuplePos;
H
Haojun Liao 已提交
48
//
L
Liu Jicong 已提交
49 50 51 52
//   STuplePos nullTuplePos;
//   bool      nullTupleSaved;
//   int16_t   type;
// } SMinmaxResInfo;
G
Ganlin Zhao 已提交
53

54
typedef struct STopBotResItem {
55 56 57
  SVariant  v;
  uint64_t  uid;  // it is a table uid, used to extract tag data during building of the final result for the tag data
  STuplePos tuplePos;  // tuple data of this chosen row
58 59
} STopBotResItem;

G
Ganlin Zhao 已提交
60
typedef struct STopBotRes {
L
Liu Jicong 已提交
61 62
  int32_t maxSize;
  int16_t type;
63

L
Liu Jicong 已提交
64 65
  STuplePos nullTuplePos;
  bool      nullTupleSaved;
66

67
  STopBotResItem* pItems;
G
Ganlin Zhao 已提交
68 69 70 71 72
} STopBotRes;

typedef struct SStddevRes {
  double  result;
  int64_t count;
73
  union {
74 75 76
    double   quadraticDSum;
    int64_t  quadraticISum;
    uint64_t quadraticUSum;
77 78
  };
  union {
79 80 81
    double   dsum;
    int64_t  isum;
    uint64_t usum;
82
  };
G
Ganlin Zhao 已提交
83
  int16_t type;
G
Ganlin Zhao 已提交
84 85
} SStddevRes;

86
typedef struct SLeastSQRInfo {
X
Xiaoyu Wang 已提交
87 88 89
  double  matrix[2][3];
  double  startVal;
  double  stepVal;
90 91 92
  int64_t num;
} SLeastSQRInfo;

G
Ganlin Zhao 已提交
93 94
typedef struct SPercentileInfo {
  double      result;
95
  tMemBucket* pMemBucket;
G
Ganlin Zhao 已提交
96 97 98 99 100 101
  int32_t     stage;
  double      minval;
  double      maxval;
  int64_t     numOfElems;
} SPercentileInfo;

102
typedef struct SAPercentileInfo {
X
Xiaoyu Wang 已提交
103 104 105 106 107
  double          result;
  double          percent;
  int8_t          algo;
  SHistogramInfo* pHisto;
  TDigest*        pTDigest;
108 109 110 111 112 113 114 115
} SAPercentileInfo;

typedef enum {
  APERCT_ALGO_UNKNOWN = 0,
  APERCT_ALGO_DEFAULT,
  APERCT_ALGO_TDIGEST,
} EAPerctAlgoType;

G
Ganlin Zhao 已提交
116
typedef struct SDiffInfo {
117 118
  bool hasPrev;
  bool includeNull;
119
  bool ignoreNegative;  // replace the ignore with case when
120 121 122 123 124
  bool firstOutput;
  union {
    int64_t i64;
    double  d64;
  } prev;
125 126

  int64_t prevTs;
G
Ganlin Zhao 已提交
127 128
} SDiffInfo;

G
Ganlin Zhao 已提交
129 130 131 132 133 134 135
typedef struct SSpreadInfo {
  double result;
  bool   hasResult;
  double min;
  double max;
} SSpreadInfo;

G
Ganlin Zhao 已提交
136 137 138 139 140 141 142
typedef struct SElapsedInfo {
  double  result;
  TSKEY   min;
  TSKEY   max;
  int64_t timeUnit;
} SElapsedInfo;

G
Ganlin Zhao 已提交
143 144
typedef struct STwaInfo {
  double      dOutput;
145
  bool        isNull;
G
Ganlin Zhao 已提交
146 147 148 149
  SPoint1     p;
  STimeWindow win;
} STwaInfo;

150
typedef struct SHistoFuncBin {
X
Xiaoyu Wang 已提交
151 152
  double  lower;
  double  upper;
153 154
  int64_t count;
  double  percentage;
155 156 157
} SHistoFuncBin;

typedef struct SHistoFuncInfo {
X
Xiaoyu Wang 已提交
158 159 160
  int32_t       numOfBins;
  int32_t       totalCount;
  bool          normalized;
161 162 163
  SHistoFuncBin bins[];
} SHistoFuncInfo;

X
Xiaoyu Wang 已提交
164
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
165

166 167
typedef struct SHLLFuncInfo {
  uint64_t result;
168
  uint64_t totalCount;
X
Xiaoyu Wang 已提交
169
  uint8_t  buckets[HLL_BUCKETS];
170 171
} SHLLInfo;

172
typedef struct SStateInfo {
173 174 175 176
  union {
    int64_t count;
    int64_t durationStart;
  };
177 178
  int64_t prevTs;
  bool    isPrevTsSet;
179 180 181 182 183 184 185 186 187 188 189
} SStateInfo;

typedef enum {
  STATE_OPER_INVALID = 0,
  STATE_OPER_LT,
  STATE_OPER_GT,
  STATE_OPER_LE,
  STATE_OPER_GE,
  STATE_OPER_NE,
  STATE_OPER_EQ,
} EStateOperType;
190

G
Ganlin Zhao 已提交
191 192 193
typedef struct SMavgInfo {
  int32_t pos;
  double  sum;
194 195
  int64_t prevTs;
  bool    isPrevTsSet;
G
Ganlin Zhao 已提交
196 197 198 199 200
  int32_t numOfPoints;
  bool    pointsMeet;
  double  points[];
} SMavgInfo;

G
Ganlin Zhao 已提交
201
typedef struct SSampleInfo {
L
Liu Jicong 已提交
202 203 204 205 206
  int32_t samples;
  int32_t totalPoints;
  int32_t numSampled;
  uint8_t colType;
  int16_t colBytes;
207

L
Liu Jicong 已提交
208 209
  STuplePos nullTuplePos;
  bool      nullTupleSaved;
210

211 212
  char*      data;
  STuplePos* tuplePos;
G
Ganlin Zhao 已提交
213 214
} SSampleInfo;

G
Ganlin Zhao 已提交
215
typedef struct STailItem {
G
Ganlin Zhao 已提交
216
  int64_t timestamp;
217
  bool    isNull;
G
Ganlin Zhao 已提交
218
  char    data[];
G
Ganlin Zhao 已提交
219
} STailItem;
G
Ganlin Zhao 已提交
220 221

typedef struct STailInfo {
X
Xiaoyu Wang 已提交
222 223 224 225 226 227
  int32_t     numOfPoints;
  int32_t     numAdded;
  int32_t     offset;
  uint8_t     colType;
  int16_t     colBytes;
  STailItem** pItems;
G
Ganlin Zhao 已提交
228 229
} STailInfo;

G
Ganlin Zhao 已提交
230 231 232 233 234 235 236 237 238 239
typedef struct SUniqueItem {
  int64_t timestamp;
  bool    isNull;
  char    data[];
} SUniqueItem;

typedef struct SUniqueInfo {
  int32_t   numOfPoints;
  uint8_t   colType;
  int16_t   colBytes;
X
Xiaoyu Wang 已提交
240 241
  bool      hasNull;  // null is not hashable, handle separately
  SHashObj* pHash;
G
Ganlin Zhao 已提交
242 243 244
  char      pItems[];
} SUniqueInfo;

G
Ganlin Zhao 已提交
245
typedef struct SModeItem {
246 247 248
  int64_t   count;
  STuplePos tuplePos;
  char      data[];
G
Ganlin Zhao 已提交
249 250 251 252 253 254 255
} SModeItem;

typedef struct SModeInfo {
  int32_t   numOfPoints;
  uint8_t   colType;
  int16_t   colBytes;
  SHashObj* pHash;
256 257 258 259

  STuplePos nullTuplePos;
  bool      nullTupleSaved;

260
  char pItems[];
G
Ganlin Zhao 已提交
261 262
} SModeInfo;

G
Ganlin Zhao 已提交
263 264 265 266 267 268 269 270 271
typedef struct SDerivInfo {
  double  prevValue;       // previous value
  TSKEY   prevTs;          // previous timestamp
  bool    ignoreNegative;  // ignore the negative value
  int64_t tsWindow;        // time window for derivative
  bool    valueSet;        // the value has been set already
} SDerivInfo;

typedef struct SRateInfo {
272 273 274 275 276
  double firstValue;
  TSKEY  firstKey;
  double lastValue;
  TSKEY  lastKey;
  int8_t hasResult;  // flag to denote has value
G
Ganlin Zhao 已提交
277 278
} SRateInfo;

279 280 281 282
typedef struct SGroupKeyInfo {
  bool hasResult;
  bool isNull;
  char data[];
G
Ganlin Zhao 已提交
283 284
} SGroupKeyInfo;

285 286 287 288 289 290
#define SET_VAL(_info, numOfElem, res) \
  do {                                 \
    if ((numOfElem) <= 0) {            \
      break;                           \
    }                                  \
    (_info)->numOfRes = (res);         \
H
Haojun Liao 已提交
291 292
  } while (0)

G
Ganlin Zhao 已提交
293 294 295
#define GET_TS_LIST(x)    ((TSKEY*)((x)->ptsList))
#define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)])

G
Ganlin Zhao 已提交
296 297 298 299 300 301 302 303 304 305 306 307
#define DO_UPDATE_SUBSID_RES(ctx, ts)                          \
  do {                                                         \
    for (int32_t _i = 0; _i < (ctx)->subsidiaries.num; ++_i) { \
      SqlFunctionCtx* __ctx = (ctx)->subsidiaries.pCtx[_i];    \
      if (__ctx->functionId == FUNCTION_TS_DUMMY) {            \
        __ctx->tag.i = (ts);                                   \
        __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT;              \
      }                                                        \
      __ctx->fpSet.process(__ctx);                             \
    }                                                          \
  } while (0)

G
Ganlin Zhao 已提交
308 309 310 311 312 313 314 315 316 317 318
#define UPDATE_DATA(ctx, left, right, num, sign, _ts) \
  do {                                                \
    if (((left) < (right)) ^ (sign)) {                \
      (left) = (right);                               \
      DO_UPDATE_SUBSID_RES(ctx, _ts);                 \
      (num) += 1;                                     \
    }                                                 \
  } while (0)

#define LOOPCHECK_N(val, _col, ctx, _t, _nrow, _start, sign, num)        \
  do {                                                                   \
319
    _t* d = (_t*)((_col)->pData);                                        \
G
Ganlin Zhao 已提交
320 321 322 323 324 325 326 327 328
    for (int32_t i = (_start); i < (_nrow) + (_start); ++i) {            \
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
        continue;                                                        \
      }                                                                  \
      TSKEY ts = (ctx)->ptsList != NULL ? GET_TS_DATA(ctx, i) : 0;       \
      UPDATE_DATA(ctx, val, d[i], num, sign, ts);                        \
    }                                                                    \
  } while (0)

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
#define LIST_ADD_N(_res, _col, _start, _rows, _t, numOfElem)             \
  do {                                                                   \
    _t* d = (_t*)(_col->pData);                                          \
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {            \
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
        continue;                                                        \
      };                                                                 \
      (_res) += (d)[i];                                                  \
      (numOfElem)++;                                                     \
    }                                                                    \
  } while (0)

#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem)             \
  do {                                                                   \
    _t* d = (_t*)(_col->pData);                                          \
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {            \
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
        continue;                                                        \
      };                                                                 \
      (_res) -= (d)[i];                                                  \
      (numOfElem)++;                                                     \
    }                                                                    \
  } while (0)

H
Haojun Liao 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365
//#define LIST_AVG_N(sumT, T)                                               \
//  do {                                                                    \
//    T* plist = (T*)pCol->pData;                                           \
//    for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
//      if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {        \
//        continue;                                                         \
//      }                                                                   \
//                                                                          \
//      numOfElem += 1;                                                     \
//      pAvgRes->count -= 1;                                                \
//      sumT -= plist[i];                                                   \
//    }                                                                     \
//  } while (0)
366 367 368 369 370 371 372 373 374 375 376

#define LIST_STDDEV_SUB_N(sumT, T)                                 \
  do {                                                             \
    T* plist = (T*)pCol->pData;                                    \
    for (int32_t i = start; i < numOfRows + start; ++i) {          \
      if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
        continue;                                                  \
      }                                                            \
      numOfElem += 1;                                              \
      pStddevRes->count -= 1;                                      \
      sumT -= plist[i];                                            \
5
54liuyao 已提交
377
      pStddevRes->quadraticISum -= (int64_t)(plist[i] * plist[i]); \
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
    }                                                              \
  } while (0)

#define LEASTSQR_CAL(p, x, y, index, step) \
  do {                                     \
    (p)[0][0] += (double)(x) * (x);        \
    (p)[0][1] += (double)(x);              \
    (p)[0][2] += (double)(x) * (y)[index]; \
    (p)[1][2] += (y)[index];               \
    (x) += step;                           \
  } while (0)

#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))

#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))

#define STATE_COMP_IMPL(_op, _lval, _rval) \
  do {                                     \
    switch (_op) {                         \
      case STATE_OPER_LT:                  \
        return ((_lval) < (_rval));        \
        break;                             \
      case STATE_OPER_GT:                  \
        return ((_lval) > (_rval));        \
        break;                             \
      case STATE_OPER_LE:                  \
        return ((_lval) <= (_rval));       \
        break;                             \
      case STATE_OPER_GE:                  \
        return ((_lval) >= (_rval));       \
        break;                             \
      case STATE_OPER_NE:                  \
        return ((_lval) != (_rval));       \
        break;                             \
      case STATE_OPER_EQ:                  \
        return ((_lval) == (_rval));       \
        break;                             \
      default:                             \
        break;                             \
    }                                      \
  } while (0)

#define INIT_INTP_POINT(_p, _k, _v) \
  do {                              \
    (_p).key = (_k);                \
    (_p).val = (_v);                \
  } while (0)

5
54liuyao 已提交
426 427
static int32_t firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);

428
bool functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
H
Haojun Liao 已提交
429 430 431 432 433 434 435 436 437 438 439 440
  if (pResultInfo->initialized) {
    return false;
  }

  if (pCtx->pOutput != NULL) {
    memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes);
  }

  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
  return true;
}

441
int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
442
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
443
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
444

445
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
H
Haojun Liao 已提交
446
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
447 448 449 450 451

  char* in = GET_ROWCELL_INTERBUF(pResInfo);
  colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes);

  return pResInfo->numOfRes;
H
Haojun Liao 已提交
452 453
}

5
54liuyao 已提交
454 455
int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
456
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
457
  int32_t              bytes = pDBuf->bytes;
5
54liuyao 已提交
458 459

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
460
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
5
54liuyao 已提交
461

5
54liuyao 已提交
462 463
  if (TSDB_CODE_SUCCESS == firstLastTransferInfoImpl(pSBuf, pDBuf, true)) {
    pDBuf->hasResult = true;
5
54liuyao 已提交
464
  }
5
54liuyao 已提交
465 466 467

  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
468 469 470
  return TSDB_CODE_SUCCESS;
}

471
int32_t functionFinalizeWithResultBuf(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, char* finalResult) {
472
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
473 474 475
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
H
Haojun Liao 已提交
476
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
477 478 479 480 481 482 483

  char* in = finalResult;
  colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes);

  return pResInfo->numOfRes;
}

484 485 486
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
487
    return FUNC_DATA_REQUIRED_NOT_LOAD;
488
  }
H
Haojun Liao 已提交
489
  return FUNC_DATA_REQUIRED_SMA_LOAD;
490
}
H
Haojun Liao 已提交
491 492 493 494 495 496

bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(int64_t);
  return true;
}

497
static int32_t getNumOfElems(SqlFunctionCtx* pCtx) {
H
Haojun Liao 已提交
498 499 500
  int32_t numOfElem = 0;

  /*
H
Haojun Liao 已提交
501 502 503
   * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true;
   * 2. for general non-primary key columns, pInputCol->hasNull may be true or false, pInput->colDataSMAIsSet == true;
   * 3. for primary key column, pInputCol->hasNull always be false, pInput->colDataSMAIsSet == false;
H
Haojun Liao 已提交
504 505
   */
  SInputColumnInfoData* pInput = &pCtx->input;
506
  SColumnInfoData*      pInputCol = pInput->pData[0];
507
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows && !IS_VAR_DATA_TYPE(pInputCol->info.type)) {
H
Haojun Liao 已提交
508 509 510 511 512 513 514 515 516 517
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
  } else {
    if (pInputCol->hasNull) {
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
          continue;
        }
        numOfElem += 1;
      }
    } else {
518 519
      // when counting on the primary time stamp column and no statistics data is presented, use the size value
      // directly.
H
Haojun Liao 已提交
520 521 522
      numOfElem = pInput->numOfRows;
    }
  }
5
54liuyao 已提交
523 524
  return numOfElem;
}
525

5
54liuyao 已提交
526 527 528 529 530
/*
 * count function does need the finalize, if data is missing, the default value, which is 0, is used
 * count function does not use the pCtx->interResBuf to keep the intermediate buffer
 */
int32_t countFunction(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
531
  int32_t numOfElem = 0;
532

X
Xiaoyu Wang 已提交
533
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
534
  SInputColumnInfoData* pInput = &pCtx->input;
535 536

  int32_t type = pInput->pData[0]->info.type;
537 538 539

  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
  if (IS_NULL_TYPE(type)) {
X
Xiaoyu Wang 已提交
540
    // select count(NULL) returns 0
541
    numOfElem = 1;
542
    *((int64_t*)buf) += 0;
543
  } else {
G
Ganlin Zhao 已提交
544
    numOfElem = getNumOfElems(pCtx);
545 546
    *((int64_t*)buf) += numOfElem;
  }
H
Haojun Liao 已提交
547

548 549 550
  if (tsCountAlwaysReturnValue) {
    pResInfo->numOfRes = 1;
  } else {
551
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
552 553
  }

wmmhello's avatar
wmmhello 已提交
554
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
555 556
}

5
54liuyao 已提交
557
int32_t countInvertFunction(SqlFunctionCtx* pCtx) {
558
  int32_t numOfElem = getNumOfElems(pCtx);
5
54liuyao 已提交
559 560 561 562 563 564 565 566 567

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  char*                buf = GET_ROWCELL_INTERBUF(pResInfo);
  *((int64_t*)buf) -= numOfElem;

  SET_VAL(pResInfo, *((int64_t*)buf), 1);
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
568 569
int32_t combineFunction(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
570
  char*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
5
54liuyao 已提交
571 572 573 574 575 576 577 578 579

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  char*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
  *((int64_t*)pDBuf) += *((int64_t*)pSBuf);

  SET_VAL(pDResInfo, *((int64_t*)pDBuf), 1);
  return TSDB_CODE_SUCCESS;
}

580
int32_t sumFunction(SqlFunctionCtx* pCtx) {
H
Haojun Liao 已提交
581 582 583 584
  int32_t numOfElem = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
585 586
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
  int32_t               type = pInput->pData[0]->info.type;
H
Haojun Liao 已提交
587

588
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
589
  pSumRes->type = type;
G
Ganlin Zhao 已提交
590

591
  if (IS_NULL_TYPE(type)) {
592
    numOfElem = 0;
593 594 595
    goto _sum_over;
  }

H
Haojun Liao 已提交
596
  if (pInput->colDataSMAIsSet) {
H
Haojun Liao 已提交
597 598 599
    numOfElem = pInput->numOfRows - pAgg->numOfNull;

    if (IS_SIGNED_NUMERIC_TYPE(type)) {
600
      pSumRes->isum += pAgg->sum;
H
Haojun Liao 已提交
601
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
602
      pSumRes->usum += pAgg->sum;
H
Haojun Liao 已提交
603
    } else if (IS_FLOAT_TYPE(type)) {
604
      pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
H
Haojun Liao 已提交
605 606 607 608
    }
  } else {  // computing based on the true data block
    SColumnInfoData* pCol = pInput->pData[0];

609
    int32_t start = pInput->startRowIndex;
H
Haojun Liao 已提交
610 611
    int32_t numOfRows = pInput->numOfRows;

612 613
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
614 615 616 617 618 619 620
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_INT) {
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
H
Haojun Liao 已提交
621
      }
622 623 624 625 626 627 628 629 630
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
      if (type == TSDB_DATA_TYPE_UTINYINT) {
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_UINT) {
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
H
Haojun Liao 已提交
631
      }
632 633 634 635
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
H
Haojun Liao 已提交
636 637 638
    }
  }

X
Xiaoyu Wang 已提交
639
  // check for overflow
640
  if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
H
Haojun Liao 已提交
641
    numOfElem = 0;
642 643
  }

644
_sum_over:
H
Haojun Liao 已提交
645 646
  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
wmmhello's avatar
wmmhello 已提交
647
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
648 649
}

5
54liuyao 已提交
650 651 652 653 654 655 656 657 658 659
int32_t sumInvertFunction(SqlFunctionCtx* pCtx) {
  int32_t numOfElem = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
  int32_t               type = pInput->pData[0]->info.type;

  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

H
Haojun Liao 已提交
660
  if (pInput->colDataSMAIsSet) {
5
54liuyao 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
    numOfElem = pInput->numOfRows - pAgg->numOfNull;

    if (IS_SIGNED_NUMERIC_TYPE(type)) {
      pSumRes->isum -= pAgg->sum;
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
      pSumRes->usum -= pAgg->sum;
    } else if (IS_FLOAT_TYPE(type)) {
      pSumRes->dsum -= GET_DOUBLE_VAL((const char*)&(pAgg->sum));
    }
  } else {  // computing based on the true data block
    SColumnInfoData* pCol = pInput->pData[0];

    int32_t start = pInput->startRowIndex;
    int32_t numOfRows = pInput->numOfRows;

    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_INT) {
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
      }
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
      if (type == TSDB_DATA_TYPE_UTINYINT) {
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_UINT) {
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
      }
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
    }
  }

  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
708 709
int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
710
  SSumRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
5
54liuyao 已提交
711 712

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
X
Xiaoyu Wang 已提交
713
  SSumRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
714
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
715

5
54liuyao 已提交
716 717 718 719 720 721 722
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
    pDBuf->isum += pSBuf->isum;
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
    pDBuf->usum += pSBuf->usum;
  } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
    pDBuf->dsum += pSBuf->dsum;
  }
5
54liuyao 已提交
723
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
724
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
725 726 727
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
728
bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
H
Haojun Liao 已提交
729 730 731 732
  pEnv->calcMemSize = sizeof(SSumRes);
  return true;
}

733
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
H
Haojun Liao 已提交
734
  return FUNC_DATA_REQUIRED_SMA_LOAD;
735 736
}

737
bool minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
738 739 740 741
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;  // not initialized since it has been initialized
  }

742 743 744
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
  buf->assign = false;
  buf->tuplePos.pageId = -1;
745 746 747

  buf->nullTupleSaved = false;
  buf->nullTuplePos.pageId = -1;
748 749 750
  return true;
}

H
Haojun Liao 已提交
751
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
752
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
753 754 755
  return true;
}

756
int32_t minFunction(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
757 758 759 760 761
  int32_t numOfElems = 0;
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
762
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
wmmhello's avatar
wmmhello 已提交
763
  return TSDB_CODE_SUCCESS;
764 765
}

766
int32_t maxFunction(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
767 768 769 770 771
  int32_t numOfElems = 0;
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
772
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
wmmhello's avatar
wmmhello 已提交
773
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
774 775
}

G
Ganlin Zhao 已提交
776 777
static int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex);
static int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos,
L
Liu Jicong 已提交
778
                                int32_t rowIndex);
779

780
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
781
  int32_t code = TSDB_CODE_SUCCESS;
782

G
Ganlin Zhao 已提交
783
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
784 785 786
  SMinmaxResInfo* pRes = GET_ROWCELL_INTERBUF(pEntryInfo);

  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
787
  int32_t currentRow = pBlock->info.rows;
788 789

  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
H
Haojun Liao 已提交
790
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
791

792 793 794 795 796
  // NOTE: do nothing change it, for performance issue
  if (!pEntryInfo->isNullRes) {
    switch (pCol->info.type) {
      case TSDB_DATA_TYPE_UBIGINT:
      case TSDB_DATA_TYPE_BIGINT:
797 798
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
//        colDataAppendInt64(pCol, currentRow, &pRes->v);
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
        break;
      case TSDB_DATA_TYPE_UINT:
      case TSDB_DATA_TYPE_INT:
        colDataAppendInt32(pCol, currentRow, (int32_t*)&pRes->v);
        break;
      case TSDB_DATA_TYPE_USMALLINT:
      case TSDB_DATA_TYPE_SMALLINT:
        colDataAppendInt16(pCol, currentRow, (int16_t*)&pRes->v);
        break;
      case TSDB_DATA_TYPE_BOOL:
      case TSDB_DATA_TYPE_UTINYINT:
      case TSDB_DATA_TYPE_TINYINT:
        colDataAppendInt8(pCol, currentRow, (int8_t*)&pRes->v);
        break;
      case TSDB_DATA_TYPE_DOUBLE:
        colDataAppendDouble(pCol, currentRow, (double*)&pRes->v);
        break;
      case TSDB_DATA_TYPE_FLOAT: {
        float v = GET_FLOAT_VAL(&pRes->v);
        colDataAppendFloat(pCol, currentRow, &v);
        break;
      }
    }
822
  } else {
823
    colDataAppendNULL(pCol, currentRow);
824
  }
825

826 827 828 829 830 831
  if (pCtx->subsidiaries.num > 0) {
    if (pEntryInfo->numOfRes > 0) {
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
    } else {
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
    }
832 833
  }

G
Ganlin Zhao 已提交
834
  return code;
835
}
836

G
Ganlin Zhao 已提交
837
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
838
  if (pCtx->subsidiaries.num <= 0) {
G
Ganlin Zhao 已提交
839
    return TSDB_CODE_SUCCESS;
840 841
  }

842 843
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
844
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
845 846 847 848

    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
    colDataAppendNULL(pDstCol, rowIndex);
  }
G
Ganlin Zhao 已提交
849 850

  return TSDB_CODE_SUCCESS;
851 852
}

G
Ganlin Zhao 已提交
853
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
854
  if (pCtx->subsidiaries.num <= 0) {
G
Ganlin Zhao 已提交
855
    return TSDB_CODE_SUCCESS;
856 857
  }

L
Liu Jicong 已提交
858 859 860 861
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
    int32_t     numOfCols = pCtx->subsidiaries.num;
    const char* p = loadTupleData(pCtx, pTuplePos);
G
Ganlin Zhao 已提交
862 863 864 865
    if (p == NULL) {
      terrno = TSDB_CODE_NO_AVAIL_DISK;
      return terrno;
    }
866

L
Liu Jicong 已提交
867 868
    bool* nullList = (bool*)p;
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
869

L
Liu Jicong 已提交
870 871 872 873
    // todo set the offset value to optimize the performance.
    for (int32_t j = 0; j < numOfCols; ++j) {
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
874

L
Liu Jicong 已提交
875 876 877 878 879
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
      if (nullList[j]) {
        colDataAppendNULL(pDstCol, rowIndex);
      } else {
        colDataAppend(pDstCol, rowIndex, pStart, false);
880
      }
L
Liu Jicong 已提交
881
      pStart += pDstCol->info.bytes;
882
    }
L
Liu Jicong 已提交
883 884 885

    if (pCtx->saveHandle.pState) {
      tdbFree((void*)p);
886 887
    }
  }
G
Ganlin Zhao 已提交
888 889

  return TSDB_CODE_SUCCESS;
890 891
}

892 893
// This function append the selectivity to subsidiaries function context directly, without fetching data
// from intermediate disk based buf page
894
void appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) {
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
  if (pCtx->subsidiaries.num <= 0) {
    return;
  }

  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];

    // get data from source col
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
    int32_t      srcSlotId = pFuncParam->pCol->slotId;

    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);

    char* pData = colDataGetData(pSrcCol, rowIndex);

    // append to dest col
L
Liu Jicong 已提交
911
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
912 913 914 915

    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);

    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
916
      colDataAppendNULL(pDstCol, pos);
917
    } else {
918
      colDataAppend(pDstCol, pos, pData, false);
919 920 921 922
    }
  }
}

923 924 925 926
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) {
  *pDestPos = *pSourcePos;
}

5
54liuyao 已提交
927 928 929 930 931 932
int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  SMinmaxResInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
933
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
5
54liuyao 已提交
934
  if (IS_FLOAT_TYPE(type)) {
X
Xiaoyu Wang 已提交
935 936
    if (pSBuf->assign && ((((*(double*)&pDBuf->v) < (*(double*)&pSBuf->v)) ^ isMinFunc) || !pDBuf->assign)) {
      *(double*)&pDBuf->v = *(double*)&pSBuf->v;
937
      replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
5
54liuyao 已提交
938
      pDBuf->assign = true;
5
54liuyao 已提交
939 940
    }
  } else {
X
Xiaoyu Wang 已提交
941
    if (pSBuf->assign && (((pDBuf->v < pSBuf->v) ^ isMinFunc) || !pDBuf->assign)) {
5
54liuyao 已提交
942
      pDBuf->v = pSBuf->v;
943
      replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
5
54liuyao 已提交
944
      pDBuf->assign = true;
5
54liuyao 已提交
945 946
    }
  }
5
54liuyao 已提交
947
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
948
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
949 950 951 952 953 954 955 956 957 958
  return TSDB_CODE_SUCCESS;
}

int32_t minCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  return minMaxCombine(pDestCtx, pSourceCtx, 1);
}
int32_t maxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
}

959 960
int32_t getStddevInfoSize() { return (int32_t)sizeof(SStddevRes); }

H
Haojun Liao 已提交
961 962 963 964 965
bool getStddevFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SStddevRes);
  return true;
}

966
bool stddevFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
H
Haojun Liao 已提交
967 968 969 970 971 972 973 974 975
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  SStddevRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
  memset(pRes, 0, sizeof(SStddevRes));
  return true;
}

H
Haojun Liao 已提交
976
int32_t stddevFunction(SqlFunctionCtx* pCtx) {
H
Haojun Liao 已提交
977 978 979 980
  int32_t numOfElem = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
H
Haojun Liao 已提交
981
  int32_t               type = pInput->pData[0]->info.type;
H
Haojun Liao 已提交
982 983

  SStddevRes* pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
G
Ganlin Zhao 已提交
984
  pStddevRes->type = type;
H
Haojun Liao 已提交
985

H
Haojun Liao 已提交
986 987
  // computing based on the true data block
  SColumnInfoData* pCol = pInput->pData[0];
H
Haojun Liao 已提交
988

H
Haojun Liao 已提交
989 990
  int32_t start = pInput->startRowIndex;
  int32_t numOfRows = pInput->numOfRows;
H
Haojun Liao 已提交
991

992
  if (IS_NULL_TYPE(type)) {
H
Haojun Liao 已提交
993
    numOfElem = 0;
994 995 996
    goto _stddev_over;
  }

H
Haojun Liao 已提交
997 998
  switch (type) {
    case TSDB_DATA_TYPE_TINYINT: {
999 1000 1001 1002
      int8_t* plist = (int8_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + start; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
H
Haojun Liao 已提交
1003
        }
H
Haojun Liao 已提交
1004

1005 1006 1007 1008
        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->isum += plist[i];
        pStddevRes->quadraticISum += plist[i] * plist[i];
H
Haojun Liao 已提交
1009 1010
      }

1011 1012 1013 1014
      break;
    }

    case TSDB_DATA_TYPE_SMALLINT: {
H
Haojun Liao 已提交
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 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
      int16_t* plist = (int16_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->isum += plist[i];
        pStddevRes->quadraticISum += plist[i] * plist[i];
      }
      break;
    }

    case TSDB_DATA_TYPE_INT: {
      int32_t* plist = (int32_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->isum += plist[i];
        pStddevRes->quadraticISum += plist[i] * plist[i];
      }

      break;
    }

    case TSDB_DATA_TYPE_BIGINT: {
      int64_t* plist = (int64_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->isum += plist[i];
        pStddevRes->quadraticISum += plist[i] * plist[i];
      }
      break;
    }

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
    case TSDB_DATA_TYPE_UTINYINT: {
      uint8_t* plist = (uint8_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + start; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->usum += plist[i];
G
Ganlin Zhao 已提交
1070
        pStddevRes->quadraticUSum += plist[i] * plist[i];
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
      }

      break;
    }

    case TSDB_DATA_TYPE_USMALLINT: {
      uint16_t* plist = (uint16_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->usum += plist[i];
G
Ganlin Zhao 已提交
1086
        pStddevRes->quadraticUSum += plist[i] * plist[i];
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
      }
      break;
    }

    case TSDB_DATA_TYPE_UINT: {
      uint32_t* plist = (uint32_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->usum += plist[i];
G
Ganlin Zhao 已提交
1101
        pStddevRes->quadraticUSum += plist[i] * plist[i];
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
      }

      break;
    }

    case TSDB_DATA_TYPE_UBIGINT: {
      uint64_t* plist = (uint64_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
        pStddevRes->usum += plist[i];
G
Ganlin Zhao 已提交
1117
        pStddevRes->quadraticUSum += plist[i] * plist[i];
1118 1119 1120 1121
      }
      break;
    }

H
Haojun Liao 已提交
1122 1123 1124 1125 1126 1127 1128 1129 1130
    case TSDB_DATA_TYPE_FLOAT: {
      float* plist = (float*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
G
Ganlin Zhao 已提交
1131 1132
        pStddevRes->dsum += plist[i];
        pStddevRes->quadraticDSum += plist[i] * plist[i];
H
Haojun Liao 已提交
1133 1134 1135 1136
      }
      break;
    }

H
Haojun Liao 已提交
1137 1138 1139 1140 1141 1142 1143 1144 1145
    case TSDB_DATA_TYPE_DOUBLE: {
      double* plist = (double*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem += 1;
        pStddevRes->count += 1;
G
Ganlin Zhao 已提交
1146 1147
        pStddevRes->dsum += plist[i];
        pStddevRes->quadraticDSum += plist[i] * plist[i];
H
Haojun Liao 已提交
1148 1149 1150 1151 1152 1153 1154 1155
      }
      break;
    }

    default:
      break;
  }

1156
_stddev_over:
H
Haojun Liao 已提交
1157 1158
  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
wmmhello's avatar
wmmhello 已提交
1159
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
1160 1161
}

G
Ganlin Zhao 已提交
1162 1163
static void stddevTransferInfo(SStddevRes* pInput, SStddevRes* pOutput) {
  pOutput->type = pInput->type;
1164
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
G
Ganlin Zhao 已提交
1165 1166
    pOutput->quadraticISum += pInput->quadraticISum;
    pOutput->isum += pInput->isum;
1167 1168 1169
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
    pOutput->quadraticUSum += pInput->quadraticUSum;
    pOutput->usum += pInput->usum;
G
Ganlin Zhao 已提交
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
  } else {
    pOutput->quadraticDSum += pInput->quadraticDSum;
    pOutput->dsum += pInput->dsum;
  }

  pOutput->count += pInput->count;
}

int32_t stddevFunctionMerge(SqlFunctionCtx* pCtx) {
  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
1181 1182 1183
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
G
Ganlin Zhao 已提交
1184 1185 1186

  SStddevRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

H
Hongze Cheng 已提交
1187
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
1188 1189 1190 1191
    char*       data = colDataGetData(pCol, i);
    SStddevRes* pInputInfo = (SStddevRes*)varDataVal(data);
    stddevTransferInfo(pInputInfo, pInfo);
  }
G
Ganlin Zhao 已提交
1192 1193 1194 1195 1196

  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
int32_t stddevInvertFunction(SqlFunctionCtx* pCtx) {
  int32_t numOfElem = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
  int32_t               type = pInput->pData[0]->info.type;

  SStddevRes* pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

  // computing based on the true data block
  SColumnInfoData* pCol = pInput->pData[0];

  int32_t start = pInput->startRowIndex;
  int32_t numOfRows = pInput->numOfRows;

  switch (type) {
    case TSDB_DATA_TYPE_TINYINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, int8_t);
      break;
    }
    case TSDB_DATA_TYPE_SMALLINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, int16_t);
      break;
    }
    case TSDB_DATA_TYPE_INT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, int32_t);
      break;
    }
    case TSDB_DATA_TYPE_BIGINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, int64_t);
      break;
    }
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
    case TSDB_DATA_TYPE_UTINYINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, uint8_t);
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, uint16_t);
      break;
    }
    case TSDB_DATA_TYPE_UINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, uint32_t);
      break;
    }
    case TSDB_DATA_TYPE_UBIGINT: {
      LIST_STDDEV_SUB_N(pStddevRes->isum, uint64_t);
      break;
    }
5
54liuyao 已提交
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
    case TSDB_DATA_TYPE_FLOAT: {
      LIST_STDDEV_SUB_N(pStddevRes->dsum, float);
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
      LIST_STDDEV_SUB_N(pStddevRes->dsum, double);
      break;
    }
    default:
      break;
  }

  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
1262
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
1263
  SInputColumnInfoData* pInput = &pCtx->input;
1264
  SStddevRes*           pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
G
Ganlin Zhao 已提交
1265
  int32_t               type = pStddevRes->type;
1266
  double                avg;
G
Ganlin Zhao 已提交
1267

1268 1269 1270 1271 1272
  if (pStddevRes->count == 0) {
    GET_RES_INFO(pCtx)->numOfRes = 0;
    return functionFinalize(pCtx, pBlock);
  }

1273
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
1274
    avg = pStddevRes->isum / ((double)pStddevRes->count);
1275
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
1276 1277 1278
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
    avg = pStddevRes->usum / ((double)pStddevRes->count);
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
G
Ganlin Zhao 已提交
1279
  } else {
1280
    avg = pStddevRes->dsum / ((double)pStddevRes->count);
1281
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
G
Ganlin Zhao 已提交
1282
  }
1283

1284 1285 1286 1287 1288
  // check for overflow
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
    GET_RES_INFO(pCtx)->numOfRes = 0;
  }

1289
  return functionFinalize(pCtx, pBlock);
H
Haojun Liao 已提交
1290 1291
}

G
Ganlin Zhao 已提交
1292 1293
int32_t stddevPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1294 1295 1296
  SStddevRes*          pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              resultBytes = getStddevInfoSize();
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
G
Ganlin Zhao 已提交
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309

  memcpy(varDataVal(res), pInfo, resultBytes);
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);

  taosMemoryFree(res);
  return pResInfo->numOfRes;
}

5
54liuyao 已提交
1310 1311
int32_t stddevCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
1312
  SStddevRes*          pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
5
54liuyao 已提交
1313 1314

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
X
Xiaoyu Wang 已提交
1315
  SStddevRes*          pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1316
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
5
54liuyao 已提交
1317

5
54liuyao 已提交
1318 1319
  stddevTransferInfo(pSBuf, pDBuf);

5
54liuyao 已提交
1320
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
1321
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
1322 1323 1324
  return TSDB_CODE_SUCCESS;
}

1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
  return true;
}

bool leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);

1337 1338
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
  return true;
}

int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
  int32_t numOfElem = 0;

  SInputColumnInfoData* pInput = &pCtx->input;
  int32_t               type = pInput->pData[0]->info.type;

  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

  SColumnInfoData* pCol = pInput->pData[0];

  double(*param)[3] = pInfo->matrix;
  double x = pInfo->startVal;

  int32_t start = pInput->startRowIndex;
  int32_t numOfRows = pInput->numOfRows;

  switch (type) {
    case TSDB_DATA_TYPE_TINYINT: {
      int8_t* plist = (int8_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }
        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
1368
      break;
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
    }
    case TSDB_DATA_TYPE_SMALLINT: {
      int16_t* plist = (int16_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

    case TSDB_DATA_TYPE_INT: {
      int32_t* plist = (int32_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

    case TSDB_DATA_TYPE_BIGINT: {
      int64_t* plist = (int64_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
    case TSDB_DATA_TYPE_UTINYINT: {
      uint8_t* plist = (uint8_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }
        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
      uint16_t* plist = (uint16_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

    case TSDB_DATA_TYPE_UINT: {
      uint32_t* plist = (uint32_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

    case TSDB_DATA_TYPE_UBIGINT: {
      uint64_t* plist = (uint64_t*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
    case TSDB_DATA_TYPE_FLOAT: {
      float* plist = (float*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }

    case TSDB_DATA_TYPE_DOUBLE: {
      double* plist = (double*)pCol->pData;
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
          continue;
        }

        numOfElem++;
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
      }
      break;
    }
1484 1485 1486 1487 1488
    case TSDB_DATA_TYPE_NULL: {
      GET_RES_INFO(pCtx)->isNullRes = 1;
      numOfElem = 1;
      break;
    }
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503

    default:
      break;
  }

  pInfo->startVal = x;
  pInfo->num += numOfElem;

  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);

  return TSDB_CODE_SUCCESS;
}

int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
1504 1505 1506
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1507 1508 1509

  int32_t currentRow = pBlock->info.rows;

1510
  if (0 == pInfo->num) {
1511
    colDataAppendNULL(pCol, currentRow);
1512 1513 1514 1515 1516 1517 1518 1519
    return 0;
  }

  double(*param)[3] = pInfo->matrix;

  param[1][1] = (double)pInfo->num;
  param[1][0] = param[0][1];

5
54liuyao 已提交
1520 1521
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
1522 1523 1524 1525 1526 1527

  if (0 == param00) {
    colDataAppendNULL(pCol, currentRow);
    return 0;
  }

5
54liuyao 已提交
1528 1529 1530 1531
  // param[0][1] = 0;
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
  // param[1][0] = 0;
  param02 /= param00;
1532

5
54liuyao 已提交
1533
  param12 /= param[1][1];
1534

G
Ganlin Zhao 已提交
1535
  char   buf[512] = {0};
X
Xiaoyu Wang 已提交
1536 1537
  size_t len =
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%.6lf, intercept:%.6lf}", param02, param12);
1538 1539
  varDataSetLen(buf, len);

1540
  colDataAppend(pCol, currentRow, buf, pResInfo->isNullRes);
1541 1542 1543 1544 1545

  return pResInfo->numOfRes;
}

int32_t leastSQRInvertFunction(SqlFunctionCtx* pCtx) {
X
Xiaoyu Wang 已提交
1546
  // TODO
1547 1548 1549
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
1550 1551 1552 1553
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
  int32_t              type = pDestCtx->input.pData[0]->info.type;
X
Xiaoyu Wang 已提交
1554
  double(*pDparam)[3] = pDBuf->matrix;
5
54liuyao 已提交
1555 1556 1557

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  SLeastSQRInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
X
Xiaoyu Wang 已提交
1558
  double(*pSparam)[3] = pSBuf->matrix;
5
54liuyao 已提交
1559 1560 1561 1562 1563 1564 1565 1566 1567
  for (int32_t i = 0; i < pSBuf->num; i++) {
    pDparam[0][0] += pDBuf->startVal * pDBuf->startVal;
    pDparam[0][1] += pDBuf->startVal;
    pDBuf->startVal += pDBuf->stepVal;
  }
  pDparam[0][2] += pSparam[0][2] + pDBuf->num * pDBuf->stepVal * pSparam[1][2];
  pDparam[1][2] += pSparam[1][2];
  pDBuf->num += pSBuf->num;
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
1568
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
1569 1570 1571
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
1572 1573 1574 1575 1576
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SPercentileInfo);
  return true;
}

1577
bool percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
H
Haojun Liao 已提交
1578 1579 1580 1581 1582
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  // in the first round, get the min-max value of all involved data
1583
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
H
Haojun Liao 已提交
1584 1585 1586 1587 1588
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
  pInfo->numOfElems = 0;

  return true;
H
Haojun Liao 已提交
1589 1590
}

1591
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
1592
  int32_t              numOfElems = 0;
1593
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1594 1595

  SInputColumnInfoData* pInput = &pCtx->input;
1596
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
H
Haojun Liao 已提交
1597

1598 1599
  SColumnInfoData* pCol = pInput->pData[0];
  int32_t          type = pCol->info.type;
1600

1601
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
G
Ganlin Zhao 已提交
1602
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
H
Haojun Liao 已提交
1603
    pInfo->stage += 1;
H
Haojun Liao 已提交
1604

H
Haojun Liao 已提交
1605 1606 1607
    // all data are null, set it completed
    if (pInfo->numOfElems == 0) {
      pResInfo->complete = true;
1608
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
1609
    } else {
1610
      pInfo->pMemBucket = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval);
H
Haojun Liao 已提交
1611 1612 1613 1614 1615
    }
  }

  // the first stage, only acquire the min/max value
  if (pInfo->stage == 0) {
H
Haojun Liao 已提交
1616
    if (pCtx->input.colDataSMAIsSet) {
H
Haojun Liao 已提交
1617
      double tmin = 0.0, tmax = 0.0;
1618 1619 1620 1621 1622 1623 1624 1625 1626
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
        tmin = (double)GET_INT64_VAL(&pAgg->min);
        tmax = (double)GET_INT64_VAL(&pAgg->max);
      } else if (IS_FLOAT_TYPE(type)) {
        tmin = GET_DOUBLE_VAL(&pAgg->min);
        tmax = GET_DOUBLE_VAL(&pAgg->max);
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
H
Haojun Liao 已提交
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
      }

      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
      }

      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
      }

1637
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
H
Haojun Liao 已提交
1638
    } else {
1639 1640 1641 1642
      // check the valid data one by one
      int32_t start = pInput->startRowIndex;
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
H
Haojun Liao 已提交
1643 1644 1645
          continue;
        }

1646
        char* data = colDataGetData(pCol, i);
1647

H
Haojun Liao 已提交
1648
        double v = 0;
1649
        GET_TYPED_DATA(v, double, type, data);
H
Haojun Liao 已提交
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
          SET_DOUBLE_VAL(&pInfo->minval, v);
        }

        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
          SET_DOUBLE_VAL(&pInfo->maxval, v);
        }

        pInfo->numOfElems += 1;
      }
    }
1661 1662 1663 1664 1665 1666 1667
  } else {
    // the second stage, calculate the true percentile value
    int32_t start = pInput->startRowIndex;
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
        continue;
      }
H
Haojun Liao 已提交
1668

1669
      char* data = colDataGetData(pCol, i);
1670
      numOfElems += 1;
1671 1672
      int32_t code = tMemBucketPut(pInfo->pMemBucket, data, 1);
      if (code != TSDB_CODE_SUCCESS) {
G
Ganlin Zhao 已提交
1673
        tMemBucketDestroy(pInfo->pMemBucket);
1674 1675
        return code;
      }
H
Haojun Liao 已提交
1676 1677
    }

1678
    SET_VAL(pResInfo, numOfElems, 1);
H
Haojun Liao 已提交
1679 1680
  }

wmmhello's avatar
wmmhello 已提交
1681
  return TSDB_CODE_SUCCESS;
1682 1683
}

1684
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1685 1686
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
1687

G
Ganlin Zhao 已提交
1688 1689
  int32_t code = 0;
  double     v = 0;
H
Haojun Liao 已提交
1690

1691
  tMemBucket* pMemBucket = ppInfo->pMemBucket;
G
Ganlin Zhao 已提交
1692 1693 1694 1695
  if (pMemBucket == NULL || pMemBucket->total == 0) {  // check for null
    code = TSDB_CODE_FAILED;
    goto _fin_error;
  }
1696

G
Ganlin Zhao 已提交
1697
  if (pCtx->numOfParams > 2) {
1698
    char   buf[512] = {0};
G
Ganlin Zhao 已提交
1699
    size_t len = 1;
1700

G
Ganlin Zhao 已提交
1701
    varDataVal(buf)[0] = '[';
1702 1703 1704 1705 1706 1707 1708
    for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
      SVariant* pVal = &pCtx->param[i].param;

      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);

      int32_t code = getPercentile(pMemBucket, v, &ppInfo->result);
      if (code != TSDB_CODE_SUCCESS) {
G
Ganlin Zhao 已提交
1709
        goto _fin_error;
1710 1711
      }

G
Ganlin Zhao 已提交
1712 1713 1714 1715 1716
      if (i == pCtx->numOfParams - 1) {
        len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
      } else {
        len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
      }
1717 1718 1719
    }

    int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
G
Ganlin Zhao 已提交
1720
    SColumnInfoData* pCol   = taosArrayGet(pBlock->pDataBlock, slotId);
1721 1722 1723 1724

    varDataSetLen(buf, len);
    colDataAppend(pCol, pBlock->info.rows, buf, false);

G
Ganlin Zhao 已提交
1725
    tMemBucketDestroy(pMemBucket);
1726 1727 1728 1729 1730 1731
    return pResInfo->numOfRes;
  } else {
    SVariant* pVal = &pCtx->param[1].param;

    GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);

H
Haojun Liao 已提交
1732
    code = getPercentile(pMemBucket, v, &ppInfo->result);
G
Ganlin Zhao 已提交
1733 1734
    if (code != TSDB_CODE_SUCCESS) {
      goto _fin_error;
1735 1736 1737 1738
    }

    tMemBucketDestroy(pMemBucket);
    return functionFinalize(pCtx, pBlock);
1739 1740
  }

G
Ganlin Zhao 已提交
1741 1742
_fin_error:

1743
  tMemBucketDestroy(pMemBucket);
G
Ganlin Zhao 已提交
1744
  return code;
1745

H
Haojun Liao 已提交
1746
}
H
Haojun Liao 已提交
1747

1748
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
X
Xiaoyu Wang 已提交
1749 1750
  int32_t bytesHist =
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1751
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
G
Ganlin Zhao 已提交
1752
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
1753 1754 1755
  return true;
}

G
Ganlin Zhao 已提交
1756
int32_t getApercentileMaxSize() {
X
Xiaoyu Wang 已提交
1757 1758
  int32_t bytesHist =
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
G
Ganlin Zhao 已提交
1759 1760 1761 1762
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
  return TMAX(bytesHist, bytesDigest);
}

X
Xiaoyu Wang 已提交
1763
static int8_t getApercentileAlgo(char* algoStr) {
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776
  int8_t algoType;
  if (strcasecmp(algoStr, "default") == 0) {
    algoType = APERCT_ALGO_DEFAULT;
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
    algoType = APERCT_ALGO_TDIGEST;
  } else {
    algoType = APERCT_ALGO_UNKNOWN;
  }

  return algoType;
}

static void buildHistogramInfo(SAPercentileInfo* pInfo) {
X
Xiaoyu Wang 已提交
1777 1778
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
1779 1780
}

1781 1782 1783 1784
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
}

1785 1786 1787 1788 1789 1790
bool apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1791 1792

  SVariant* pVal = &pCtx->param[1].param;
1793
  pInfo->percent = 0;
1794
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i);
1795

1796 1797 1798
  if (pCtx->numOfParams == 2) {
    pInfo->algo = APERCT_ALGO_DEFAULT;
  } else if (pCtx->numOfParams == 3) {
1799
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
1800 1801 1802 1803 1804
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
      return false;
    }
  }

X
Xiaoyu Wang 已提交
1805
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
1806 1807 1808 1809 1810
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
  } else {
    buildHistogramInfo(pInfo);
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
G
Ganlin Zhao 已提交
1811 1812
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
1813 1814 1815 1816 1817 1818
  }

  return true;
}

int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
1819 1820
  int32_t               numOfElems = 0;
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
1821 1822 1823 1824 1825 1826 1827 1828 1829
  SInputColumnInfoData* pInput = &pCtx->input;

  SColumnInfoData* pCol = pInput->pData[0];
  int32_t          type = pCol->info.type;

  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  int32_t start = pInput->startRowIndex;
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
5
54liuyao 已提交
1830 1831
    buildTDigestInfo(pInfo);
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1832 1833 1834 1835
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
        continue;
      }
1836
      numOfElems += 1;
1837 1838
      char* data = colDataGetData(pCol, i);

X
Xiaoyu Wang 已提交
1839 1840
      double  v = 0;  // value
      int64_t w = 1;  // weigth
1841 1842 1843 1844
      GET_TYPED_DATA(v, double, type, data);
      tdigestAdd(pInfo->pTDigest, v, w);
    }
  } else {
1845 1846 1847
    // might be a race condition here that pHisto can be overwritten or setup function
    // has not been called, need to relink the buffer pHisto points to.
    buildHistogramInfo(pInfo);
5
54liuyao 已提交
1848 1849 1850
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
           pInfo->pHisto->elems);
1851 1852 1853 1854
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
        continue;
      }
1855
      numOfElems += 1;
1856 1857 1858 1859
      char* data = colDataGetData(pCol, i);

      double v = 0;
      GET_TYPED_DATA(v, double, type, data);
G
Ganlin Zhao 已提交
1860 1861 1862 1863
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
      if (code != 0) {
        return TSDB_CODE_FAILED;
      }
1864
    }
1865

1866 1867 1868
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
           pInfo->pHisto->elems);
1869 1870
  }

1871
  SET_VAL(pResInfo, numOfElems, 1);
1872 1873 1874
  return TSDB_CODE_SUCCESS;
}

1875 1876 1877 1878 1879 1880
static void apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput) {
  pOutput->percent = pInput->percent;
  pOutput->algo = pInput->algo;
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
    buildTDigestInfo(pInput);
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
1881

X
Xiaoyu Wang 已提交
1882
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
1883
      return;
1884 1885
    }

1886
    buildTDigestInfo(pOutput);
X
Xiaoyu Wang 已提交
1887
    TDigest* pTDigest = pOutput->pTDigest;
5
54liuyao 已提交
1888
    tdigestAutoFill(pTDigest, COMPRESSION);
1889

5
54liuyao 已提交
1890
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
1891
      memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
1892 1893
      tdigestAutoFill(pTDigest, COMPRESSION);
    } else {
1894
      tdigestMerge(pTDigest, pInput->pTDigest);
1895
    }
1896
  } else {
1897 1898 1899
    buildHistogramInfo(pInput);
    if (pInput->pHisto->numOfElems <= 0) {
      return;
1900 1901
    }

1902
    buildHistogramInfo(pOutput);
X
Xiaoyu Wang 已提交
1903
    SHistogramInfo* pHisto = pOutput->pHisto;
1904 1905

    if (pHisto->numOfElems <= 0) {
1906
      memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
X
Xiaoyu Wang 已提交
1907
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
1908

L
Liu Jicong 已提交
1909 1910
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
             pHisto);
1911
    } else {
X
Xiaoyu Wang 已提交
1912
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
G
Ganlin Zhao 已提交
1913 1914
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
             pHisto->numOfEntries, pInput->pHisto);
1915

X
Xiaoyu Wang 已提交
1916
      SHistogramInfo* pRes = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN);
1917
      memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
X
Xiaoyu Wang 已提交
1918
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
1919

L
Liu Jicong 已提交
1920 1921
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
             pHisto);
1922 1923 1924
      tHistogramDestroy(&pRes);
    }
  }
1925
}
1926

1927 1928 1929 1930 1931 1932
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);

  SInputColumnInfoData* pInput = &pCtx->input;

  SColumnInfoData* pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
1933 1934 1935
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
1936 1937 1938

  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);

G
Ganlin Zhao 已提交
1939
  qDebug("%s total %d rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
1940

1941
  int32_t start = pInput->startRowIndex;
X
Xiaoyu Wang 已提交
1942
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1943 1944
    char* data = colDataGetData(pCol, i);

1945 1946 1947
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
    apercentileTransferInfo(pInputInfo, pInfo);
  }
1948

H
Haojun Liao 已提交
1949
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
1950
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
L
Liu Jicong 已提交
1951
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
H
Haojun Liao 已提交
1952
  }
1953

1954
  SET_VAL(pResInfo, 1, 1);
1955 1956 1957
  return TSDB_CODE_SUCCESS;
}

1958 1959
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
1960
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
1961 1962

  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
1963
    buildTDigestInfo(pInfo);
5
54liuyao 已提交
1964
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1965
    if (pInfo->pTDigest->size > 0) {
1966
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1967
    } else {  // no need to free
X
Xiaoyu Wang 已提交
1968
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
1969 1970 1971
      return TSDB_CODE_SUCCESS;
    }
  } else {
1972
    buildHistogramInfo(pInfo);
1973
    if (pInfo->pHisto->numOfElems > 0) {
G
Ganlin Zhao 已提交
1974 1975
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
1976

X
Xiaoyu Wang 已提交
1977 1978
      double  ratio[] = {pInfo->percent};
      double* res = tHistogramUniform(pInfo->pHisto, ratio, 1);
1979
      pInfo->result = *res;
X
Xiaoyu Wang 已提交
1980
      // memcpy(pCtx->pOutput, res, sizeof(double));
1981 1982
      taosMemoryFree(res);
    } else {  // no need to free
X
Xiaoyu Wang 已提交
1983
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
1984 1985 1986
      // return TSDB_CODE_SUCCESS;
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
1987 1988 1989 1990 1991 1992
    }
  }

  return functionFinalize(pCtx, pBlock);
}

1993 1994
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
1995
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
1996

1997
  int32_t resultBytes = getApercentileMaxSize();
X
Xiaoyu Wang 已提交
1998
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1999 2000

  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
2001 2002
    memcpy(varDataVal(res), pInfo, resultBytes);
    varDataSetLen(res, resultBytes);
2003
  } else {
2004 2005
    memcpy(varDataVal(res), pInfo, resultBytes);
    varDataSetLen(res, resultBytes);
2006 2007 2008 2009 2010
  }

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

2011
  colDataAppend(pCol, pBlock->info.rows, res, false);
2012

2013
  taosMemoryFree(res);
2014 2015 2016
  return pResInfo->numOfRes;
}

2017 2018 2019 2020 2021 2022
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
2023

G
Ganlin Zhao 已提交
2024
  qDebug("%s start to combine apercentile, %p", __FUNCTION__, pDBuf->pHisto);
2025

2026
  apercentileTransferInfo(pSBuf, pDBuf);
2027
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
2028
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
2029 2030 2031
  return TSDB_CODE_SUCCESS;
}

2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047
EFuncDataRequired firstDynDataReq(void* pRes, STimeWindow* pTimeWindow) {
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;

  // not initialized yet, data is required
  if (pEntry == NULL) {
    return FUNC_DATA_REQUIRED_DATA_LOAD;
  }

  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
  if (pResult->hasResult && pResult->ts <= pTimeWindow->skey) {
    return FUNC_DATA_REQUIRED_NOT_LOAD;
  } else {
    return FUNC_DATA_REQUIRED_DATA_LOAD;
  }
}

2048
EFuncDataRequired lastDynDataReq(void* pRes, STimeWindow* pTimeWindow) {
L
Liu Jicong 已提交
2049
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063

  // not initialized yet, data is required
  if (pEntry == NULL) {
    return FUNC_DATA_REQUIRED_DATA_LOAD;
  }

  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
  if (pResult->hasResult && pResult->ts >= pTimeWindow->ekey) {
    return FUNC_DATA_REQUIRED_NOT_LOAD;
  } else {
    return FUNC_DATA_REQUIRED_DATA_LOAD;
  }
}

2064
int32_t getFirstLastInfoSize(int32_t resBytes) { return sizeof(SFirstLastRes) + resBytes; }
2065

H
Haojun Liao 已提交
2066
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2067
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
2068
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes);
H
Haojun Liao 已提交
2069 2070 2071
  return true;
}

2072
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2073
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
2074 2075 2076 2077
  pEnv->calcMemSize = pNode->node.resType.bytes;
  return true;
}

2078 2079
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
G
Ganlin Zhao 已提交
2080
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
2081 2082 2083
  return true;
}

2084 2085 2086 2087 2088
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
  if (pTsColInfo == NULL) {
    return 0;
  }

2089
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
2090 2091
}

2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
static void prepareBuf(SqlFunctionCtx* pCtx) {
  if (pCtx->subsidiaries.rowLen == 0) {
    int32_t rowLen = 0;
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
      rowLen += pc->pExpr->base.resSchema.bytes;
    }

    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
  }
}

2105
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
L
Liu Jicong 已提交
2106
                                   SFirstLastRes* pInfo) {
G
Ganlin Zhao 已提交
2107 2108
  int32_t code = TSDB_CODE_SUCCESS;

2109
  if (pCtx->subsidiaries.num <= 0) {
2110
    return TSDB_CODE_SUCCESS;
2111 2112 2113
  }

  if (!pInfo->hasResult) {
G
Ganlin Zhao 已提交
2114
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
2115
  } else {
G
Ganlin Zhao 已提交
2116
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
2117
  }
2118

G
Ganlin Zhao 已提交
2119
  return code;
2120 2121
}

2122
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, int32_t type, char* pData) {
2123 2124 2125 2126 2127 2128 2129 2130 2131
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  if (IS_VAR_DATA_TYPE(type)) {
    pInfo->bytes = varDataTLen(pData);
  }

  memcpy(pInfo->buf, pData, pInfo->bytes);
  pInfo->ts = currentTs;
2132 2133 2134 2135
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo);
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
2136 2137

  pInfo->hasResult = true;
2138
  return TSDB_CODE_SUCCESS;
2139 2140
}

2141 2142
// This ordinary first function does not care if current scan is ascending order or descending order scan
// the OPTIMIZED version of first function will only handle the ascending order scan
2143
int32_t firstFunction(SqlFunctionCtx* pCtx) {
H
Haojun Liao 已提交
2144 2145
  int32_t numOfElems = 0;

2146
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2147
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
H
Haojun Liao 已提交
2148 2149

  SInputColumnInfoData* pInput = &pCtx->input;
2150
  SColumnInfoData*      pInputCol = pInput->pData[0];
H
Haojun Liao 已提交
2151

2152
  pInfo->bytes = pInputCol->info.bytes;
2153

G
Ganlin Zhao 已提交
2154
  if (IS_NULL_TYPE(pInputCol->info.type)) {
G
Ganlin Zhao 已提交
2155
    return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
2156 2157
  }

H
Haojun Liao 已提交
2158
  // All null data column, return directly.
G
Ganlin Zhao 已提交
2159
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && pInputCol->hasNull == true) {
2160
    // save selectivity value for column consisted of all null values
2161 2162 2163 2164
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
G
Ganlin Zhao 已提交
2165
    return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2166 2167
  }

H
Haojun Liao 已提交
2168
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
2169

2170 2171
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2172

2173
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
2174

L
Liu Jicong 已提交
2175 2176
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2177
#if 0
2178 2179 2180
  if (blockDataOrder == TSDB_ORDER_ASC) {
    // filter according to current result firstly
    if (pResInfo->numOfRes > 0) {
2181
      if (pInfo->ts < startKey) {
2182 2183 2184 2185 2186 2187 2188 2189 2190
        return TSDB_CODE_SUCCESS;
      }
    }

    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
        continue;
      }

2191 2192
      numOfElems++;

2193
      char* data = colDataGetData(pInputCol, i);
2194
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2195 2196
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2197
        break;
2198 2199 2200 2201 2202 2203
      }
    }
  } else {
    // in case of descending order time stamp serial, which usually happens as the results of the nest query,
    // all data needs to be check.
    if (pResInfo->numOfRes > 0) {
2204
      if (pInfo->ts < endKey) {
2205 2206
        return TSDB_CODE_SUCCESS;
      }
H
Haojun Liao 已提交
2207 2208
    }

2209 2210 2211 2212 2213
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
        continue;
      }

2214 2215
      numOfElems++;

2216
      char* data = colDataGetData(pInputCol, i);
2217
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2218

2219 2220
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2221
        break;
2222 2223
      }
    }
H
Haojun Liao 已提交
2224
  }
2225
#else
2226
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2227 2228 2229 2230 2231 2232 2233 2234
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
      continue;
    }

    numOfElems++;

    char* data = colDataGetData(pInputCol, i);
H
Haojun Liao 已提交
2235
    TSKEY cts = pts[i];
2236
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2237 2238 2239 2240
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
2241 2242 2243 2244
      pResInfo->numOfRes = 1;
    }
  }
#endif
H
Haojun Liao 已提交
2245

2246 2247
  if (numOfElems == 0) {
    // save selectivity value for column consisted of all null values
2248 2249 2250 2251
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2252
  }
H
Haojun Liao 已提交
2253
  SET_VAL(pResInfo, numOfElems, 1);
wmmhello's avatar
wmmhello 已提交
2254
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2255 2256
}

2257
int32_t lastFunction(SqlFunctionCtx* pCtx) {
H
Haojun Liao 已提交
2258 2259
  int32_t numOfElems = 0;

2260
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2261
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
H
Haojun Liao 已提交
2262 2263

  SInputColumnInfoData* pInput = &pCtx->input;
2264
  SColumnInfoData*      pInputCol = pInput->pData[0];
H
Haojun Liao 已提交
2265

2266
  int32_t type = pInputCol->info.type;
2267
  int32_t bytes = pInputCol->info.bytes;
2268
  pInfo->bytes = bytes;
2269

G
Ganlin Zhao 已提交
2270
  if (IS_NULL_TYPE(type)) {
G
Ganlin Zhao 已提交
2271
    return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
2272 2273
  }

H
Haojun Liao 已提交
2274
  // All null data column, return directly.
G
Ganlin Zhao 已提交
2275
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && pInputCol->hasNull == true) {
2276
    // save selectivity value for column consisted of all null values
2277 2278 2279 2280
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
G
Ganlin Zhao 已提交
2281
    return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2282 2283
  }

H
Haojun Liao 已提交
2284
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
2285 2286 2287 2288

  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);

2289
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
2290

L
Liu Jicong 已提交
2291 2292
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
  //  function.
2293
#if 0
2294
  if (blockDataOrder == TSDB_ORDER_ASC) {
H
Haojun Liao 已提交
2295
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2296
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
H
Haojun Liao 已提交
2297 2298 2299 2300
        continue;
      }

      numOfElems++;
2301 2302 2303

      char* data = colDataGetData(pInputCol, i);
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2304 2305
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
        doSaveCurrentVal(pCtx, i, cts, type, data);
2306
      }
2307

H
Haojun Liao 已提交
2308 2309
      break;
    }
2310
  } else {  // descending order
H
Haojun Liao 已提交
2311
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2312
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
H
Haojun Liao 已提交
2313 2314 2315
        continue;
      }

2316
      numOfElems++;
H
Haojun Liao 已提交
2317

2318 2319
      char* data = colDataGetData(pInputCol, i);
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2320 2321
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
        doSaveCurrentVal(pCtx, i, cts, type, data);
H
Haojun Liao 已提交
2322 2323 2324 2325
      }
      break;
    }
  }
2326
#else
H
Haojun Liao 已提交
2327
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
H
Haojun Liao 已提交
2328

H
Haojun Liao 已提交
2329
#if 0
H
Haojun Liao 已提交
2330 2331 2332 2333
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
        continue;
      }
2334

H
Haojun Liao 已提交
2335
      numOfElems++;
H
Haojun Liao 已提交
2336 2337 2338
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
        char* data = colDataGetData(pInputCol, i);
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
H
Haojun Liao 已提交
2339 2340
        pResInfo->numOfRes = 1;
      }
2341
    }
H
Haojun Liao 已提交
2342
#else
2343 2344
  if (!pInputCol->hasNull) {
    numOfElems = 1;
H
Haojun Liao 已提交
2345

2346 2347
    int32_t round = pInput->numOfRows >> 2;
    int32_t reminder = pInput->numOfRows & 0x03;
H
Haojun Liao 已提交
2348

L
Liu Jicong 已提交
2349 2350 2351
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
      int64_t cts = pts[i];
      int32_t chosen = i;
H
Haojun Liao 已提交
2352

2353 2354 2355 2356
      if (cts < pts[i + 1]) {
        cts = pts[i + 1];
        chosen = i + 1;
      }
H
Haojun Liao 已提交
2357

2358 2359 2360 2361
      if (cts < pts[i + 2]) {
        cts = pts[i + 2];
        chosen = i + 2;
      }
H
Haojun Liao 已提交
2362

2363 2364 2365 2366
      if (cts < pts[i + 3]) {
        cts = pts[i + 3];
        chosen = i + 3;
      }
H
Haojun Liao 已提交
2367

2368 2369
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
        char* data = colDataGetData(pInputCol, chosen);
2370 2371 2372 2373
        int32_t code = doSaveCurrentVal(pCtx, i, cts, type, data);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
2374
        pResInfo->numOfRes = 1;
H
Haojun Liao 已提交
2375
      }
2376
    }
H
Haojun Liao 已提交
2377

L
Liu Jicong 已提交
2378 2379 2380
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
        char* data = colDataGetData(pInputCol, i);
2381 2382 2383 2384
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], type, data);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
L
Liu Jicong 已提交
2385 2386 2387 2388 2389 2390 2391
        pResInfo->numOfRes = 1;
      }
    }
  } else {
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
        continue;
H
Haojun Liao 已提交
2392 2393
      }

2394
      numOfElems++;
H
Haojun Liao 已提交
2395

2396 2397
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
        char* data = colDataGetData(pInputCol, i);
2398 2399 2400 2401
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], type, data);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
2402
        pResInfo->numOfRes = 1;
H
Haojun Liao 已提交
2403 2404
      }
    }
2405
  }
H
Haojun Liao 已提交
2406
#endif
H
Haojun Liao 已提交
2407

2408
#endif
H
Haojun Liao 已提交
2409 2410

  // save selectivity value for column consisted of all null values
2411
  if (numOfElems == 0) {
2412 2413 2414 2415
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2416
  }
H
Haojun Liao 已提交
2417

2418
  //  SET_VAL(pResInfo, numOfElems, 1);
wmmhello's avatar
wmmhello 已提交
2419
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2420
}
H
Haojun Liao 已提交
2421

5
54liuyao 已提交
2422
static int32_t firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
G
Ganlin Zhao 已提交
2423
  if (pOutput->hasResult) {
2424
    if (isFirst) {
2425
      if (pInput->ts > pOutput->ts) {
5
54liuyao 已提交
2426
        return TSDB_CODE_FAILED;
2427 2428
      }
    } else {
2429
      if (pInput->ts < pOutput->ts) {
5
54liuyao 已提交
2430
        return TSDB_CODE_FAILED;
2431
      }
G
Ganlin Zhao 已提交
2432 2433
    }
  }
2434

2435 2436 2437 2438
  pOutput->isNull = pInput->isNull;
  pOutput->ts = pInput->ts;
  pOutput->bytes = pInput->bytes;

G
Ganlin Zhao 已提交
2439
  memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
5
54liuyao 已提交
2440 2441
  return TSDB_CODE_SUCCESS;
}
G
Ganlin Zhao 已提交
2442

2443
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
5
54liuyao 已提交
2444 2445
                                  int32_t rowIndex) {
  if (TSDB_CODE_SUCCESS == firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
2446 2447 2448 2449
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
5
54liuyao 已提交
2450 2451
    pOutput->hasResult = true;
  }
2452 2453

  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
2454 2455
}

2456
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
G
Ganlin Zhao 已提交
2457
  SInputColumnInfoData* pInput = &pCtx->input;
2458
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
2459 2460 2461
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
G
Ganlin Zhao 已提交
2462 2463 2464

  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

2465 2466
  int32_t start = pInput->startRowIndex;
  int32_t numOfElems = 0;
G
Ganlin Zhao 已提交
2467

X
Xiaoyu Wang 已提交
2468 2469
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
    char*          data = colDataGetData(pCol, i);
2470
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
2471 2472 2473 2474
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2475 2476 2477 2478
    if (!numOfElems) {
      numOfElems = pInputInfo->hasResult ? 1 : 0;
    }
  }
2479 2480

  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
G
Ganlin Zhao 已提交
2481 2482 2483
  return TSDB_CODE_SUCCESS;
}

2484
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
2485

2486
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
2487

2488
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
2489
  int32_t          code = TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
2490 2491 2492 2493 2494 2495
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;

G
Ganlin Zhao 已提交
2496
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
X
Xiaoyu Wang 已提交
2497
  colDataAppend(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
2498

2499
  // handle selectivity
G
Ganlin Zhao 已提交
2500
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
G
Ganlin Zhao 已提交
2501

G
Ganlin Zhao 已提交
2502
  return code;
G
Ganlin Zhao 已提交
2503 2504
}

G
Ganlin Zhao 已提交
2505
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
2506 2507
  int32_t code = TSDB_CODE_SUCCESS;

G
Ganlin Zhao 已提交
2508
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2509
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2510

2511
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes);
G
Ganlin Zhao 已提交
2512

2513 2514
  // todo check for failure
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
G
Ganlin Zhao 已提交
2515
  memcpy(varDataVal(res), pRes, resultBytes);
2516

G
Ganlin Zhao 已提交
2517 2518 2519 2520 2521 2522
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);
G
Ganlin Zhao 已提交
2523
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
G
Ganlin Zhao 已提交
2524 2525

  taosMemoryFree(res);
G
Ganlin Zhao 已提交
2526
  return code;
G
Ganlin Zhao 已提交
2527 2528
}

5
54liuyao 已提交
2529 2530
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
2531
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
2532
  int32_t              bytes = pDBuf->bytes;
5
54liuyao 已提交
2533 2534

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
2535
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
5
54liuyao 已提交
2536

5
54liuyao 已提交
2537 2538
  if (TSDB_CODE_SUCCESS == firstLastTransferInfoImpl(pSBuf, pDBuf, false)) {
    pDBuf->hasResult = true;
5
54liuyao 已提交
2539
  }
5
54liuyao 已提交
2540 2541 2542

  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
5
54liuyao 已提交
2543 2544 2545
  return TSDB_CODE_SUCCESS;
}

2546
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562
  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pInputCol = pInput->pData[0];

  if (colDataIsNull_s(pInputCol, rowIndex)) {
    pInfo->isNull = true;
  } else {
    pInfo->isNull = false;

    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
      pInfo->bytes = varDataTLen(pData);
    }

    memcpy(pInfo->buf, pData, pInfo->bytes);
  }

  pInfo->ts = cts;
2563 2564 2565 2566
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo);
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
2567 2568

  pInfo->hasResult = true;
2569 2570

  return TSDB_CODE_SUCCESS;
2571 2572
}

2573 2574 2575 2576 2577 2578 2579 2580 2581
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
  int32_t numOfElems = 0;

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pInputCol = pInput->pData[0];

L
Liu Jicong 已提交
2582
  int32_t type = pInputCol->info.type;
2583 2584 2585
  int32_t bytes = pInputCol->info.bytes;
  pInfo->bytes = bytes;

G
Ganlin Zhao 已提交
2586 2587 2588 2589
  if (IS_NULL_TYPE(type)) {
    return TSDB_CODE_SUCCESS;
  }

2590 2591 2592
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);

2593
#if 0
2594 2595
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;

H
Haojun Liao 已提交
2596 2597
  // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
  // this assumption is NOT always works if project operator exists in downstream.
2598 2599 2600 2601
  if (blockDataOrder == TSDB_ORDER_ASC) {
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
      char* data = colDataGetData(pInputCol, i);
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2602 2603 2604 2605
      numOfElems++;

      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
        doSaveLastrow(pCtx, data, i, cts, pInfo);
2606
      }
2607

2608 2609 2610 2611 2612 2613
      break;
    }
  } else {  // descending order
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
      char* data = colDataGetData(pInputCol, i);
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2614 2615 2616 2617
      numOfElems++;

      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
        doSaveLastrow(pCtx, data, i, cts, pInfo);
2618 2619 2620 2621
      }
      break;
    }
  }
2622
#else
H
Haojun Liao 已提交
2623 2624

  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2625
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2626 2627
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
H
Haojun Liao 已提交
2628
    TSKEY cts = pts[i];
2629

H
Haojun Liao 已提交
2630
    numOfElems++;
2631
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2632 2633 2634 2635
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
2636 2637 2638
      pResInfo->numOfRes = 1;
    }
  }
2639

2640
#endif
2641

2642 2643 2644 2645
  SET_VAL(pResInfo, numOfElems, 1);
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
2646 2647 2648 2649 2650
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SDiffInfo);
  return true;
}

2651
bool diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
H
Haojun Liao 已提交
2652 2653 2654 2655 2656
  if (!functionSetup(pCtx, pResInfo)) {
    return false;
  }

  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2657
  pDiffInfo->hasPrev = false;
H
Haojun Liao 已提交
2658
  pDiffInfo->prev.i64 = 0;
2659
  pDiffInfo->prevTs = -1;
2660 2661 2662 2663 2664
  if (pCtx->numOfParams > 1) {
    pDiffInfo->ignoreNegative = pCtx->param[1].param.i;  // TODO set correct param
  } else {
    pDiffInfo->ignoreNegative = false;
  }
H
Haojun Liao 已提交
2665 2666
  pDiffInfo->includeNull = false;
  pDiffInfo->firstOutput = false;
H
Haojun Liao 已提交
2667 2668 2669
  return true;
}

G
Ganlin Zhao 已提交
2670
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
X
Xiaoyu Wang 已提交
2671
  switch (type) {
2672
    case TSDB_DATA_TYPE_BOOL:
L
Liu Jicong 已提交
2673
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
2674
      break;
2675
    case TSDB_DATA_TYPE_TINYINT:
X
Xiaoyu Wang 已提交
2676 2677
      pDiffInfo->prev.i64 = *(int8_t*)pv;
      break;
2678
    case TSDB_DATA_TYPE_INT:
X
Xiaoyu Wang 已提交
2679 2680
      pDiffInfo->prev.i64 = *(int32_t*)pv;
      break;
2681
    case TSDB_DATA_TYPE_SMALLINT:
X
Xiaoyu Wang 已提交
2682 2683
      pDiffInfo->prev.i64 = *(int16_t*)pv;
      break;
2684
    case TSDB_DATA_TYPE_TIMESTAMP:
2685
    case TSDB_DATA_TYPE_BIGINT:
X
Xiaoyu Wang 已提交
2686 2687
      pDiffInfo->prev.i64 = *(int64_t*)pv;
      break;
2688
    case TSDB_DATA_TYPE_FLOAT:
X
Xiaoyu Wang 已提交
2689 2690
      pDiffInfo->prev.d64 = *(float*)pv;
      break;
2691
    case TSDB_DATA_TYPE_DOUBLE:
X
Xiaoyu Wang 已提交
2692 2693
      pDiffInfo->prev.d64 = *(double*)pv;
      break;
2694
    default:
G
Ganlin Zhao 已提交
2695
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
2696
  }
2697
  pDiffInfo->prevTs = ts;
G
Ganlin Zhao 已提交
2698 2699

  return TSDB_CODE_SUCCESS;
2700 2701
}

G
Ganlin Zhao 已提交
2702
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2703
                         int32_t order, int64_t ts) {
X
Xiaoyu Wang 已提交
2704
  int32_t factor = (order == TSDB_ORDER_ASC) ? 1 : -1;
2705
  pDiffInfo->prevTs = ts;
2706 2707 2708
  switch (type) {
    case TSDB_DATA_TYPE_INT: {
      int32_t v = *(int32_t*)pv;
X
Xiaoyu Wang 已提交
2709
      int64_t delta = factor * (v - pDiffInfo->prev.i64);  // direct previous may be null
2710
      if (delta < 0 && pDiffInfo->ignoreNegative) {
2711
        colDataSetNull_f_s(pOutput, pos);
2712
      } else {
2713
        colDataAppendInt64(pOutput, pos, &delta);
2714 2715
      }
      pDiffInfo->prev.i64 = v;
2716

2717 2718 2719 2720
      break;
    }
    case TSDB_DATA_TYPE_BOOL:
    case TSDB_DATA_TYPE_TINYINT: {
X
Xiaoyu Wang 已提交
2721 2722
      int8_t  v = *(int8_t*)pv;
      int64_t delta = factor * (v - pDiffInfo->prev.i64);  // direct previous may be null
2723
      if (delta < 0 && pDiffInfo->ignoreNegative) {
2724
        colDataSetNull_f_s(pOutput, pos);
2725
      } else {
2726
        colDataAppendInt64(pOutput, pos, &delta);
2727 2728 2729 2730 2731 2732
      }
      pDiffInfo->prev.i64 = v;
      break;
    }
    case TSDB_DATA_TYPE_SMALLINT: {
      int16_t v = *(int16_t*)pv;
X
Xiaoyu Wang 已提交
2733
      int64_t delta = factor * (v - pDiffInfo->prev.i64);  // direct previous may be null
2734
      if (delta < 0 && pDiffInfo->ignoreNegative) {
2735
        colDataSetNull_f_s(pOutput, pos);
2736
      } else {
2737
        colDataAppendInt64(pOutput, pos, &delta);
2738 2739 2740 2741
      }
      pDiffInfo->prev.i64 = v;
      break;
    }
2742
    case TSDB_DATA_TYPE_TIMESTAMP:
2743 2744
    case TSDB_DATA_TYPE_BIGINT: {
      int64_t v = *(int64_t*)pv;
X
Xiaoyu Wang 已提交
2745
      int64_t delta = factor * (v - pDiffInfo->prev.i64);  // direct previous may be null
2746
      if (delta < 0 && pDiffInfo->ignoreNegative) {
2747
        colDataSetNull_f_s(pOutput, pos);
2748 2749 2750 2751 2752 2753 2754
      } else {
        colDataAppendInt64(pOutput, pos, &delta);
      }
      pDiffInfo->prev.i64 = v;
      break;
    }
    case TSDB_DATA_TYPE_FLOAT: {
X
Xiaoyu Wang 已提交
2755 2756 2757
      float  v = *(float*)pv;
      double delta = factor * (v - pDiffInfo->prev.d64);                               // direct previous may be null
      if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) {  // check for overflow
2758
        colDataSetNull_f_s(pOutput, pos);
2759
      } else {
2760
        colDataAppendDouble(pOutput, pos, &delta);
2761 2762 2763 2764 2765 2766
      }
      pDiffInfo->prev.d64 = v;
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
      double v = *(double*)pv;
X
Xiaoyu Wang 已提交
2767 2768
      double delta = factor * (v - pDiffInfo->prev.d64);                               // direct previous may be null
      if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) {  // check for overflow
2769
        colDataSetNull_f_s(pOutput, pos);
2770 2771 2772 2773 2774 2775 2776
      } else {
        colDataAppendDouble(pOutput, pos, &delta);
      }
      pDiffInfo->prev.d64 = v;
      break;
    }
    default:
G
Ganlin Zhao 已提交
2777
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
2778
  }
G
Ganlin Zhao 已提交
2779 2780

  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
2781
}
2782

2783 2784 2785
int32_t diffFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
H
Haojun Liao 已提交
2786 2787 2788

  SInputColumnInfoData* pInput = &pCtx->input;

2789
  SColumnInfoData* pInputCol = pInput->pData[0];
H
Haojun Liao 已提交
2790

2791 2792
  TSKEY* tsList = (int64_t*)pInput->pPTS->pData;

2793
  int32_t numOfElems = 0;
H
Haojun Liao 已提交
2794
  int32_t startOffset = pCtx->offset;
H
Haojun Liao 已提交
2795

2796
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
H
Haojun Liao 已提交
2797

2798 2799 2800
  if (pCtx->order == TSDB_ORDER_ASC) {
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
      int32_t pos = startOffset + numOfElems;
H
Haojun Liao 已提交
2801

2802 2803
      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        if (pDiffInfo->includeNull) {
2804
          colDataSetNull_f_s(pOutput, pos);
H
Haojun Liao 已提交
2805

2806
          numOfElems += 1;
H
Haojun Liao 已提交
2807
        }
2808
        continue;
H
Haojun Liao 已提交
2809 2810
      }

2811
      char* pv = colDataGetData(pInputCol, i);
H
Haojun Liao 已提交
2812

2813
      if (pDiffInfo->hasPrev) {
2814 2815 2816
        if (tsList[i] == pDiffInfo->prevTs) {
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
        }
G
Ganlin Zhao 已提交
2817 2818 2819 2820
        int32_t code = doHandleDiff(pDiffInfo, pInputCol->info.type, pv, pOutput, pos, pCtx->order, tsList[i]);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
2821
        // handle selectivity
2822 2823 2824
        if (pCtx->subsidiaries.num > 0) {
          appendSelectivityValue(pCtx, i, pos);
        }
H
Haojun Liao 已提交
2825 2826

        numOfElems++;
2827
      } else {
G
Ganlin Zhao 已提交
2828 2829 2830 2831
        int32_t code = doSetPrevVal(pDiffInfo, pInputCol->info.type, pv, tsList[i]);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
H
Haojun Liao 已提交
2832 2833
      }

2834 2835 2836 2837 2838 2839 2840 2841
      pDiffInfo->hasPrev = true;
    }
  } else {
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
      int32_t pos = startOffset + numOfElems;

      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        if (pDiffInfo->includeNull) {
2842
          colDataSetNull_f_s(pOutput, pos);
2843
          numOfElems += 1;
H
Haojun Liao 已提交
2844
        }
2845
        continue;
H
Haojun Liao 已提交
2846 2847
      }

2848
      char* pv = colDataGetData(pInputCol, i);
H
Haojun Liao 已提交
2849

2850 2851
      // there is a row of previous data block to be handled in the first place.
      if (pDiffInfo->hasPrev) {
2852 2853 2854
        if (tsList[i] == pDiffInfo->prevTs) {
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
        }
G
Ganlin Zhao 已提交
2855 2856 2857 2858
        int32_t code = doHandleDiff(pDiffInfo, pInputCol->info.type, pv, pOutput, pos, pCtx->order, tsList[i]);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
2859
        // handle selectivity
2860 2861 2862
        if (pCtx->subsidiaries.num > 0) {
          appendSelectivityValue(pCtx, i, pos);
        }
H
Haojun Liao 已提交
2863 2864

        numOfElems++;
2865
      } else {
G
Ganlin Zhao 已提交
2866 2867 2868 2869
        int32_t code = doSetPrevVal(pDiffInfo, pInputCol->info.type, pv, tsList[i]);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
H
Haojun Liao 已提交
2870 2871
      }

2872
      pDiffInfo->hasPrev = true;
H
Haojun Liao 已提交
2873 2874 2875
    }
  }

2876 2877
  pResInfo->numOfRes = numOfElems;
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2878
}
H
Haojun Liao 已提交
2879

X
Xiaoyu Wang 已提交
2880
int32_t getTopBotInfoSize(int64_t numOfItems) { return sizeof(STopBotRes) + numOfItems * sizeof(STopBotResItem); }
G
Ganlin Zhao 已提交
2881

2882
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2883
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2884
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2885 2886 2887
  return true;
}

G
Ganlin Zhao 已提交
2888 2889 2890 2891 2892
bool topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
  if (!functionSetup(pCtx, pResInfo)) {
    return false;
  }

X
Xiaoyu Wang 已提交
2893
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
2894 2895 2896 2897
  SInputColumnInfoData* pInput = &pCtx->input;

  pRes->maxSize = pCtx->param[1].param.i;

2898 2899
  pRes->nullTupleSaved = false;
  pRes->nullTuplePos.pageId = -1;
G
Ganlin Zhao 已提交
2900 2901 2902
  return true;
}

2903 2904 2905 2906
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
2907 2908

  return pRes;
2909 2910
}

G
Ganlin Zhao 已提交
2911 2912
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
                               uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
2913

G
Ganlin Zhao 已提交
2914 2915
static void addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery);

2916 2917 2918
int32_t topFunction(SqlFunctionCtx* pCtx) {
  int32_t              numOfElems = 0;
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2919 2920

  SInputColumnInfoData* pInput = &pCtx->input;
2921
  SColumnInfoData*      pCol = pInput->pData[0];
2922

G
Ganlin Zhao 已提交
2923 2924
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
  pRes->type = pInput->pData[0]->info.type;
2925 2926

  int32_t start = pInput->startRowIndex;
2927
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2928 2929 2930
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
      continue;
    }
2931

2932
    numOfElems++;
2933
    char* data = colDataGetData(pCol, i);
G
Ganlin Zhao 已提交
2934 2935 2936 2937
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2938 2939
  }

2940
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
G
Ganlin Zhao 已提交
2941 2942 2943 2944
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2945 2946
    pRes->nullTupleSaved = true;
  }
2947 2948 2949
  return TSDB_CODE_SUCCESS;
}

2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
  int32_t              numOfElems = 0;
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pCol = pInput->pData[0];

  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
  pRes->type = pInput->pData[0]->info.type;

  int32_t start = pInput->startRowIndex;
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
      continue;
    }

    numOfElems++;
    char* data = colDataGetData(pCol, i);
G
Ganlin Zhao 已提交
2968 2969 2970 2971
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2972 2973
  }

2974
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
G
Ganlin Zhao 已提交
2975 2976 2977 2978
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
2979 2980 2981
    pRes->nullTupleSaved = true;
  }

2982 2983 2984
  return TSDB_CODE_SUCCESS;
}

2985 2986
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
  uint16_t type = *(uint16_t*)param;
2987

2988 2989
  STopBotResItem* val1 = (STopBotResItem*)p1;
  STopBotResItem* val2 = (STopBotResItem*)p2;
2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002

  if (IS_SIGNED_NUMERIC_TYPE(type)) {
    if (val1->v.i == val2->v.i) {
      return 0;
    }

    return (val1->v.i > val2->v.i) ? 1 : -1;
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
    if (val1->v.u == val2->v.u) {
      return 0;
    }

    return (val1->v.u > val2->v.u) ? 1 : -1;
3003 3004 3005 3006 3007 3008
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
    if (val1->v.f == val2->v.f) {
      return 0;
    }

    return (val1->v.f > val2->v.f) ? 1 : -1;
3009 3010 3011 3012 3013 3014 3015 3016 3017
  }

  if (val1->v.d == val2->v.d) {
    return 0;
  }

  return (val1->v.d > val2->v.d) ? 1 : -1;
}

G
Ganlin Zhao 已提交
3018
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
3019
                     uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3020
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
3021

3022 3023 3024
  SVariant val = {0};
  taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type);

3025
  STopBotResItem* pItems = pRes->pItems;
3026 3027

  // not full yet
G
Ganlin Zhao 已提交
3028
  if (pEntryInfo->numOfRes < pRes->maxSize) {
3029
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
3030
    pItem->v = val;
3031
    pItem->uid = uid;
3032

3033
    // save the data of this tuple
G
Ganlin Zhao 已提交
3034
    if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
3035 3036 3037 3038
      int32_t code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
G
Ganlin Zhao 已提交
3039
    }
3040
#ifdef BUF_PAGE_DEBUG
X
Xiaoyu Wang 已提交
3041 3042
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
           pItem->tuplePos.offset);
3043
#endif
3044 3045
    // allocate the buffer and keep the data of this row into the new allocated buffer
    pEntryInfo->numOfRes++;
3046
    taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type, topBotResComparFn,
3047
                 !isTopQuery);
3048
  } else {  // replace the minimum value in the result
X
Xiaoyu Wang 已提交
3049 3050
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
3051 3052
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
X
Xiaoyu Wang 已提交
3053 3054
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
3055 3056
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
3057
      // replace the old data and the coresponding tuple data
3058
      STopBotResItem* pItem = &pItems[0];
3059
      pItem->v = val;
3060
      pItem->uid = uid;
3061 3062

      // save the data of this tuple by over writing the old data
G
Ganlin Zhao 已提交
3063
      if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
3064 3065 3066 3067
        int32_t code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
G
Ganlin Zhao 已提交
3068
      }
3069
#ifdef BUF_PAGE_DEBUG
wmmhello's avatar
wmmhello 已提交
3070
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3071
#endif
3072
      taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
3073
                     topBotResComparFn, NULL, !isTopQuery);
3074
    }
3075
  }
G
Ganlin Zhao 已提交
3076 3077

  return TSDB_CODE_SUCCESS;
3078
}
3079

3080 3081 3082 3083 3084 3085
/*
 * +------------------------------------+--------------+--------------+
 * |            null bitmap             |              |              |
 * |(n columns, one bit for each column)| src column #1| src column #2|
 * +------------------------------------+--------------+--------------+
 */
L
Liu Jicong 已提交
3086 3087
void* serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
                         char* buf) {
3088 3089
  char* nullList = buf;
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
3090 3091

  int32_t offset = 0;
3092 3093
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
wmmhello's avatar
wmmhello 已提交
3094 3095 3096 3097 3098 3099

    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
    int32_t      srcSlotId = pFuncParam->pCol->slotId;

    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
3100
      offset += pCol->info.bytes;
3101 3102 3103 3104 3105
      continue;
    }

    char* p = colDataGetData(pCol, rowIndex);
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
X
Xiaoyu Wang 已提交
3106
      memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
3107 3108 3109 3110 3111 3112 3113
    } else {
      memcpy(pStart + offset, p, pCol->info.bytes);
    }

    offset += pCol->info.bytes;
  }

3114
  return buf;
3115 3116
}

G
Ganlin Zhao 已提交
3117 3118
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STupleKey key,
                               STuplePos* pPos) {
3119 3120 3121
  STuplePos p = {0};
  if (pHandle->pBuf != NULL) {
    SFilePage* pPage = NULL;
3122

3123 3124
    if (pHandle->currentPage == -1) {
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
3125
      if (pPage == NULL) {
G
Ganlin Zhao 已提交
3126
        return terrno;
3127
      }
3128 3129 3130
      pPage->num = sizeof(SFilePage);
    } else {
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
3131
      if (pPage == NULL) {
G
Ganlin Zhao 已提交
3132
        return terrno;
3133
      }
3134 3135 3136 3137
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
        // current page is all used, let's prepare a new buffer page
        releaseBufPage(pHandle->pBuf, pPage);
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
3138
        if (pPage == NULL) {
G
Ganlin Zhao 已提交
3139
          return terrno;
3140
        }
3141 3142 3143
        pPage->num = sizeof(SFilePage);
      }
    }
3144

G
Ganlin Zhao 已提交
3145
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
3146
    memcpy(pPage->data + pPage->num, pBuf, length);
3147

3148 3149 3150 3151 3152
    pPage->num += length;
    setBufPageDirty(pPage, true);
    releaseBufPage(pHandle->pBuf, pPage);
  } else {
    // other tuple save policy
G
Ganlin Zhao 已提交
3153 3154
    if (streamStateFuncPut(pHandle->pState, &key, pBuf, length) >= 0) {
      p.streamTupleKey = key;
3155
    }
3156
  }
wmmhello's avatar
wmmhello 已提交
3157

G
Ganlin Zhao 已提交
3158 3159
  *pPos = p;
  return TSDB_CODE_SUCCESS;
3160
}
3161

G
Ganlin Zhao 已提交
3162
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
3163 3164
  prepareBuf(pCtx);

L
Liu Jicong 已提交
3165 3166 3167
  STupleKey key;
  if (pCtx->saveHandle.pBuf == NULL) {
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, 0);
G
Ganlin Zhao 已提交
3168 3169
    if (pColInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
      int64_t skey = *(int64_t*)colDataGetData(pColInfo, rowIndex);
L
Liu Jicong 已提交
3170

G
Ganlin Zhao 已提交
3171 3172 3173 3174
      key.groupId = pSrcBlock->info.id.groupId;
      key.ts = skey;
      key.exprIdx = pCtx->exprIdx;
    }
L
Liu Jicong 已提交
3175 3176
  }

3177
  char* buf = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf);
G
Ganlin Zhao 已提交
3178
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, key, pPos);
3179 3180 3181 3182 3183
}

static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos) {
  if (pHandle->pBuf != NULL) {
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
G
Ganlin Zhao 已提交
3184 3185 3186
    if (pPage == NULL) {
      return terrno;
    }
3187 3188 3189 3190
    memcpy(pPage->data + pPos->offset, pBuf, length);
    setBufPageDirty(pPage, true);
    releaseBufPage(pHandle->pBuf, pPage);
  } else {
3191
    streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
3192 3193 3194 3195 3196
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
3197
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
3198 3199
  prepareBuf(pCtx);

3200
  char* buf = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf);
G
Ganlin Zhao 已提交
3201
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos);
3202 3203 3204 3205 3206
}

static char* doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos) {
  if (pHandle->pBuf != NULL) {
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
G
Ganlin Zhao 已提交
3207 3208 3209
    if (pPage == NULL) {
      return NULL;
    }
L
Liu Jicong 已提交
3210
    char*      p = pPage->data + pPos->offset;
3211 3212 3213
    releaseBufPage(pHandle->pBuf, pPage);
    return p;
  } else {
3214 3215 3216 3217
    void*   value = NULL;
    int32_t vLen;
    streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, &value, &vLen);
    return (char*)value;
3218 3219 3220
  }
}

H
Haojun Liao 已提交
3221
const char* loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos) {
3222
  return doLoadTupleData(&pCtx->saveHandle, pPos);
3223 3224
}

3225
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
3226 3227
  int32_t code = TSDB_CODE_SUCCESS;

3228
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
3229
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
3230

3231
  int16_t type = pCtx->pExpr->base.resSchema.type;
3232 3233
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;

3234 3235 3236 3237
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  // todo assign the tag value and the corresponding row data
  int32_t currentRow = pBlock->info.rows;
3238 3239
  if (pEntryInfo->numOfRes <= 0) {
    colDataAppendNULL(pCol, currentRow);
G
Ganlin Zhao 已提交
3240 3241
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
    return code;
3242
  }
3243 3244
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
    STopBotResItem* pItem = &pRes->pItems[i];
3245
    colDataAppend(pCol, currentRow, (const char*)&pItem->v.i, false);
3246
#ifdef BUF_PAGE_DEBUG
X
Xiaoyu Wang 已提交
3247 3248
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
           pItem->tuplePos.offset);
3249
#endif
G
Ganlin Zhao 已提交
3250
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
3251
    currentRow += 1;
3252 3253
  }

G
Ganlin Zhao 已提交
3254
  return code;
3255
}
G
Ganlin Zhao 已提交
3256

X
Xiaoyu Wang 已提交
3257
void addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
3258
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
3259 3260
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
  STopBotResItem*      pItems = pRes->pItems;
3261 3262

  // not full yet
G
Ganlin Zhao 已提交
3263
  if (pEntryInfo->numOfRes < pRes->maxSize) {
3264 3265 3266 3267 3268 3269 3270 3271 3272
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
    pItem->v = pSourceItem->v;
    pItem->uid = pSourceItem->uid;
    pItem->tuplePos.pageId = -1;
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
    pEntryInfo->numOfRes++;
    taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type, topBotResComparFn,
                 !isTopQuery);
  } else {  // replace the minimum value in the result
X
Xiaoyu Wang 已提交
3273 3274
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
3275 3276
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
X
Xiaoyu Wang 已提交
3277 3278
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
3279 3280
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296
      // replace the old data and the coresponding tuple data
      STopBotResItem* pItem = &pItems[0];
      pItem->v = pSourceItem->v;
      pItem->uid = pSourceItem->uid;

      // save the data of this tuple by over writing the old data
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
      taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
                     topBotResComparFn, NULL, !isTopQuery);
    }
  }
}

int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
3297
  int16_t              type = pSBuf->type;
3298 3299 3300 3301 3302 3303 3304 3305 3306
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
    addResult(pDestCtx, pSBuf->pItems + i, type, true);
  }
  return TSDB_CODE_SUCCESS;
}

int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
3307
  int16_t              type = pSBuf->type;
3308 3309 3310 3311 3312 3313
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
    addResult(pDestCtx, pSBuf->pItems + i, type, false);
  }
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
3314
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
G
Ganlin Zhao 已提交
3315

G
Ganlin Zhao 已提交
3316 3317 3318 3319 3320
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SSpreadInfo);
  return true;
}

X
Xiaoyu Wang 已提交
3321
bool spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
G
Ganlin Zhao 已提交
3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
  pInfo->hasResult = false;
  return true;
}

X
Xiaoyu Wang 已提交
3333
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
3334 3335 3336 3337
  int32_t numOfElems = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
3338 3339
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
  int32_t               type = pInput->pData[0]->info.type;
G
Ganlin Zhao 已提交
3340 3341 3342

  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

H
Haojun Liao 已提交
3343
  if (pInput->colDataSMAIsSet) {
G
Ganlin Zhao 已提交
3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
    if (numOfElems == 0) {
      goto _spread_over;
    }
    double tmin = 0.0, tmax = 0.0;
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
      tmin = (double)GET_INT64_VAL(&pAgg->min);
      tmax = (double)GET_INT64_VAL(&pAgg->max);
    } else if (IS_FLOAT_TYPE(type)) {
      tmin = GET_DOUBLE_VAL(&pAgg->min);
      tmax = GET_DOUBLE_VAL(&pAgg->max);
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
    }

    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
      SET_DOUBLE_VAL(&pInfo->min, tmin);
    }

    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
      SET_DOUBLE_VAL(&pInfo->max, tmax);
    }

  } else {  // computing based on the true data block
    SColumnInfoData* pCol = pInput->pData[0];

X
Xiaoyu Wang 已提交
3371
    int32_t start = pInput->startRowIndex;
G
Ganlin Zhao 已提交
3372 3373 3374 3375 3376 3377
    // check the valid data one by one
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
        continue;
      }

X
Xiaoyu Wang 已提交
3378
      char* data = colDataGetData(pCol, i);
G
Ganlin Zhao 已提交
3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403

      double v = 0;
      GET_TYPED_DATA(v, double, type, data);
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
        SET_DOUBLE_VAL(&pInfo->min, v);
      }

      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
        SET_DOUBLE_VAL(&pInfo->max, v);
      }

      numOfElems += 1;
    }
  }

_spread_over:
  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
  if (numOfElems > 0) {
    pInfo->hasResult = true;
  }

  return TSDB_CODE_SUCCESS;
}

3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
  pOutput->hasResult = pInput->hasResult;
  if (pInput->max > pOutput->max) {
    pOutput->max = pInput->max;
  }

  if (pInput->min < pOutput->min) {
    pOutput->min = pInput->min;
  }
}

X
Xiaoyu Wang 已提交
3415
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
3416
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
3417
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
3418 3419 3420
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
3421 3422 3423

  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

3424
  int32_t start = pInput->startRowIndex;
X
Xiaoyu Wang 已提交
3425 3426
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
    char*        data = colDataGetData(pCol, i);
3427
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
3428 3429 3430
    if (pInputInfo->hasResult) {
      spreadTransferInfo(pInputInfo, pInfo);
    }
3431
  }
3432

3433 3434 3435
  if (pInfo->hasResult) {
    GET_RES_INFO(pCtx)->numOfRes = 1;
  }
3436 3437 3438 3439

  return TSDB_CODE_SUCCESS;
}

G
Ganlin Zhao 已提交
3440 3441 3442 3443
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  if (pInfo->hasResult == true) {
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
3444 3445
  } else {
    GET_RES_INFO(pCtx)->isNullRes = 1;
G
Ganlin Zhao 已提交
3446 3447 3448
  }
  return functionFinalize(pCtx, pBlock);
}
3449

3450 3451
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3452 3453 3454
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              resultBytes = getSpreadInfoSize();
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467

  memcpy(varDataVal(res), pInfo, resultBytes);
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);

  taosMemoryFree(res);
  return pResInfo->numOfRes;
}

3468 3469
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
3470
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3471 3472

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
X
Xiaoyu Wang 已提交
3473
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3474
  spreadTransferInfo(pSBuf, pDBuf);
3475
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
3476
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3477 3478 3479
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
3480
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
3481

G
Ganlin Zhao 已提交
3482 3483 3484 3485 3486
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SElapsedInfo);
  return true;
}

X
Xiaoyu Wang 已提交
3487
bool elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
G
Ganlin Zhao 已提交
3488 3489 3490 3491 3492 3493
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
  pInfo->result = 0;
H
Hongze Cheng 已提交
3494
  pInfo->min = TSKEY_MAX;
G
Ganlin Zhao 已提交
3495 3496
  pInfo->max = 0;

3497
  if (pCtx->numOfParams > 1) {
G
Ganlin Zhao 已提交
3498 3499 3500 3501 3502 3503 3504 3505
    pInfo->timeUnit = pCtx->param[1].param.i;
  } else {
    pInfo->timeUnit = 1;
  }

  return true;
}

X
Xiaoyu Wang 已提交
3506
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
3507 3508 3509 3510
  int32_t numOfElems = 0;

  // Only the pre-computing information loaded and actual data does not loaded
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
3511
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
G
Ganlin Zhao 已提交
3512 3513 3514

  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

X
Xiaoyu Wang 已提交
3515
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
G
Ganlin Zhao 已提交
3516 3517 3518 3519
  if (numOfElems == 0) {
    goto _elapsed_over;
  }

H
Haojun Liao 已提交
3520
  if (pInput->colDataSMAIsSet) {
H
Hongze Cheng 已提交
3521
    if (pInfo->min == TSKEY_MAX) {
G
Ganlin Zhao 已提交
3522 3523 3524 3525 3526 3527 3528 3529 3530 3531
      pInfo->min = GET_INT64_VAL(&pAgg->min);
      pInfo->max = GET_INT64_VAL(&pAgg->max);
    } else {
      if (pCtx->order == TSDB_ORDER_ASC) {
        pInfo->max = GET_INT64_VAL(&pAgg->max);
      } else {
        pInfo->min = GET_INT64_VAL(&pAgg->min);
      }
    }
  } else {  // computing based on the true data block
H
Haojun Liao 已提交
3532
    if (0 == pInput->numOfRows) {
G
Ganlin Zhao 已提交
3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546
      if (pCtx->order == TSDB_ORDER_DESC) {
        if (pCtx->end.key != INT64_MIN) {
          pInfo->min = pCtx->end.key;
        }
      } else {
        if (pCtx->end.key != INT64_MIN) {
          pInfo->max = pCtx->end.key + 1;
        }
      }
      goto _elapsed_over;
    }

    SColumnInfoData* pCol = pInput->pData[0];

3547 3548
    int32_t start = pInput->startRowIndex;
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
G
Ganlin Zhao 已提交
3549 3550
    if (pCtx->order == TSDB_ORDER_DESC) {
      if (pCtx->start.key == INT64_MIN) {
3551
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
G
Ganlin Zhao 已提交
3552 3553 3554 3555
      } else {
        pInfo->max = pCtx->start.key + 1;
      }

3556
      if (pCtx->end.key == INT64_MIN) {
L
Liu Jicong 已提交
3557 3558
        pInfo->min =
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
G
Ganlin Zhao 已提交
3559
      } else {
3560
        pInfo->min = pCtx->end.key;
G
Ganlin Zhao 已提交
3561 3562 3563
      }
    } else {
      if (pCtx->start.key == INT64_MIN) {
3564
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
G
Ganlin Zhao 已提交
3565 3566 3567 3568
      } else {
        pInfo->min = pCtx->start.key;
      }

3569
      if (pCtx->end.key == INT64_MIN) {
L
Liu Jicong 已提交
3570 3571
        pInfo->max =
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
G
Ganlin Zhao 已提交
3572
      } else {
3573
        pInfo->max = pCtx->end.key + 1;
G
Ganlin Zhao 已提交
3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584
      }
    }
  }

_elapsed_over:
  // data in the check operation are all null, not output
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);

  return TSDB_CODE_SUCCESS;
}

3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
  pOutput->timeUnit = pInput->timeUnit;
  if (pOutput->min > pInput->min) {
    pOutput->min = pInput->min;
  }

  if (pOutput->max < pInput->max) {
    pOutput->max = pInput->max;
  }
}

X
Xiaoyu Wang 已提交
3596
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
3597
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
3598
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
3599 3600 3601
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
3602 3603 3604

  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

3605
  int32_t start = pInput->startRowIndex;
3606

X
Xiaoyu Wang 已提交
3607 3608
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
    char*         data = colDataGetData(pCol, i);
3609 3610 3611
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
    elapsedTransferInfo(pInputInfo, pInfo);
  }
3612 3613 3614 3615 3616

  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
  return TSDB_CODE_SUCCESS;
}

G
Ganlin Zhao 已提交
3617 3618
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
X
Xiaoyu Wang 已提交
3619
  double        result = (double)pInfo->max - (double)pInfo->min;
G
Ganlin Zhao 已提交
3620 3621 3622 3623 3624
  result = (result >= 0) ? result : -result;
  pInfo->result = result / pInfo->timeUnit;
  return functionFinalize(pCtx, pBlock);
}

3625 3626
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
3627 3628 3629
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              resultBytes = getElapsedInfoSize();
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642

  memcpy(varDataVal(res), pInfo, resultBytes);
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);

  taosMemoryFree(res);
  return pResInfo->numOfRes;
}

3643 3644
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
3645
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3646 3647

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
X
Xiaoyu Wang 已提交
3648
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3649

3650
  elapsedTransferInfo(pSBuf, pDBuf);
3651
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
3652
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3653 3654 3655
  return TSDB_CODE_SUCCESS;
}

3656 3657 3658 3659
int32_t getHistogramInfoSize() {
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
}

3660 3661 3662 3663 3664
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
  return true;
}

X
Xiaoyu Wang 已提交
3665
static int8_t getHistogramBinType(char* binTypeStr) {
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679
  int8_t binType;
  if (strcasecmp(binTypeStr, "user_input") == 0) {
    binType = USER_INPUT_BIN;
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
    binType = LINEAR_BIN;
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
    binType = LOG_BIN;
  } else {
    binType = UNKNOWN_BIN;
  }

  return binType;
}

X
Xiaoyu Wang 已提交
3680
static bool getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
3681 3682 3683 3684 3685 3686 3687
  cJSON*  binDesc = cJSON_Parse(binDescStr);
  int32_t numOfBins;
  double* intervals;
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
    int32_t startIndex;
    if (numOfParams != 4) {
3688
      cJSON_Delete(binDesc);
3689 3690 3691
      return false;
    }

X
Xiaoyu Wang 已提交
3692 3693 3694 3695
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
3696 3697 3698
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");

    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
3699
      cJSON_Delete(binDesc);
3700 3701 3702
      return false;
    }

X
Xiaoyu Wang 已提交
3703
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
3704
      cJSON_Delete(binDesc);
3705 3706 3707 3708 3709
      return false;
    }

    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
3710
      cJSON_Delete(binDesc);
3711 3712 3713
      return false;
    }

3714
    int32_t counter = (int32_t)count->valueint;
3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727
    if (infinity->valueint == false) {
      startIndex = 0;
      numOfBins = counter + 1;
    } else {
      startIndex = 1;
      numOfBins = counter + 3;
    }

    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
      // linear bin process
      if (width->valuedouble == 0) {
        taosMemoryFree(intervals);
3728
        cJSON_Delete(binDesc);
3729 3730 3731 3732 3733 3734
        return false;
      }
      for (int i = 0; i < counter + 1; ++i) {
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
        if (isinf(intervals[startIndex])) {
          taosMemoryFree(intervals);
3735
          cJSON_Delete(binDesc);
3736 3737 3738 3739 3740 3741 3742 3743
          return false;
        }
        startIndex++;
      }
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
      // log bin process
      if (start->valuedouble == 0) {
        taosMemoryFree(intervals);
3744
        cJSON_Delete(binDesc);
3745 3746 3747 3748
        return false;
      }
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
        taosMemoryFree(intervals);
3749
        cJSON_Delete(binDesc);
3750 3751 3752 3753 3754 3755
        return false;
      }
      for (int i = 0; i < counter + 1; ++i) {
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
        if (isinf(intervals[startIndex])) {
          taosMemoryFree(intervals);
3756
          cJSON_Delete(binDesc);
3757 3758 3759 3760 3761 3762
          return false;
        }
        startIndex++;
      }
    } else {
      taosMemoryFree(intervals);
3763
      cJSON_Delete(binDesc);
3764 3765 3766 3767 3768 3769 3770
      return false;
    }

    if (infinity->valueint == true) {
      intervals[0] = -INFINITY;
      intervals[numOfBins - 1] = INFINITY;
      // in case of desc bin orders, -inf/inf should be swapped
G
Ganlin Zhao 已提交
3771 3772 3773
      if (numOfBins < 4) {
        return false;
      }
3774 3775 3776 3777 3778 3779
      if (intervals[1] > intervals[numOfBins - 2]) {
        TSWAP(intervals[0], intervals[numOfBins - 1]);
      }
    }
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
    if (binType != USER_INPUT_BIN) {
3780
      cJSON_Delete(binDesc);
3781 3782
      return false;
    }
3783
    numOfBins = cJSON_GetArraySize(binDesc);
3784 3785 3786 3787
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
    cJSON* bin = binDesc->child;
    if (bin == NULL) {
      taosMemoryFree(intervals);
3788
      cJSON_Delete(binDesc);
3789 3790 3791 3792 3793 3794 3795
      return false;
    }
    int i = 0;
    while (bin) {
      intervals[i] = bin->valuedouble;
      if (!cJSON_IsNumber(bin)) {
        taosMemoryFree(intervals);
3796
        cJSON_Delete(binDesc);
3797 3798 3799 3800
        return false;
      }
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
        taosMemoryFree(intervals);
3801
        cJSON_Delete(binDesc);
3802 3803 3804 3805 3806 3807
        return false;
      }
      bin = bin->next;
      i++;
    }
  } else {
3808
    cJSON_Delete(binDesc);
3809 3810 3811
    return false;
  }

X
Xiaoyu Wang 已提交
3812
  pInfo->numOfBins = numOfBins - 1;
3813
  pInfo->normalized = normalized;
3814
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
3815 3816 3817 3818 3819 3820
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
    pInfo->bins[i].count = 0;
  }

  taosMemoryFree(intervals);
3821 3822
  cJSON_Delete(binDesc);

3823 3824 3825
  return true;
}

X
Xiaoyu Wang 已提交
3826
bool histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3827 3828 3829 3830
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

X
Xiaoyu Wang 已提交
3831
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
3832 3833 3834
  pInfo->numOfBins = 0;
  pInfo->totalCount = 0;
  pInfo->normalized = 0;
3835

L
Liu Jicong 已提交
3836
  char*  binTypeStr = strndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
3837 3838 3839
  int8_t binType = getHistogramBinType(binTypeStr);
  taosMemoryFree(binTypeStr);

3840 3841 3842
  if (binType == UNKNOWN_BIN) {
    return false;
  }
3843
  char*   binDesc = strndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
3844
  int64_t normalized = pCtx->param[3].param.i;
3845
  if (normalized != 0 && normalized != 1) {
G
Ganlin Zhao 已提交
3846
    taosMemoryFree(binDesc);
3847 3848
    return false;
  }
3849
  if (!getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized)) {
3850
    taosMemoryFree(binDesc);
3851 3852
    return false;
  }
3853
  taosMemoryFree(binDesc);
3854 3855 3856 3857

  return true;
}

3858
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
3859 3860 3861 3862 3863 3864 3865 3866 3867 3868
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pCol = pInput->pData[0];

  int32_t type = pInput->pData[0]->info.type;

  int32_t start = pInput->startRowIndex;
  int32_t numOfRows = pInput->numOfRows;

3869
  int32_t numOfElems = 0;
3870 3871 3872 3873 3874
  for (int32_t i = start; i < numOfRows + start; ++i) {
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
      continue;
    }

3875 3876
    numOfElems++;

X
Xiaoyu Wang 已提交
3877
    char*  data = colDataGetData(pCol, i);
3878 3879 3880 3881 3882 3883
    double v;
    GET_TYPED_DATA(v, double, type, data);

    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
        pInfo->bins[k].count++;
3884
        pInfo->totalCount++;
3885 3886 3887
        break;
      }
    }
3888 3889
  }

3890
  if (!isPartial) {
3891
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
3892
  } else {
3893
    GET_RES_INFO(pCtx)->numOfRes = 1;
3894
  }
3895 3896 3897
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
3898
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
3899

X
Xiaoyu Wang 已提交
3900
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
3901

3902 3903
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
  pOutput->normalized = pInput->normalized;
X
Xiaoyu Wang 已提交
3904
  pOutput->numOfBins = pInput->numOfBins;
3905 3906 3907 3908 3909 3910 3911 3912
  pOutput->totalCount += pInput->totalCount;
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
    pOutput->bins[k].lower = pInput->bins[k].lower;
    pOutput->bins[k].upper = pInput->bins[k].upper;
    pOutput->bins[k].count += pInput->bins[k].count;
  }
}

X
Xiaoyu Wang 已提交
3913
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
3914
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
3915
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
3916 3917 3918
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
  }
3919 3920 3921

  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

3922
  int32_t start = pInput->startRowIndex;
3923

X
Xiaoyu Wang 已提交
3924 3925
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
    char*           data = colDataGetData(pCol, i);
3926 3927 3928
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
    histogramTransferInfo(pInputInfo, pInfo);
  }
3929

G
Ganlin Zhao 已提交
3930
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
3931 3932 3933
  return TSDB_CODE_SUCCESS;
}

3934
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3935
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
3936 3937 3938
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
3939 3940 3941

  int32_t currentRow = pBlock->info.rows;

3942 3943
  if (pInfo->normalized) {
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
X
Xiaoyu Wang 已提交
3944
      if (pInfo->totalCount != 0) {
3945 3946 3947 3948 3949 3950 3951
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
      } else {
        pInfo->bins[k].percentage = 0;
      }
    }
  }

3952
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
3953
    int32_t len;
X
Xiaoyu Wang 已提交
3954
    char    buf[512] = {0};
3955
    if (!pInfo->normalized) {
X
Xiaoyu Wang 已提交
3956 3957
      len = sprintf(varDataVal(buf), "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}",
                    pInfo->bins[i].lower, pInfo->bins[i].upper, pInfo->bins[i].count);
3958
    } else {
X
Xiaoyu Wang 已提交
3959 3960
      len = sprintf(varDataVal(buf), "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower,
                    pInfo->bins[i].upper, pInfo->bins[i].percentage);
3961 3962 3963 3964 3965 3966
    }
    varDataSetLen(buf, len);
    colDataAppend(pCol, currentRow, buf, false);
    currentRow++;
  }

3967
  return pResInfo->numOfRes;
3968
}
3969

3970
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3971
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
3972 3973 3974
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              resultBytes = getHistogramInfoSize();
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
3975 3976 3977 3978 3979 3980 3981 3982 3983 3984

  memcpy(varDataVal(res), pInfo, resultBytes);
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);

  taosMemoryFree(res);
3985
  return pResInfo->numOfRes;
3986 3987
}

3988 3989 3990 3991 3992 3993 3994
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);

3995
  histogramTransferInfo(pSBuf, pDBuf);
3996
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
3997
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3998 3999 4000
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
4001
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
4002

4003 4004 4005 4006 4007
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SHLLInfo);
  return true;
}

X
Xiaoyu Wang 已提交
4008
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
4009
  uint64_t hash = MurmurHash3_64(data, bytes);
X
Xiaoyu Wang 已提交
4010
  int32_t  index = hash & HLL_BUCKET_MASK;
4011 4012 4013
  hash >>= HLL_BUCKET_BITS;
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
  uint64_t bit = 1;
X
Xiaoyu Wang 已提交
4014 4015
  uint8_t  count = 1;
  while ((hash & bit) == 0) {
4016 4017 4018 4019 4020 4021 4022
    count++;
    bit <<= 1;
  }
  *buk = index;
  return count;
}

X
Xiaoyu Wang 已提交
4023 4024 4025
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
  uint64_t* word = (uint64_t*)buckets;
  uint8_t*  bytes;
4026

X
Xiaoyu Wang 已提交
4027
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
4028 4029 4030
    if (*word == 0) {
      bucketHisto[0] += 8;
    } else {
X
Xiaoyu Wang 已提交
4031
      bytes = (uint8_t*)word;
4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052
      bucketHisto[bytes[0]]++;
      bucketHisto[bytes[1]]++;
      bucketHisto[bytes[2]]++;
      bucketHisto[bytes[3]]++;
      bucketHisto[bytes[4]]++;
      bucketHisto[bytes[5]]++;
      bucketHisto[bytes[6]]++;
      bucketHisto[bytes[7]]++;
    }
    word++;
  }
}
static double hllTau(double x) {
  if (x == 0. || x == 1.) return 0.;
  double zPrime;
  double y = 1.0;
  double z = 1 - x;
  do {
    x = sqrt(x);
    zPrime = z;
    y *= 0.5;
X
Xiaoyu Wang 已提交
4053 4054
    z -= pow(1 - x, 2) * y;
  } while (zPrime != z);
4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067
  return z / 3;
}

static double hllSigma(double x) {
  if (x == 1.0) return INFINITY;
  double zPrime;
  double y = 1;
  double z = x;
  do {
    x *= x;
    zPrime = z;
    z += x * y;
    y += y;
X
Xiaoyu Wang 已提交
4068
  } while (zPrime != z);
4069 4070 4071
  return z;
}

X
Xiaoyu Wang 已提交
4072 4073 4074 4075
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
// sketches"
static uint64_t hllCountCnt(uint8_t* buckets) {
  double  m = HLL_BUCKETS;
4076
  int32_t buckethisto[64] = {0};
X
Xiaoyu Wang 已提交
4077
  hllBucketHisto(buckets, buckethisto);
4078

X
Xiaoyu Wang 已提交
4079
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
4080 4081 4082 4083
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
    z += buckethisto[j];
    z *= 0.5;
  }
4084

X
Xiaoyu Wang 已提交
4085 4086
  z += m * hllSigma(buckethisto[0] / (double)m);
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
4087

X
Xiaoyu Wang 已提交
4088
  return (uint64_t)E;
4089 4090
}

X
Xiaoyu Wang 已提交
4091
int32_t hllFunction(SqlFunctionCtx* pCtx) {
4092 4093 4094 4095 4096
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pCol = pInput->pData[0];

X
Xiaoyu Wang 已提交
4097
  int32_t type = pCol->info.type;
4098 4099 4100 4101 4102 4103
  int32_t bytes = pCol->info.bytes;

  int32_t start = pInput->startRowIndex;
  int32_t numOfRows = pInput->numOfRows;

  int32_t numOfElems = 0;
G
Ganlin Zhao 已提交
4104 4105 4106 4107
  if (IS_NULL_TYPE(type)) {
    goto _hll_over;
  }

4108 4109 4110 4111 4112 4113 4114 4115 4116
  for (int32_t i = start; i < numOfRows + start; ++i) {
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
      continue;
    }

    numOfElems++;

    char* data = colDataGetData(pCol, i);
    if (IS_VAR_DATA_TYPE(type)) {
G
Ganlin Zhao 已提交
4117
      bytes = varDataLen(data);
4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128
      data = varDataVal(data);
    }

    int32_t index = 0;
    uint8_t count = hllCountNum(data, bytes, &index);
    uint8_t oldcount = pInfo->buckets[index];
    if (count > oldcount) {
      pInfo->buckets[index] = count;
    }
  }

G
Ganlin Zhao 已提交
4129
_hll_over:
4130 4131 4132 4133 4134 4135 4136 4137
  pInfo->totalCount += numOfElems;

  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
  } else {
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
  }

4138 4139 4140
  return TSDB_CODE_SUCCESS;
}

4141 4142 4143 4144 4145 4146
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
    if (pOutput->buckets[k] < pInput->buckets[k]) {
      pOutput->buckets[k] = pInput->buckets[k];
    }
  }
4147
  pOutput->totalCount += pInput->totalCount;
4148 4149
}

X
Xiaoyu Wang 已提交
4150
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
G
Ganlin Zhao 已提交
4151
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
4152
  SColumnInfoData*      pCol = pInput->pData[0];
G
Ganlin Zhao 已提交
4153 4154 4155 4156

  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
    return TSDB_CODE_SUCCESS;
  }
G
Ganlin Zhao 已提交
4157 4158 4159

  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));

4160
  int32_t start = pInput->startRowIndex;
G
Ganlin Zhao 已提交
4161

X
Xiaoyu Wang 已提交
4162 4163
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
    char*     data = colDataGetData(pCol, i);
4164 4165 4166
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
    hllTransferInfo(pInputInfo, pInfo);
  }
G
Ganlin Zhao 已提交
4167

4168 4169 4170 4171 4172 4173
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
  } else {
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
  }

G
Ganlin Zhao 已提交
4174 4175 4176
  return TSDB_CODE_SUCCESS;
}

4177
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
X
Xiaoyu Wang 已提交
4178
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
4179

4180 4181 4182 4183 4184
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
    pInfo->numOfRes = 1;
  }
4185 4186 4187 4188

  return functionFinalize(pCtx, pBlock);
}

G
Ganlin Zhao 已提交
4189 4190
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
4191 4192 4193
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  int32_t              resultBytes = getHLLInfoSize();
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
G
Ganlin Zhao 已提交
4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206

  memcpy(varDataVal(res), pInfo, resultBytes);
  varDataSetLen(res, resultBytes);

  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  colDataAppend(pCol, pBlock->info.rows, res, false);

  taosMemoryFree(res);
  return pResInfo->numOfRes;
}

4207 4208
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
X
Xiaoyu Wang 已提交
4209
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
4210 4211

  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
X
Xiaoyu Wang 已提交
4212
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
4213

4214
  hllTransferInfo(pSBuf, pDBuf);
4215
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
5
54liuyao 已提交
4216
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
4217 4218 4219
  return TSDB_CODE_SUCCESS;
}

4220 4221 4222 4223 4224
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SStateInfo);
  return true;
}

X
Xiaoyu Wang 已提交
4225
static int8_t getStateOpType(char* opStr) {
4226
  int8_t opType;
4227
  if (strncasecmp(opStr, "LT", 2) == 0) {
4228
    opType = STATE_OPER_LT;
4229
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
4230
    opType = STATE_OPER_GT;
4231
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
4232
    opType = STATE_OPER_LE;
4233
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
4234
    opType = STATE_OPER_GE;
4235
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
4236
    opType = STATE_OPER_NE;
4237
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
4238 4239 4240 4241 4242 4243 4244 4245 4246 4247
    opType = STATE_OPER_EQ;
  } else {
    opType = STATE_OPER_INVALID;
  }

  return opType;
}

static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
  char* data = colDataGetData(pCol, index);
X
Xiaoyu Wang 已提交
4248
  switch (pCol->info.type) {
4249
    case TSDB_DATA_TYPE_TINYINT: {
X
Xiaoyu Wang 已提交
4250
      int8_t v = *(int8_t*)data;
4251 4252 4253 4254
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_UTINYINT: {
X
Xiaoyu Wang 已提交
4255
      uint8_t v = *(uint8_t*)data;
4256 4257 4258 4259
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_SMALLINT: {
X
Xiaoyu Wang 已提交
4260
      int16_t v = *(int16_t*)data;
4261 4262 4263 4264
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
X
Xiaoyu Wang 已提交
4265
      uint16_t v = *(uint16_t*)data;
4266 4267 4268 4269
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_INT: {
X
Xiaoyu Wang 已提交
4270
      int32_t v = *(int32_t*)data;
4271 4272 4273 4274
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_UINT: {
X
Xiaoyu Wang 已提交
4275
      uint32_t v = *(uint32_t*)data;
4276 4277 4278 4279
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_BIGINT: {
X
Xiaoyu Wang 已提交
4280
      int64_t v = *(int64_t*)data;
4281 4282 4283 4284
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_UBIGINT: {
X
Xiaoyu Wang 已提交
4285
      uint64_t v = *(uint64_t*)data;
4286 4287 4288 4289
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_FLOAT: {
X
Xiaoyu Wang 已提交
4290
      float v = *(float*)data;
4291 4292 4293 4294
      STATE_COMP(op, v, param);
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
X
Xiaoyu Wang 已提交
4295
      double v = *(double*)data;
4296 4297 4298 4299
      STATE_COMP(op, v, param);
      break;
    }
    default: {
G
Ganlin Zhao 已提交
4300
      return false;
4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
    }
  }
  return false;
}

int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
4311
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
4312 4313 4314

  SColumnInfoData* pInputCol = pInput->pData[0];

X
Xiaoyu Wang 已提交
4315
  int32_t          numOfElems = 0;
4316 4317 4318
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
4319 4320 4321 4322
  if (STATE_OPER_INVALID == op) {
    return 0;
  }

4323
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4324 4325 4326 4327 4328 4329 4330
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
    } else {
      pInfo->prevTs = tsList[i];
    }

    pInfo->isPrevTsSet = true;
4331
    numOfElems++;
4332

4333 4334
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
      colDataAppendNULL(pOutput, i);
4335 4336
      // handle selectivity
      if (pCtx->subsidiaries.num > 0) {
D
dapan1121 已提交
4337
        appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4338
      }
4339 4340 4341
      continue;
    }

4342 4343
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);

4344 4345 4346 4347 4348 4349
    int64_t output = -1;
    if (ret) {
      output = ++pInfo->count;
    } else {
      pInfo->count = 0;
    }
D
dapan1121 已提交
4350
    colDataAppend(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
4351 4352 4353

    // handle selectivity
    if (pCtx->subsidiaries.num > 0) {
D
dapan1121 已提交
4354
      appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4355
    }
4356 4357
  }

4358 4359
  pResInfo->numOfRes = numOfElems;
  return TSDB_CODE_SUCCESS;
4360
}
4361 4362 4363 4364 4365 4366

int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
4367
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
4368 4369 4370

  SColumnInfoData* pInputCol = pInput->pData[0];

X
Xiaoyu Wang 已提交
4371
  int32_t          numOfElems = 0;
4372 4373
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

X
Xiaoyu Wang 已提交
4374
  // TODO: process timeUnit for different db precisions
4375
  int32_t timeUnit = 1;
X
Xiaoyu Wang 已提交
4376
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
4377 4378 4379 4380 4381
    timeUnit = pCtx->param[3].param.i;
  }

  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
  if (STATE_OPER_INVALID == op) {
4382
    return TSDB_CODE_INVALID_PARA;
4383 4384 4385
  }

  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4386 4387 4388 4389 4390 4391 4392
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
    } else {
      pInfo->prevTs = tsList[i];
    }

    pInfo->isPrevTsSet = true;
4393
    numOfElems++;
4394

4395 4396
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
      colDataAppendNULL(pOutput, i);
4397 4398
      // handle selectivity
      if (pCtx->subsidiaries.num > 0) {
D
dapan1121 已提交
4399
        appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4400
      }
4401 4402 4403
      continue;
    }

X
Xiaoyu Wang 已提交
4404
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415
    int64_t output = -1;
    if (ret) {
      if (pInfo->durationStart == 0) {
        output = 0;
        pInfo->durationStart = tsList[i];
      } else {
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
      }
    } else {
      pInfo->durationStart = 0;
    }
D
dapan1121 已提交
4416
    colDataAppend(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
4417 4418 4419

    // handle selectivity
    if (pCtx->subsidiaries.num > 0) {
D
dapan1121 已提交
4420
      appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4421
    }
4422 4423
  }

4424 4425
  pResInfo->numOfRes = numOfElems;
  return TSDB_CODE_SUCCESS;
4426
}
G
Ganlin Zhao 已提交
4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437

bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SSumRes);
  return true;
}

int32_t csumFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
4438
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
G
Ganlin Zhao 已提交
4439 4440 4441 4442 4443 4444 4445 4446

  SColumnInfoData* pInputCol = pInput->pData[0];
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

  int32_t numOfElems = 0;
  int32_t type = pInputCol->info.type;
  int32_t startOffset = pCtx->offset;
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4447 4448 4449 4450 4451 4452 4453
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
    } else {
      pSumRes->prevTs = tsList[i];
    }
    pSumRes->isPrevTsSet = true;

G
Ganlin Zhao 已提交
4454 4455
    int32_t pos = startOffset + numOfElems;
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
X
Xiaoyu Wang 已提交
4456
      // colDataAppendNULL(pOutput, i);
G
Ganlin Zhao 已提交
4457 4458 4459 4460 4461 4462 4463 4464
      continue;
    }

    char* data = colDataGetData(pInputCol, i);
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
      int64_t v;
      GET_TYPED_DATA(v, int64_t, type, data);
      pSumRes->isum += v;
X
Xiaoyu Wang 已提交
4465
      colDataAppend(pOutput, pos, (char*)&pSumRes->isum, false);
G
Ganlin Zhao 已提交
4466 4467 4468 4469
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
      uint64_t v;
      GET_TYPED_DATA(v, uint64_t, type, data);
      pSumRes->usum += v;
X
Xiaoyu Wang 已提交
4470
      colDataAppend(pOutput, pos, (char*)&pSumRes->usum, false);
G
Ganlin Zhao 已提交
4471 4472 4473 4474
    } else if (IS_FLOAT_TYPE(type)) {
      double v;
      GET_TYPED_DATA(v, double, type, data);
      pSumRes->dsum += v;
X
Xiaoyu Wang 已提交
4475
      // check for overflow
4476 4477
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
        colDataAppendNULL(pOutput, pos);
X
Xiaoyu Wang 已提交
4478 4479
      } else {
        colDataAppend(pOutput, pos, (char*)&pSumRes->dsum, false);
4480
      }
G
Ganlin Zhao 已提交
4481 4482
    }

4483 4484 4485 4486 4487
    // handle selectivity
    if (pCtx->subsidiaries.num > 0) {
      appendSelectivityValue(pCtx, i, pos);
    }

G
Ganlin Zhao 已提交
4488 4489 4490
    numOfElems++;
  }

4491 4492
  pResInfo->numOfRes = numOfElems;
  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
4493
}
G
Ganlin Zhao 已提交
4494 4495 4496 4497 4498 4499

bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
  return true;
}

X
Xiaoyu Wang 已提交
4500
bool mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
G
Ganlin Zhao 已提交
4501 4502 4503 4504
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

X
Xiaoyu Wang 已提交
4505
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
G
Ganlin Zhao 已提交
4506 4507
  pInfo->pos = 0;
  pInfo->sum = 0;
4508 4509
  pInfo->prevTs = -1;
  pInfo->isPrevTsSet = false;
G
Ganlin Zhao 已提交
4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523
  pInfo->numOfPoints = pCtx->param[1].param.i;
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
    return false;
  }
  pInfo->pointsMeet = false;

  return true;
}

int32_t mavgFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
4524
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
G
Ganlin Zhao 已提交
4525 4526 4527 4528 4529 4530 4531 4532 4533

  SColumnInfoData* pInputCol = pInput->pData[0];
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

  int32_t numOfElems = 0;
  int32_t type = pInputCol->info.type;
  int32_t startOffset = pCtx->offset;
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4534 4535 4536 4537 4538 4539 4540
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
    } else {
      pInfo->prevTs = tsList[i];
    }
    pInfo->isPrevTsSet = true;

G
Ganlin Zhao 已提交
4541 4542
    int32_t pos = startOffset + numOfElems;
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
X
Xiaoyu Wang 已提交
4543
      // colDataAppendNULL(pOutput, i);
G
Ganlin Zhao 已提交
4544 4545 4546
      continue;
    }

X
Xiaoyu Wang 已提交
4547
    char*  data = colDataGetData(pInputCol, i);
G
Ganlin Zhao 已提交
4548 4549 4550 4551 4552 4553 4554 4555
    double v;
    GET_TYPED_DATA(v, double, type, data);

    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
      pInfo->points[pInfo->pos] = v;
      pInfo->sum += v;
    } else {
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
X
Xiaoyu Wang 已提交
4556
        pInfo->sum += v;
G
Ganlin Zhao 已提交
4557 4558 4559 4560 4561
        pInfo->pointsMeet = true;
      } else {
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
      }

G
Ganlin Zhao 已提交
4562 4563
      pInfo->points[pInfo->pos] = v;
      double result = pInfo->sum / pInfo->numOfPoints;
X
Xiaoyu Wang 已提交
4564
      // check for overflow
4565 4566
      if (isinf(result) || isnan(result)) {
        colDataAppendNULL(pOutput, pos);
X
Xiaoyu Wang 已提交
4567 4568
      } else {
        colDataAppend(pOutput, pos, (char*)&result, false);
4569
      }
G
Ganlin Zhao 已提交
4570

4571 4572 4573 4574 4575
      // handle selectivity
      if (pCtx->subsidiaries.num > 0) {
        appendSelectivityValue(pCtx, i, pos);
      }

G
Ganlin Zhao 已提交
4576
      numOfElems++;
G
Ganlin Zhao 已提交
4577 4578
    }

G
Ganlin Zhao 已提交
4579 4580 4581 4582
    pInfo->pos++;
    if (pInfo->pos == pInfo->numOfPoints) {
      pInfo->pos = 0;
    }
G
Ganlin Zhao 已提交
4583 4584
  }

4585 4586
  pResInfo->numOfRes = numOfElems;
  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
4587
}
G
Ganlin Zhao 已提交
4588

4589 4590 4591 4592 4593 4594 4595 4596 4597 4598
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);

  return pInfo;
}

G
Ganlin Zhao 已提交
4599 4600
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
X
Xiaoyu Wang 已提交
4601 4602
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
  int32_t      numOfSamples = pVal->datum.i;
4603
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
G
Ganlin Zhao 已提交
4604 4605 4606
  return true;
}

X
Xiaoyu Wang 已提交
4607
bool sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
G
Ganlin Zhao 已提交
4608 4609 4610 4611 4612 4613
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  taosSeedRand(taosSafeRand());

X
Xiaoyu Wang 已提交
4614
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
G
Ganlin Zhao 已提交
4615 4616 4617
  pInfo->samples = pCtx->param[1].param.i;
  pInfo->totalPoints = 0;
  pInfo->numSampled = 0;
G
Ganlin Zhao 已提交
4618 4619
  pInfo->colType = pCtx->resDataInfo.type;
  pInfo->colBytes = pCtx->resDataInfo.bytes;
4620 4621
  pInfo->nullTuplePos.pageId = -1;
  pInfo->nullTupleSaved = false;
X
Xiaoyu Wang 已提交
4622
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
4623
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
G
Ganlin Zhao 已提交
4624 4625 4626 4627

  return true;
}

4628
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
G
Ganlin Zhao 已提交
4629
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
G
Ganlin Zhao 已提交
4630 4631
}

G
Ganlin Zhao 已提交
4632
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
G
Ganlin Zhao 已提交
4633 4634
  pInfo->totalPoints++;
  if (pInfo->numSampled < pInfo->samples) {
4635 4636
    sampleAssignResult(pInfo, data, pInfo->numSampled);
    if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
4637 4638 4639 4640
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
4641
    }
G
Ganlin Zhao 已提交
4642 4643 4644 4645
    pInfo->numSampled++;
  } else {
    int32_t j = taosRand() % (pInfo->totalPoints);
    if (j < pInfo->samples) {
4646 4647
      sampleAssignResult(pInfo, data, j);
      if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
4648 4649 4650 4651
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
4652
      }
G
Ganlin Zhao 已提交
4653 4654
    }
  }
G
Ganlin Zhao 已提交
4655 4656

  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
4657 4658 4659 4660
}

int32_t sampleFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4661
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
G
Ganlin Zhao 已提交
4662 4663 4664

  SInputColumnInfoData* pInput = &pCtx->input;

4665
  SColumnInfoData* pInputCol = pInput->pData[0];
G
Ganlin Zhao 已提交
4666
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4667
    if (colDataIsNull_s(pInputCol, i)) {
G
Ganlin Zhao 已提交
4668 4669 4670 4671
      continue;
    }

    char* data = colDataGetData(pInputCol, i);
G
Ganlin Zhao 已提交
4672 4673 4674 4675
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
G
Ganlin Zhao 已提交
4676 4677
  }

4678
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
G
Ganlin Zhao 已提交
4679 4680 4681 4682
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
4683 4684 4685
    pInfo->nullTupleSaved = true;
  }

4686 4687 4688 4689 4690
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
  return TSDB_CODE_SUCCESS;
}

int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
4691
  int32_t code = TSDB_CODE_SUCCESS;
4692 4693
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);

4694
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
4695 4696
  pEntryInfo->complete = true;

X
Xiaoyu Wang 已提交
4697
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
4698 4699 4700
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  int32_t currentRow = pBlock->info.rows;
4701 4702
  if (pInfo->numSampled == 0) {
    colDataAppendNULL(pCol, currentRow);
G
Ganlin Zhao 已提交
4703 4704
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
    return code;
4705
  }
G
Ganlin Zhao 已提交
4706
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
4707
    colDataAppend(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
G
Ganlin Zhao 已提交
4708
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
G
Ganlin Zhao 已提交
4709 4710
  }

G
Ganlin Zhao 已提交
4711
  return code;
G
Ganlin Zhao 已提交
4712 4713
}

G
Ganlin Zhao 已提交
4714
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
4715
#if 0
G
Ganlin Zhao 已提交
4716 4717
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
X
Xiaoyu Wang 已提交
4718
  int32_t      numOfPoints = pVal->datum.i;
G
Ganlin Zhao 已提交
4719
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
4720
#endif
G
Ganlin Zhao 已提交
4721 4722 4723
  return true;
}

X
Xiaoyu Wang 已提交
4724
bool tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4725
#if 0
G
Ganlin Zhao 已提交
4726 4727 4728 4729
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

X
Xiaoyu Wang 已提交
4730
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
G
Ganlin Zhao 已提交
4731 4732
  pInfo->numAdded = 0;
  pInfo->numOfPoints = pCtx->param[1].param.i;
4733 4734 4735 4736 4737
  if (pCtx->numOfParams == 4) {
    pInfo->offset = pCtx->param[2].param.i;
  } else {
    pInfo->offset = 0;
  }
G
Ganlin Zhao 已提交
4738 4739 4740 4741 4742 4743 4744
  pInfo->colType = pCtx->resDataInfo.type;
  pInfo->colBytes = pCtx->resDataInfo.bytes;
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
    return false;
  }

X
Xiaoyu Wang 已提交
4745 4746
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
G
Ganlin Zhao 已提交
4747

G
Ganlin Zhao 已提交
4748
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
G
Ganlin Zhao 已提交
4749
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
X
Xiaoyu Wang 已提交
4750
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
4751
    pInfo->pItems[i]->isNull = false;
G
Ganlin Zhao 已提交
4752
  }
4753
#endif
G
Ganlin Zhao 已提交
4754 4755 4756 4757

  return true;
}

X
Xiaoyu Wang 已提交
4758
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
4759
#if 0
G
Ganlin Zhao 已提交
4760
  pItem->timestamp = ts;
4761 4762 4763
  if (isNull) {
    pItem->isNull = true;
  } else {
4764
    pItem->isNull = false;
4765 4766
    memcpy(pItem->data, data, colBytes);
  }
4767
#endif
G
Ganlin Zhao 已提交
4768 4769
}

4770
#if 0
X
Xiaoyu Wang 已提交
4771 4772 4773
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
  STailItem* d1 = *(STailItem**)p1;
  STailItem* d2 = *(STailItem**)p2;
G
Ganlin Zhao 已提交
4774 4775 4776
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
}

X
Xiaoyu Wang 已提交
4777 4778
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
  STailItem** pList = pInfo->pItems;
G
Ganlin Zhao 已提交
4779
  if (pInfo->numAdded < pInfo->numOfPoints) {
4780
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
X
Xiaoyu Wang 已提交
4781
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
G
Ganlin Zhao 已提交
4782
    pInfo->numAdded++;
G
Ganlin Zhao 已提交
4783
  } else if (pList[0]->timestamp < ts) {
4784
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
X
Xiaoyu Wang 已提交
4785
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
G
Ganlin Zhao 已提交
4786 4787
  }
}
4788
#endif
G
Ganlin Zhao 已提交
4789 4790

int32_t tailFunction(SqlFunctionCtx* pCtx) {
4791
#if 0
G
Ganlin Zhao 已提交
4792
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
4793
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
G
Ganlin Zhao 已提交
4794 4795

  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
4796
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
G
Ganlin Zhao 已提交
4797 4798 4799 4800 4801

  SColumnInfoData* pInputCol = pInput->pData[0];
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

  int32_t startOffset = pCtx->offset;
4802 4803 4804
  if (pInfo->offset >= pInput->numOfRows) {
    return 0;
  } else {
wafwerar's avatar
wafwerar 已提交
4805
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
4806 4807
  }
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
G
Ganlin Zhao 已提交
4808
    char* data = colDataGetData(pInputCol, i);
4809
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
G
Ganlin Zhao 已提交
4810 4811
  }

4812 4813
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);

G
Ganlin Zhao 已提交
4814
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
X
Xiaoyu Wang 已提交
4815 4816
    int32_t    pos = startOffset + i;
    STailItem* pItem = pInfo->pItems[i];
4817 4818 4819 4820 4821
    if (pItem->isNull) {
      colDataAppendNULL(pOutput, pos);
    } else {
      colDataAppend(pOutput, pos, pItem->data, false);
    }
G
Ganlin Zhao 已提交
4822 4823
  }

G
Ganlin Zhao 已提交
4824
  return pInfo->numOfPoints;
4825 4826
#endif
  return 0;
G
Ganlin Zhao 已提交
4827
}
G
Ganlin Zhao 已提交
4828 4829

int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4830
#if 0
G
Ganlin Zhao 已提交
4831
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
X
Xiaoyu Wang 已提交
4832
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
G
Ganlin Zhao 已提交
4833 4834 4835 4836 4837 4838 4839 4840 4841 4842
  pEntryInfo->complete = true;

  int32_t type = pCtx->input.pData[0]->info.type;
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;

  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  // todo assign the tag value and the corresponding row data
  int32_t currentRow = pBlock->info.rows;
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
X
Xiaoyu Wang 已提交
4843
    STailItem* pItem = pInfo->pItems[i];
G
Ganlin Zhao 已提交
4844 4845 4846 4847 4848
    colDataAppend(pCol, currentRow, pItem->data, false);
    currentRow += 1;
  }

  return pEntryInfo->numOfRes;
4849 4850
#endif
  return 0;
G
Ganlin Zhao 已提交
4851
}
4852 4853

bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
4854
#if 0
4855
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
4856
#endif
4857 4858 4859 4860
  return true;
}

bool uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
4861
#if 0
4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874
  if (!functionSetup(pCtx, pResInfo)) {
    return false;
  }

  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
  pInfo->numOfPoints = 0;
  pInfo->colType = pCtx->resDataInfo.type;
  pInfo->colBytes = pCtx->resDataInfo.bytes;
  if (pInfo->pHash != NULL) {
    taosHashClear(pInfo->pHash);
  } else {
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
  }
4875
#endif
4876 4877 4878
  return true;
}

4879
#if 0
X
Xiaoyu Wang 已提交
4880 4881
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
  // handle null elements
4882
  if (isNull == true) {
X
Xiaoyu Wang 已提交
4883 4884
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
4885
    if (pInfo->hasNull == false && pItem->isNull == false) {
4886 4887 4888
      pItem->timestamp = ts;
      pItem->isNull = true;
      pInfo->numOfPoints++;
4889
      pInfo->hasNull = true;
4890 4891 4892 4893 4894
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
      pItem->timestamp = ts;
    }
    return;
  }
4895

X
Xiaoyu Wang 已提交
4896 4897
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
4898
  if (pHashItem == NULL) {
X
Xiaoyu Wang 已提交
4899 4900
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
4901 4902 4903
    pItem->timestamp = ts;
    memcpy(pItem->data, data, pInfo->colBytes);

X
Xiaoyu Wang 已提交
4904
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
4905 4906 4907 4908 4909
    pInfo->numOfPoints++;
  } else if (pHashItem->timestamp > ts) {
    pHashItem->timestamp = ts;
  }
}
4910
#endif
4911 4912

int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
4913
#if 0
4914 4915 4916 4917
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
4918
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935

  SColumnInfoData* pInputCol = pInput->pData[0];
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

  int32_t startOffset = pCtx->offset;
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
    char* data = colDataGetData(pInputCol, i);
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));

    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
      taosHashCleanup(pInfo->pHash);
      return 0;
    }
  }

  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
X
Xiaoyu Wang 已提交
4936
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
4937 4938 4939 4940 4941
    if (pItem->isNull == true) {
      colDataAppendNULL(pOutput, i);
    } else {
      colDataAppend(pOutput, i, pItem->data, false);
    }
4942 4943 4944 4945 4946 4947
    if (pTsOutput != NULL) {
      colDataAppendInt64(pTsOutput, i, &pItem->timestamp);
    }
  }

  return pInfo->numOfPoints;
4948 4949
#endif
  return 0;
4950 4951
}

G
Ganlin Zhao 已提交
4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SModeInfo) + MODE_MAX_RESULT_SIZE;
  return true;
}

bool modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
  if (!functionSetup(pCtx, pResInfo)) {
    return false;
  }

  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
  pInfo->numOfPoints = 0;
  pInfo->colType = pCtx->resDataInfo.type;
  pInfo->colBytes = pCtx->resDataInfo.bytes;
  if (pInfo->pHash != NULL) {
    taosHashClear(pInfo->pHash);
  } else {
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
  }
4971 4972 4973
  pInfo->nullTupleSaved = false;
  pInfo->nullTuplePos.pageId = -1;

G
Ganlin Zhao 已提交
4974 4975 4976
  return true;
}

G
Ganlin Zhao 已提交
4977
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
4978
  int32_t     hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
4979
  SModeItem** pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
G
Ganlin Zhao 已提交
4980
  if (pHashItem == NULL) {
4981 4982
    int32_t    size = sizeof(SModeItem) + pInfo->colBytes;
    SModeItem* pItem = (SModeItem*)(pInfo->pItems + pInfo->numOfPoints * size);
4983
    memcpy(pItem->data, data, hashKeyBytes);
G
Ganlin Zhao 已提交
4984 4985
    pItem->count += 1;

4986
    if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
4987 4988 4989 4990
      int32_t code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pItem->tuplePos);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
4991 4992
    }

G
Ganlin Zhao 已提交
4993
    taosHashPut(pInfo->pHash, data, hashKeyBytes, &pItem, sizeof(SModeItem*));
G
Ganlin Zhao 已提交
4994 4995
    pInfo->numOfPoints++;
  } else {
G
Ganlin Zhao 已提交
4996
    (*pHashItem)->count += 1;
4997
    if (pCtx->subsidiaries.num > 0) {
G
Ganlin Zhao 已提交
4998 4999 5000 5001
      int32_t code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &((*pHashItem)->tuplePos));
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
5002
    }
G
Ganlin Zhao 已提交
5003
  }
G
Ganlin Zhao 已提交
5004 5005

  return TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
5006 5007 5008
}

int32_t modeFunction(SqlFunctionCtx* pCtx) {
5009
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5010
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
G
Ganlin Zhao 已提交
5011 5012 5013 5014 5015 5016

  SInputColumnInfoData* pInput = &pCtx->input;

  SColumnInfoData* pInputCol = pInput->pData[0];
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

5017
  int32_t numOfElems = 0;
G
Ganlin Zhao 已提交
5018 5019
  int32_t startOffset = pCtx->offset;
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5020 5021 5022 5023
    if (colDataIsNull_s(pInputCol, i)) {
      continue;
    }
    numOfElems++;
5024 5025

    char* data = colDataGetData(pInputCol, i);
G
Ganlin Zhao 已提交
5026 5027 5028 5029
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
G
Ganlin Zhao 已提交
5030 5031 5032 5033 5034 5035 5036

    if (sizeof(SModeInfo) + pInfo->numOfPoints * (sizeof(SModeItem) + pInfo->colBytes) >= MODE_MAX_RESULT_SIZE) {
      taosHashCleanup(pInfo->pHash);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }

5037
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
G
Ganlin Zhao 已提交
5038 5039 5040 5041
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
5042 5043 5044
    pInfo->nullTupleSaved = true;
  }

5045
  SET_VAL(pResInfo, numOfElems, 1);
G
Ganlin Zhao 已提交
5046

G
Ganlin Zhao 已提交
5047 5048 5049 5050
  return TSDB_CODE_SUCCESS;
}

int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
G
Ganlin Zhao 已提交
5051
  int32_t              code = TSDB_CODE_SUCCESS;
G
Ganlin Zhao 已提交
5052 5053
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
X
Xiaoyu Wang 已提交
5054 5055
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
G
Ganlin Zhao 已提交
5056
  int32_t              currentRow = pBlock->info.rows;
5057

G
Ganlin Zhao 已提交
5058
  int32_t resIndex = -1;
G
Ganlin Zhao 已提交
5059 5060 5061
  int32_t maxCount = 0;
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
    SModeItem* pItem = (SModeItem*)(pInfo->pItems + i * (sizeof(SModeItem) + pInfo->colBytes));
5062
    if (pItem->count >= maxCount) {
G
Ganlin Zhao 已提交
5063 5064 5065
      maxCount = pItem->count;
      resIndex = i;
    }
5066 5067
  }

G
Ganlin Zhao 已提交
5068 5069 5070
  if (maxCount != 0) {
    SModeItem* pResItem = (SModeItem*)(pInfo->pItems + resIndex * (sizeof(SModeItem) + pInfo->colBytes));
    colDataAppend(pCol, currentRow, pResItem->data, false);
G
Ganlin Zhao 已提交
5071
    code = setSelectivityValue(pCtx, pBlock, &pResItem->tuplePos, currentRow);
G
Ganlin Zhao 已提交
5072 5073
  } else {
    colDataAppendNULL(pCol, currentRow);
G
Ganlin Zhao 已提交
5074
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
G
Ganlin Zhao 已提交
5075
  }
G
Ganlin Zhao 已提交
5076

G
Ganlin Zhao 已提交
5077 5078
  taosHashCleanup(pInfo->pHash);

G
Ganlin Zhao 已提交
5079
  return code;
5080 5081
}

5082 5083 5084 5085 5086
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(STwaInfo);
  return true;
}

X
Xiaoyu Wang 已提交
5087
bool twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5088 5089 5090 5091
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

X
Xiaoyu Wang 已提交
5092
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5093
  pInfo->isNull = false;
5094 5095
  pInfo->p.key = INT64_MIN;
  pInfo->win = TSWINDOW_INITIALIZER;
5096 5097 5098 5099
  return true;
}

static double twa_get_area(SPoint1 s, SPoint1 e) {
5100 5101 5102 5103
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
    return 0;
  }

X
Xiaoyu Wang 已提交
5104
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
5105 5106 5107
    return (s.val + e.val) * (e.key - s.key) / 2;
  }

X
Xiaoyu Wang 已提交
5108
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
5109 5110 5111 5112 5113 5114
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
  return val;
}

int32_t twaFunction(SqlFunctionCtx* pCtx) {
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
5115
  SColumnInfoData*      pInputCol = pInput->pData[0];
5116 5117 5118

  TSKEY* tsList = (int64_t*)pInput->pPTS->pData;

X
Xiaoyu Wang 已提交
5119
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5120

X
Xiaoyu Wang 已提交
5121 5122
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
  SPoint1*  last = &pInfo->p;
5123
  int32_t   numOfElems = 0;
5124

5125 5126 5127 5128 5129
  if (IS_NULL_TYPE(pInputCol->info.type)) {
    pInfo->isNull = true;
    goto _twa_over;
  }

5130
  int32_t i = pInput->startRowIndex;
G
Ganlin Zhao 已提交
5131
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
5132 5133 5134 5135
    for (; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        continue;
      }
5136

5137
      last->key = tsList[i];
5138

5139 5140 5141 5142 5143 5144 5145 5146
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, colDataGetData(pInputCol, i));

      pInfo->dOutput += twa_get_area(pCtx->start, *last);
      pInfo->win.skey = pCtx->start.key;
      numOfElems++;
      i += 1;
      break;
    }
5147
  } else if (pInfo->p.key == INT64_MIN) {
5148 5149 5150 5151
    for (; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        continue;
      }
5152

5153 5154 5155 5156 5157 5158 5159 5160 5161
      last->key = tsList[i];

      GET_TYPED_DATA(last->val, double, pInputCol->info.type, colDataGetData(pInputCol, i));

      pInfo->win.skey = last->key;
      numOfElems++;
      i += 1;
      break;
    }
5162 5163
  }

5164 5165
  SPoint1 st = {0};

5166
  // calculate the value of
X
Xiaoyu Wang 已提交
5167
  switch (pInputCol->info.type) {
5168
    case TSDB_DATA_TYPE_TINYINT: {
X
Xiaoyu Wang 已提交
5169
      int8_t* val = (int8_t*)colDataGetData(pInputCol, 0);
5170
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5171 5172 5173
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5174
        numOfElems++;
5175

5176
        INIT_INTP_POINT(st, tsList[i], val[i]);
5177
        if (pInfo->p.key == st.key) {
5178
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5179 5180
        }

5181 5182 5183 5184 5185 5186 5187
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }

    case TSDB_DATA_TYPE_SMALLINT: {
X
Xiaoyu Wang 已提交
5188
      int16_t* val = (int16_t*)colDataGetData(pInputCol, 0);
5189
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5190 5191 5192
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5193
        numOfElems++;
5194

5195
        INIT_INTP_POINT(st, tsList[i], val[i]);
5196
        if (pInfo->p.key == st.key) {
5197
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5198 5199
        }

5200 5201 5202 5203 5204 5205
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_INT: {
X
Xiaoyu Wang 已提交
5206
      int32_t* val = (int32_t*)colDataGetData(pInputCol, 0);
5207
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5208 5209 5210
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5211
        numOfElems++;
5212

5213
        INIT_INTP_POINT(st, tsList[i], val[i]);
5214
        if (pInfo->p.key == st.key) {
5215
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5216 5217
        }

5218 5219 5220 5221 5222 5223
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_BIGINT: {
X
Xiaoyu Wang 已提交
5224
      int64_t* val = (int64_t*)colDataGetData(pInputCol, 0);
5225
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5226 5227 5228
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5229
        numOfElems++;
5230

5231
        INIT_INTP_POINT(st, tsList[i], val[i]);
5232
        if (pInfo->p.key == st.key) {
5233
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5234 5235
        }

5236 5237 5238 5239 5240 5241
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_FLOAT: {
X
Xiaoyu Wang 已提交
5242
      float* val = (float*)colDataGetData(pInputCol, 0);
5243
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5244 5245 5246
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5247
        numOfElems++;
5248

5249
        INIT_INTP_POINT(st, tsList[i], val[i]);
5250
        if (pInfo->p.key == st.key) {
5251
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5252 5253
        }

5254 5255 5256 5257 5258 5259
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
X
Xiaoyu Wang 已提交
5260
      double* val = (double*)colDataGetData(pInputCol, 0);
5261
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5262 5263 5264
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5265
        numOfElems++;
5266

5267
        INIT_INTP_POINT(st, tsList[i], val[i]);
5268
        if (pInfo->p.key == st.key) {
5269
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5270 5271
        }

5272 5273 5274 5275 5276 5277
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_UTINYINT: {
X
Xiaoyu Wang 已提交
5278
      uint8_t* val = (uint8_t*)colDataGetData(pInputCol, 0);
5279
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5280 5281 5282
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5283
        numOfElems++;
5284

5285
        INIT_INTP_POINT(st, tsList[i], val[i]);
5286
        if (pInfo->p.key == st.key) {
5287
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5288 5289
        }

5290 5291 5292 5293 5294 5295
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
X
Xiaoyu Wang 已提交
5296
      uint16_t* val = (uint16_t*)colDataGetData(pInputCol, 0);
5297
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5298 5299 5300
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5301
        numOfElems++;
5302

5303
        INIT_INTP_POINT(st, tsList[i], val[i]);
5304
        if (pInfo->p.key == st.key) {
5305
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5306 5307
        }

5308 5309 5310 5311 5312 5313
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_UINT: {
X
Xiaoyu Wang 已提交
5314
      uint32_t* val = (uint32_t*)colDataGetData(pInputCol, 0);
5315
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5316 5317 5318
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5319
        numOfElems++;
5320

5321
        INIT_INTP_POINT(st, tsList[i], val[i]);
5322
        if (pInfo->p.key == st.key) {
5323
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5324 5325
        }

5326 5327 5328 5329 5330 5331
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }
    case TSDB_DATA_TYPE_UBIGINT: {
X
Xiaoyu Wang 已提交
5332
      uint64_t* val = (uint64_t*)colDataGetData(pInputCol, 0);
5333
      for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5334 5335 5336
        if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
          continue;
        }
5337
        numOfElems++;
5338

5339
        INIT_INTP_POINT(st, tsList[i], val[i]);
5340
        if (pInfo->p.key == st.key) {
5341
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
5342 5343
        }

5344 5345 5346 5347 5348 5349
        pInfo->dOutput += twa_get_area(pInfo->p, st);
        pInfo->p = st;
      }
      break;
    }

X
Xiaoyu Wang 已提交
5350
    default:
G
Ganlin Zhao 已提交
5351
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
5352 5353 5354 5355
  }

  // the last interpolated time window value
  if (pCtx->end.key != INT64_MIN) {
X
Xiaoyu Wang 已提交
5356
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5357
    pInfo->p = pCtx->end;
H
Haojun Liao 已提交
5358
    numOfElems += 1;
5359 5360
  }

X
Xiaoyu Wang 已提交
5361
  pInfo->win.ekey = pInfo->p.key;
5362

5363
_twa_over:
5364 5365 5366 5367 5368
  if (numOfElems == 0) {
    pInfo->isNull = true;
  }

  SET_VAL(pResInfo, 1, 1);
5369 5370 5371 5372 5373 5374 5375 5376
  return TSDB_CODE_SUCCESS;
}

/*
 * To copy the input to interResBuf to avoid the input buffer space be over writen
 * by next input data. The TWA function only applies to each table, so no merge procedure
 * is required, we simply copy to the resut ot interResBuffer.
 */
X
Xiaoyu Wang 已提交
5377 5378
// void twa_function_copy(SQLFunctionCtx *pCtx) {
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
5379
//
X
Xiaoyu Wang 已提交
5380 5381 5382
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
// }
5383

X
Xiaoyu Wang 已提交
5384 5385
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5386

X
Xiaoyu Wang 已提交
5387
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
5388 5389
  if (pInfo->isNull == true) {
    pResInfo->numOfRes = 0;
5390 5391 5392
  } else {
    if (pInfo->win.ekey == pInfo->win.skey) {
      pInfo->dOutput = pInfo->p.val;
5393
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
5394
      pInfo->dOutput = 0;
5395 5396 5397 5398 5399 5400 5401 5402 5403 5404
    } else {
      pInfo->dOutput = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
    }

    pResInfo->numOfRes = 1;
  }

  return functionFinalize(pCtx, pBlock);
}

5405
bool blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5406 5407 5408 5409 5410 5411 5412 5413 5414
  if (!functionSetup(pCtx, pResultInfo)) {
    return false;
  }

  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
  pInfo->minRows = INT32_MAX;
  return true;
}

X
Xiaoyu Wang 已提交
5415
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
5416 5417
  const int32_t BLOCK_DIST_RESULT_ROWS = 24;

5418
  SInputColumnInfoData* pInput = &pCtx->input;
X
Xiaoyu Wang 已提交
5419
  SColumnInfoData*      pInputCol = pInput->pData[0];
5420

X
Xiaoyu Wang 已提交
5421
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5422

5423 5424 5425 5426 5427 5428 5429 5430
  STableBlockDistInfo* pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);

  STableBlockDistInfo p1 = {0};
  tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1);

  pDistInfo->numOfBlocks += p1.numOfBlocks;
  pDistInfo->numOfTables += p1.numOfTables;
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
5431
  pDistInfo->numOfVgroups += p1.numOfVgroups;
5432 5433 5434 5435
  pDistInfo->totalSize += p1.totalSize;
  pDistInfo->totalRows += p1.totalRows;
  pDistInfo->numOfFiles += p1.numOfFiles;

5436 5437
  pDistInfo->defMinRows = p1.defMinRows;
  pDistInfo->defMaxRows = p1.defMaxRows;
5438
  pDistInfo->rowSize = p1.rowSize;
5439 5440
  pDistInfo->numOfSmallBlocks = p1.numOfSmallBlocks;

5441 5442 5443 5444 5445 5446 5447
  if (pDistInfo->minRows > p1.minRows) {
    pDistInfo->minRows = p1.minRows;
  }
  if (pDistInfo->maxRows < p1.maxRows) {
    pDistInfo->maxRows = p1.maxRows;
  }

X
Xiaoyu Wang 已提交
5448
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
5449 5450 5451
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
  }

5452
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463
  return TSDB_CODE_SUCCESS;
}

int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
  SEncoder encoder = {0};
  tEncoderInit(&encoder, buf, bufLen);

  if (tStartEncode(&encoder) < 0) return -1;
  if (tEncodeU32(&encoder, pInfo->rowSize) < 0) return -1;

  if (tEncodeU16(&encoder, pInfo->numOfFiles) < 0) return -1;
5464
  if (tEncodeU32(&encoder, pInfo->numOfBlocks) < 0) return -1;
5465
  if (tEncodeU32(&encoder, pInfo->numOfTables) < 0) return -1;
5466
  if (tEncodeU32(&encoder, pInfo->numOfVgroups) < 0) return -1;
5467 5468 5469 5470 5471 5472 5473 5474 5475 5476

  if (tEncodeU64(&encoder, pInfo->totalSize) < 0) return -1;
  if (tEncodeU64(&encoder, pInfo->totalRows) < 0) return -1;
  if (tEncodeI32(&encoder, pInfo->maxRows) < 0) return -1;
  if (tEncodeI32(&encoder, pInfo->minRows) < 0) return -1;
  if (tEncodeI32(&encoder, pInfo->defMaxRows) < 0) return -1;
  if (tEncodeI32(&encoder, pInfo->defMinRows) < 0) return -1;
  if (tEncodeU32(&encoder, pInfo->numOfInmemRows) < 0) return -1;
  if (tEncodeU32(&encoder, pInfo->numOfSmallBlocks) < 0) return -1;

X
Xiaoyu Wang 已提交
5477
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495
    if (tEncodeI32(&encoder, pInfo->blockRowsHisto[i]) < 0) return -1;
  }

  tEndEncode(&encoder);

  int32_t tlen = encoder.pos;
  tEncoderClear(&encoder);
  return tlen;
}

int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
  SDecoder decoder = {0};
  tDecoderInit(&decoder, buf, bufLen);

  if (tStartDecode(&decoder) < 0) return -1;
  if (tDecodeU32(&decoder, &pInfo->rowSize) < 0) return -1;

  if (tDecodeU16(&decoder, &pInfo->numOfFiles) < 0) return -1;
5496
  if (tDecodeU32(&decoder, &pInfo->numOfBlocks) < 0) return -1;
5497
  if (tDecodeU32(&decoder, &pInfo->numOfTables) < 0) return -1;
5498
  if (tDecodeU32(&decoder, &pInfo->numOfVgroups) < 0) return -1;
5499 5500 5501 5502 5503 5504 5505 5506 5507 5508

  if (tDecodeU64(&decoder, &pInfo->totalSize) < 0) return -1;
  if (tDecodeU64(&decoder, &pInfo->totalRows) < 0) return -1;
  if (tDecodeI32(&decoder, &pInfo->maxRows) < 0) return -1;
  if (tDecodeI32(&decoder, &pInfo->minRows) < 0) return -1;
  if (tDecodeI32(&decoder, &pInfo->defMaxRows) < 0) return -1;
  if (tDecodeI32(&decoder, &pInfo->defMinRows) < 0) return -1;
  if (tDecodeU32(&decoder, &pInfo->numOfInmemRows) < 0) return -1;
  if (tDecodeU32(&decoder, &pInfo->numOfSmallBlocks) < 0) return -1;

X
Xiaoyu Wang 已提交
5509
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
5510 5511 5512 5513 5514 5515 5516 5517
    if (tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]) < 0) return -1;
  }

  tDecoderClear(&decoder);
  return 0;
}

int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
X
Xiaoyu Wang 已提交
5518
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5519
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
5520

5521 5522
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);

H
Haojun Liao 已提交
5523 5524 5525 5526
  if (pData->totalRows == 0) {
    pData->minRows = 0;
  }

5527
  int32_t row = 0;
X
Xiaoyu Wang 已提交
5528
  char    st[256] = {0};
5529 5530 5531 5532 5533 5534 5535 5536 5537 5538
  double  averageSize = 0;
  if (pData->numOfBlocks != 0) {
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
  }
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
  double   compRatio = 0;
  if (totalRawSize != 0) {
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
  }

5539 5540
  int32_t len = sprintf(st + VARSTR_HEADER_SIZE,
                        "Total_Blocks=[%d] Total_Size=[%.2f Kb] Average_size=[%.2f Kb] Compression_Ratio=[%.2f %c]",
L
Liu Jicong 已提交
5541
                        pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
5542 5543 5544

  varDataSetLen(st, len);
  colDataAppend(pColInfo, row++, st, false);
5545

H
Haojun Liao 已提交
5546 5547 5548 5549 5550
  int64_t avgRows = 0;
  if (pData->numOfBlocks > 0) {
    avgRows = pData->totalRows / pData->numOfBlocks;
  }

5551 5552
  len = sprintf(st + VARSTR_HEADER_SIZE,
                "Total_Rows=[%" PRId64 "] Inmem_Rows=[%d] MinRows=[%d] MaxRows=[%d] Average_Rows=[%" PRId64 "]",
H
Haojun Liao 已提交
5553
                pData->totalRows, pData->numOfInmemRows, pData->minRows, pData->maxRows, avgRows);
5554

5555 5556
  varDataSetLen(st, len);
  colDataAppend(pColInfo, row++, st, false);
5557

5558
  len = sprintf(st + VARSTR_HEADER_SIZE, "Total_Tables=[%d] Total_Files=[%d] Total_Vgroups=[%d]", pData->numOfTables,
5559
                pData->numOfFiles, pData->numOfVgroups);
5560 5561 5562 5563

  varDataSetLen(st, len);
  colDataAppend(pColInfo, row++, st, false);

X
Xiaoyu Wang 已提交
5564 5565
  len = sprintf(st + VARSTR_HEADER_SIZE,
                "--------------------------------------------------------------------------------");
5566 5567
  varDataSetLen(st, len);
  colDataAppend(pColInfo, row++, st, false);
5568 5569 5570

  int32_t maxVal = 0;
  int32_t minVal = INT32_MAX;
5571 5572 5573
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
    if (maxVal < pData->blockRowsHisto[i]) {
      maxVal = pData->blockRowsHisto[i];
5574 5575
    }

5576 5577
    if (minVal > pData->blockRowsHisto[i]) {
      minVal = pData->blockRowsHisto[i];
5578 5579 5580
    }
  }

5581 5582
  // maximum number of step is 80
  double factor = pData->numOfBlocks / 80.0;
5583 5584

  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
5585
  int32_t bucketRange = (pData->defMaxRows - pData->defMinRows) / numOfBuckets;
5586

5587
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
5588
    len = sprintf(st + VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * i);
5589

5590
    int32_t num = 0;
5591 5592
    if (pData->blockRowsHisto[i] > 0) {
      num = (pData->blockRowsHisto[i]) / factor;
5593
    }
5594 5595 5596

    for (int32_t j = 0; j < num; ++j) {
      int32_t x = sprintf(st + VARSTR_HEADER_SIZE + len, "%c", '|');
5597 5598 5599
      len += x;
    }

5600 5601 5602 5603
    if (num > 0) {
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
      len += sprintf(st + VARSTR_HEADER_SIZE + len, "  %d (%.2f%c)", pData->blockRowsHisto[i], v, '%');
    }
5604 5605 5606

    varDataSetLen(st, len);
    colDataAppend(pColInfo, row++, st, false);
5607 5608
  }

5609
  return TSDB_CODE_SUCCESS;
5610
}
5611 5612 5613 5614 5615 5616

bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SDerivInfo);
  return true;
}

5617
bool derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
5618 5619 5620 5621 5622 5623 5624
  if (!functionSetup(pCtx, pResInfo)) {
    return false;  // not initialized since it has been initialized
  }

  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);

  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
5625
  pDerivInfo->prevTs = -1;
5626 5627 5628 5629 5630
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
  pDerivInfo->valueSet = false;
  return true;
}

5631 5632 5633
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
5634 5635

  SInputColumnInfoData* pInput = &pCtx->input;
5636
  SColumnInfoData*      pInputCol = pInput->pData[0];
H
Haojun Liao 已提交
5637

5638
  int32_t          numOfElems = 0;
5639 5640 5641 5642
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;

  int32_t i = pInput->startRowIndex;
5643
  TSKEY*  tsList = (int64_t*)pInput->pPTS->pData;
5644

5645
  double v = 0;
5646

5647 5648
  if (pCtx->order == TSDB_ORDER_ASC) {
    for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5649 5650 5651 5652
      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        continue;
      }

5653
      char* d = (char*)pInputCol->pData + pInputCol->info.bytes * i;
5654 5655 5656 5657 5658 5659
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);

      int32_t pos = pCtx->offset + numOfElems;
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
        pDerivInfo->valueSet = true;
      } else {
5660 5661 5662
        if (tsList[i] == pDerivInfo->prevTs) {
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
        }
5663 5664 5665
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs);
        if (pDerivInfo->ignoreNegative && r < 0) {
        } else {
5666 5667 5668 5669 5670 5671
          if (isinf(r) || isnan(r)) {
            colDataAppendNULL(pOutput, pos);
          } else {
            colDataAppend(pOutput, pos, (const char*)&r, false);
          }

5672 5673 5674
          if (pTsOutput != NULL) {
            colDataAppendInt64(pTsOutput, pos, &tsList[i]);
          }
5675 5676 5677 5678 5679 5680

          // handle selectivity
          if (pCtx->subsidiaries.num > 0) {
            appendSelectivityValue(pCtx, i, pos);
          }

5681 5682 5683 5684 5685 5686 5687 5688
          numOfElems++;
        }
      }

      pDerivInfo->prevValue = v;
      pDerivInfo->prevTs = tsList[i];
    }
  } else {
5689 5690 5691 5692 5693
    for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
      if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
        continue;
      }

5694
      char* d = (char*)pInputCol->pData + pInputCol->info.bytes * i;
5695 5696 5697 5698 5699 5700
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);

      int32_t pos = pCtx->offset + numOfElems;
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
        pDerivInfo->valueSet = true;
      } else {
5701 5702 5703
        if (tsList[i] == pDerivInfo->prevTs) {
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
        }
5704 5705 5706
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - tsList[i]);
        if (pDerivInfo->ignoreNegative && r < 0) {
        } else {
5707 5708 5709 5710 5711 5712
          if (isinf(r) || isnan(r)) {
            colDataAppendNULL(pOutput, pos);
          } else {
            colDataAppend(pOutput, pos, (const char*)&r, false);
          }

5713 5714 5715
          if (pTsOutput != NULL) {
            colDataAppendInt64(pTsOutput, pos, &pDerivInfo->prevTs);
          }
5716 5717 5718 5719 5720 5721

          // handle selectivity
          if (pCtx->subsidiaries.num > 0) {
            appendSelectivityValue(pCtx, i, pos);
          }

5722 5723 5724
          numOfElems++;
        }
      }
5725

5726 5727 5728
      pDerivInfo->prevValue = v;
      pDerivInfo->prevTs = tsList[i];
    }
5729 5730
  }

5731 5732 5733
  pResInfo->numOfRes = numOfElems;

  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
5734 5735
}

G
Ganlin Zhao 已提交
5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
  pEnv->calcMemSize = sizeof(SRateInfo);
  return true;
}

bool irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
  if (!functionSetup(pCtx, pResInfo)) {
    return false;  // not initialized since it has been initialized
  }

  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);

5748 5749
  pInfo->firstKey = INT64_MIN;
  pInfo->lastKey = INT64_MIN;
G
Ganlin Zhao 已提交
5750
  pInfo->firstValue = (double)INT64_MIN;
5751
  pInfo->lastValue = (double)INT64_MIN;
G
Ganlin Zhao 已提交
5752

5753
  pInfo->hasResult = 0;
G
Ganlin Zhao 已提交
5754 5755 5756 5757 5758
  return true;
}

int32_t irateFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5759
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
G
Ganlin Zhao 已提交
5760 5761 5762 5763 5764 5765

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pInputCol = pInput->pData[0];

  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;

5766
  TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
G
Ganlin Zhao 已提交
5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777

  int32_t numOfElems = 0;
  int32_t type = pInputCol->info.type;

  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
      continue;
    }

    numOfElems++;

5778 5779
    char*  data = colDataGetData(pInputCol, i);
    double v = 0;
G
Ganlin Zhao 已提交
5780 5781 5782 5783
    GET_TYPED_DATA(v, double, type, data);

    if (INT64_MIN == pRateInfo->lastKey) {
      pRateInfo->lastValue = v;
5784
      pRateInfo->lastKey = tsList[i];
G
Ganlin Zhao 已提交
5785 5786 5787 5788 5789 5790 5791 5792 5793 5794
      continue;
    }

    if (tsList[i] > pRateInfo->lastKey) {
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
        pRateInfo->firstValue = pRateInfo->lastValue;
        pRateInfo->firstKey = pRateInfo->lastKey;
      }

      pRateInfo->lastValue = v;
5795
      pRateInfo->lastKey = tsList[i];
G
Ganlin Zhao 已提交
5796 5797

      continue;
5798 5799
    } else if (tsList[i] == pRateInfo->lastKey) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
G
Ganlin Zhao 已提交
5800 5801 5802 5803 5804
    }

    if ((INT64_MIN == pRateInfo->firstKey) || tsList[i] > pRateInfo->firstKey) {
      pRateInfo->firstValue = v;
      pRateInfo->firstKey = tsList[i];
5805 5806
    } else if (tsList[i] == pRateInfo->firstKey) {
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
G
Ganlin Zhao 已提交
5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832
    }
  }

  SET_VAL(pResInfo, numOfElems, 1);
  return TSDB_CODE_SUCCESS;
}

static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
    return 0.0;
  }

  double diff = 0;
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
  // value between two values.
  diff = pRateInfo->lastValue;
  if (diff >= pRateInfo->firstValue) {
    diff -= pRateInfo->firstValue;
  }

  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
  if (duration == 0) {
    return 0;
  }

5833
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
G
Ganlin Zhao 已提交
5834 5835 5836 5837 5838 5839 5840 5841 5842 5843
}

int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;

  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5844
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
G
Ganlin Zhao 已提交
5845 5846 5847 5848 5849
  colDataAppend(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);

  return pResInfo->numOfRes;
}

5850 5851
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) {
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5852
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5853 5854

  SInputColumnInfoData* pInput = &pCtx->input;
5855
  SColumnInfoData*      pInputCol = pInput->pData[0];
5856 5857

  int32_t startIndex = pInput->startRowIndex;
5858

5859
  // escape rest of data blocks to avoid first entry to be overwritten.
5860 5861 5862 5863
  if (pInfo->hasResult) {
    goto _group_key_over;
  }

5864
  if (colDataIsNull_s(pInputCol, startIndex)) {
5865 5866
    pInfo->isNull = true;
    pInfo->hasResult = true;
G
Ganlin Zhao 已提交
5867
    goto _group_key_over;
5868 5869 5870
  }

  char* data = colDataGetData(pInputCol, startIndex);
5871
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
X
Xiaoyu Wang 已提交
5872 5873
    memcpy(pInfo->data, data,
           (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
5874 5875 5876
  } else {
    memcpy(pInfo->data, data, pInputCol->info.bytes);
  }
5877
  pInfo->hasResult = true;
G
Ganlin Zhao 已提交
5878 5879

_group_key_over:
5880

G
Ganlin Zhao 已提交
5881
  SET_VAL(pResInfo, 1, 1);
5882 5883 5884
  return TSDB_CODE_SUCCESS;
}

G
Ganlin Zhao 已提交
5885 5886 5887 5888 5889 5890 5891
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);

  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5892 5893

  if (pInfo->hasResult) {
5894 5895 5896 5897
    int32_t currentRow = pBlock->info.rows;
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
      colDataAppend(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
    }
5898 5899 5900
  } else {
    pResInfo->numOfRes = 0;
  }
G
Ganlin Zhao 已提交
5901 5902 5903 5904

  return pResInfo->numOfRes;
}

5905
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916
  int32_t numOfElems = 0;

  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);

  SInputColumnInfoData* pInput = &pCtx->input;
  SColumnInfoData*      pInputCol = pInput->pData[0];

  int32_t bytes = pInputCol->info.bytes;
  pInfo->bytes = bytes;

5917
  // last_row function does not ignore the null value
5918 5919 5920
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
    numOfElems++;

H
Haojun Liao 已提交
5921 5922 5923
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);

5924
    TSKEY cts = getRowPTs(pInput->pPTS, i);
5925
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
5926 5927 5928 5929
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
5930
      pResInfo->numOfRes = 1;
5931 5932 5933 5934 5935 5936
    }
  }

  SET_VAL(pResInfo, numOfElems, 1);
  return TSDB_CODE_SUCCESS;
}