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

H
Haojun Liao 已提交
20
#include "exception.h"
21
#include "hash.h"
H
Haojun Liao 已提交
22
#include "texpr.h"
H
Haojun Liao 已提交
23 24 25
#include "qExecutor.h"
#include "qResultbuf.h"
#include "qUtil.h"
S
slguan 已提交
26
#include "queryLog.h"
27
#include "tlosertree.h"
28
#include "ttype.h"
H
Haojun Liao 已提交
29
#include "tscompression.h"
30

31
#define IS_MASTER_SCAN(runtime)        ((runtime)->scanFlag == MASTER_SCAN)
H
hjxilinx 已提交
32
#define IS_REVERSE_SCAN(runtime)       ((runtime)->scanFlag == REVERSE_SCAN)
33
#define SET_MASTER_SCAN_FLAG(runtime)  ((runtime)->scanFlag = MASTER_SCAN)
H
hjxilinx 已提交
34
#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN)
35

36
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
37

H
Haojun Liao 已提交
38 39
#define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0}

S
TD-1057  
Shengliang Guan 已提交
40
#define TIME_WINDOW_COPY(_dst, _src)  do {\
H
Haojun Liao 已提交
41 42
   (_dst).skey = (_src).skey;\
   (_dst).ekey = (_src).ekey;\
H
Haojun Liao 已提交
43
} while (0)
S
TD-1057  
Shengliang Guan 已提交
44

45
enum {
46 47
  TS_JOIN_TS_EQUAL       = 0,
  TS_JOIN_TS_NOT_EQUALS  = 1,
48 49 50
  TS_JOIN_TAG_NOT_EQUALS = 2,
};

H
Haojun Liao 已提交
51 52 53 54 55
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP   = 2,
} SResultTsInterpType;

H
Haojun Liao 已提交
56
#if 0
H
Haojun Liao 已提交
57
static UNUSED_FUNC void *u_malloc (size_t __size) {
H
Haojun Liao 已提交
58
  uint32_t v = rand();
H
Haojun Liao 已提交
59 60

  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
61 62
    return NULL;
  } else {
H
Haojun Liao 已提交
63
    return malloc(__size);
H
Haojun Liao 已提交
64
  }
H
Haojun Liao 已提交
65 66
}

H
Haojun Liao 已提交
67 68
static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) {
  uint32_t v = rand();
H
Haojun Liao 已提交
69
  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
70 71 72 73 74 75
    return NULL;
  } else {
    return calloc(num, __size);
  }
}

H
Haojun Liao 已提交
76 77 78 79 80 81 82 83 84
static UNUSED_FUNC void* u_realloc(void* p, size_t __size) {
  uint32_t v = rand();
  if (v % 5 <= 1) {
    return NULL;
  } else {
    return realloc(p, __size);
  }
}

H
Haojun Liao 已提交
85
#define calloc  u_calloc
H
Haojun Liao 已提交
86
#define malloc  u_malloc
H
Haojun Liao 已提交
87
#define realloc u_realloc
H
Haojun Liao 已提交
88
#endif
H
Haojun Liao 已提交
89

90
#define CLEAR_QUERY_STATUS(q, st)   ((q)->status &= (~(st)))
H
Haojun Liao 已提交
91
#define GET_NUM_OF_TABLEGROUP(q)    taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
92
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)
H
Haojun Liao 已提交
93

D
fix bug  
dapan1121 已提交
94 95
uint64_t queryHandleId = 0;

H
Haojun Liao 已提交
96
int32_t getMaximumIdleDurationSec() {
97 98
  return tsShellActivityTimer * 2;
}
99

D
dapan1121 已提交
100 101 102
int64_t genQueryId(void) {
  int64_t uid = 0;
  int64_t did = tsDnodeId;
H
Haojun Liao 已提交
103

D
dapan1121 已提交
104
  uid = did << 54;
H
Haojun Liao 已提交
105

D
dapan1121 已提交
106 107 108
  int64_t pid = ((int64_t)taosGetPId()) & 0x3FF;

  uid |= pid << 44;
H
Haojun Liao 已提交
109

D
dapan1121 已提交
110 111 112
  int64_t ts = taosGetTimestampMs() & 0x1FFFFFFFF;

  uid |= ts << 11;
H
Haojun Liao 已提交
113

D
dapan1121 已提交
114 115 116 117 118 119 120
  int64_t sid = atomic_add_fetch_64(&queryHandleId, 1) & 0x7FF;

  uid |= sid;

  return uid;
}

H
Haojun Liao 已提交
121 122 123 124 125
static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
  int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
  if (pQueryAttr->interval.intervalUnit != 'n' && pQueryAttr->interval.intervalUnit != 'y') {
    tw->skey += pQueryAttr->interval.sliding * factor;
    tw->ekey = tw->skey + pQueryAttr->interval.interval - 1;
126 127 128
    return;
  }

H
Haojun Liao 已提交
129 130
  int64_t key = tw->skey / 1000, interval = pQueryAttr->interval.interval;
  if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
131 132
    key /= 1000;
  }
H
Haojun Liao 已提交
133
  if (pQueryAttr->interval.intervalUnit == 'y') {
134 135
    interval *= 12;
  }
136 137 138 139 140

  struct tm tm;
  time_t t = (time_t)key;
  localtime_r(&t, &tm);

S
Shengliang Guan 已提交
141
  int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
142 143 144 145
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->skey = mktime(&tm) * 1000L;

S
Shengliang Guan 已提交
146
  mon = (int)(mon + interval);
147 148 149 150
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->ekey = mktime(&tm) * 1000L;

H
Haojun Liao 已提交
151
  if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
152 153 154 155 156 157
    tw->skey *= 1000L;
    tw->ekey *= 1000L;
  }
  tw->ekey -= 1;
}

H
Haojun Liao 已提交
158
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
159 160
static void setResultOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRow* pResult, SQLFunctionCtx* pCtx,
                               int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
161

H
Haojun Liao 已提交
162
void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset);
163
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId);
164

H
Haojun Liao 已提交
165
static void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex);
166

H
Haojun Liao 已提交
167
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
168
static bool hasMainOutput(SQueryAttr *pQueryAttr);
169

H
Haojun Liao 已提交
170
static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
171
static void releaseQueryBuf(size_t numOfTables);
172
static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order);
H
Haojun Liao 已提交
173
static STsdbQueryCond createTsdbQueryCond(SQueryAttr* pQueryAttr, STimeWindow* win);
H
Haojun Liao 已提交
174
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo);
175

H
Haojun Liao 已提交
176
static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream);
177 178 179
static int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols,
                                  SSingleColumnFilterInfo** pFilterInfo, uint64_t qId);
static void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols);
H
Haojun Liao 已提交
180

H
Haojun Liao 已提交
181
static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr);
H
Haojun Liao 已提交
182

H
Haojun Liao 已提交
183 184 185 186
static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput);
static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput);
static void destroyArithOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
187
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
188
static void destroyOperatorInfo(SOperatorInfo* pOperator);
H
Haojun Liao 已提交
189

H
Haojun Liao 已提交
190
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock);
H
Haojun Liao 已提交
191

H
Haojun Liao 已提交
192
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock);
H
Haojun Liao 已提交
193
static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SGroupbyOperatorInfo *pInfo, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex);
H
Haojun Liao 已提交
194

H
Haojun Liao 已提交
195
static void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size);
H
Haojun Liao 已提交
196 197
static void getAlignQueryTimeWindow(SQueryAttr *pQueryAttr, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win);
static void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo);
H
Haojun Liao 已提交
198 199
static void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable);
static void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr);
H
Haojun Liao 已提交
200
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
201 202 203
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
204

H
Haojun Liao 已提交
205
// setup the output buffer for each operator
H
Haojun Liao 已提交
206
SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows) {
207 208
  const static int32_t minSize = 8;

H
Haojun Liao 已提交
209
  SSDataBlock *res = calloc(1, sizeof(SSDataBlock));
H
Haojun Liao 已提交
210
  res->info.numOfCols = numOfOutput;
H
Haojun Liao 已提交
211

H
Haojun Liao 已提交
212 213
  res->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
214
    SColumnInfoData idata = {{0}};
H
Haojun Liao 已提交
215 216
    idata.info.type  = pExpr[i].base.resType;
    idata.info.bytes = pExpr[i].base.resBytes;
H
Haojun Liao 已提交
217
    idata.info.colId = pExpr[i].base.resColId;
218

H
Haojun Liao 已提交
219 220
    int32_t size = MAX(idata.info.bytes * numOfRows, minSize);
    idata.pData = calloc(1, size);  // at least to hold a pointer on x64 platform
H
Haojun Liao 已提交
221 222
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
223 224

  return res;
H
Haojun Liao 已提交
225 226
}

227
void* destroyOutputBuf(SSDataBlock* pBlock) {
H
Haojun Liao 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
  if (pBlock == NULL) {
    return NULL;
  }

  int32_t numOfOutput = pBlock->info.numOfCols;
  for(int32_t i = 0; i < numOfOutput; ++i) {
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
    tfree(pColInfoData->pData);
  }

  taosArrayDestroy(pBlock->pDataBlock);
  tfree(pBlock->pBlockStatis);
  tfree(pBlock);
  return NULL;
}

sangshuduo's avatar
sangshuduo 已提交
244
int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
245 246
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
  bool    hasMainFunction = hasMainOutput(pQueryAttr);
H
Haojun Liao 已提交
247

sangshuduo's avatar
sangshuduo 已提交
248
  int32_t maxOutput = 0;
H
Haojun Liao 已提交
249
  for (int32_t j = 0; j < numOfOutput; ++j) {
H
Haojun Liao 已提交
250
    int32_t id = pCtx[j].functionId;
H
Haojun Liao 已提交
251 252 253 254 255

    /*
     * ts, tag, tagprj function can not decide the output number of current query
     * the number of output result is decided by main output
     */
H
Haojun Liao 已提交
256
    if (hasMainFunction && (id == TSDB_FUNC_TS || id == TSDB_FUNC_TAG || id == TSDB_FUNC_TAGPRJ)) {
H
Haojun Liao 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269
      continue;
    }

    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo != NULL && maxOutput < pResInfo->numOfRes) {
      maxOutput = pResInfo->numOfRes;
    }
  }

  assert(maxOutput >= 0);
  return maxOutput;
}

H
Haojun Liao 已提交
270
static void clearNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
271 272 273 274 275 276
  for (int32_t j = 0; j < numOfOutput; ++j) {
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    pResInfo->numOfRes = 0;
  }
}

H
Haojun Liao 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
static bool isSelectivityWithTagsQuery(SQLFunctionCtx *pCtx, int32_t numOfOutput) {
  bool    hasTags = false;
  int32_t numOfSelectivity = 0;

  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functId = pCtx[i].functionId;
    if (functId == TSDB_FUNC_TAG_DUMMY || functId == TSDB_FUNC_TS_DUMMY) {
      hasTags = true;
      continue;
    }

    if ((aAggs[functId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
      numOfSelectivity++;
    }
  }

  return (numOfSelectivity > 0 && hasTags);
}
295

H
Haojun Liao 已提交
296 297 298
static bool isProjQuery(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functId = pQueryAttr->pExpr1[i].base.functionId;
299 300 301 302 303 304 305 306
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

H
Haojun Liao 已提交
307 308 309 310 311 312 313 314 315 316 317 318
static bool hasNullRv(SColIndex* pColIndex, SDataStatis *pStatis) {
  if (TSDB_COL_IS_TAG(pColIndex->flag) || TSDB_COL_IS_UD_COL(pColIndex->flag) || pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
    return false;
  }

  if (pStatis != NULL && pStatis->numOfNull == 0) {
    return false;
  }

  return true;
}

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, SQueryRuntimeEnv* pRuntimeEnv) {
  // more than the capacity, reallocate the resources
  if (pResultRowInfo->size < pResultRowInfo->capacity) {
    return;
  }

  int64_t newCapacity = 0;
  if (pResultRowInfo->capacity > 10000) {
    newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25);
  } else {
    newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5);
  }

  char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES));
  if (t == NULL) {
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

  pResultRowInfo->pResult = (SResultRow **)t;

  int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity;
  memset(&pResultRowInfo->pResult[pResultRowInfo->capacity], 0, POINTER_BYTES * inc);

  pResultRowInfo->capacity = (int32_t)newCapacity;
}

H
Haojun Liao 已提交
345
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
346
                                             int16_t bytes, bool masterscan, uint64_t uid) {
347
  bool existed = false;
H
Haojun Liao 已提交
348
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
349 350 351 352 353

  SResultRow **p1 =
      (SResultRow **)taosHashGet(pRuntimeEnv->pResultRowHashTable, pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));

  // in case of repeat scan/reverse scan, no new time window added.
H
Haojun Liao 已提交
354
  if (QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQueryAttr)) {
355 356 357 358 359 360 361 362 363 364 365 366 367
    if (!masterscan) {  // the *p1 may be NULL in case of sliding+offset exists.
      return (p1 != NULL)? *p1:NULL;
    }

    if (p1 != NULL) {
      for(int32_t i = pResultRowInfo->size - 1; i >= 0; --i) {
        if (pResultRowInfo->pResult[i] == (*p1)) {
          pResultRowInfo->curIndex = i;
          existed = true;
          break;
        }
      }
    }
368
  } else {
369 370
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
371
    }
372
  }
373

374
  if (!existed) {
375
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
376

377 378 379 380 381 382 383 384 385 386 387 388
    SResultRow *pResult = NULL;
    if (p1 == NULL) {
      pResult = getNewResultRow(pRuntimeEnv->pool);
      int32_t ret = initResultRow(pResult);
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

      // add a new result set for a new group
      taosHashPut(pRuntimeEnv->pResultRowHashTable, pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pResult, POINTER_BYTES);
    } else {
      pResult = *p1;
389
    }
H
Haojun Liao 已提交
390

391
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
392
    pResultRowInfo->curIndex = pResultRowInfo->size++;
393
  }
394

395
  // too many time window in query
H
Haojun Liao 已提交
396
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
397 398 399
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
400
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
401 402
}

H
Haojun Liao 已提交
403 404 405
static void getInitialStartTimeWindow(SQueryAttr* pQueryAttr, TSKEY ts, STimeWindow* w) {
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
    getAlignQueryTimeWindow(pQueryAttr, ts, ts, pQueryAttr->window.ekey, w);
406 407
  } else {
    // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
H
Haojun Liao 已提交
408
    getAlignQueryTimeWindow(pQueryAttr, ts, pQueryAttr->window.ekey, ts, w);
409 410 411

    int64_t key = w->skey;
    while(key < ts) { // moving towards end
H
Haojun Liao 已提交
412 413
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        key = taosTimeAdd(key, pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit, pQueryAttr->precision);
414
      } else {
H
Haojun Liao 已提交
415
        key += pQueryAttr->interval.sliding;
416 417 418 419 420 421 422 423 424 425 426
      }

      if (key >= ts) {
        break;
      }

      w->skey = key;
    }
  }
}

427
// get the correct time window according to the handled timestamp
H
Haojun Liao 已提交
428
static STimeWindow getActiveTimeWindow(SResultRowInfo * pResultRowInfo, int64_t ts, SQueryAttr *pQueryAttr) {
429
  STimeWindow w = {0};
430

H
Haojun Liao 已提交
431
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
432
    if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
433
      getInitialStartTimeWindow(pQueryAttr, ts, &w);
434 435 436 437
      pResultRowInfo->prevSKey = w.skey;
    } else {
      w.skey = pResultRowInfo->prevSKey;
    }
H
Haojun Liao 已提交
438

H
Haojun Liao 已提交
439 440
    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
      w.ekey = taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
441
    } else {
H
Haojun Liao 已提交
442
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
443
    }
444
  } else {
H
Haojun Liao 已提交
445 446
    int32_t slot = curTimeWindowIndex(pResultRowInfo);
    SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot);
447
    w = pWindowRes->win;
448
  }
449

450
  if (w.skey > ts || w.ekey < ts) {
H
Haojun Liao 已提交
451 452 453
    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
      w.skey = taosTimeTruncate(ts, &pQueryAttr->interval, pQueryAttr->precision);
      w.ekey = taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
454 455
    } else {
      int64_t st = w.skey;
456

457
      if (st > ts) {
H
Haojun Liao 已提交
458
        st -= ((st - ts + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
459
      }
460

H
Haojun Liao 已提交
461
      int64_t et = st + pQueryAttr->interval.interval - 1;
462
      if (et < ts) {
H
Haojun Liao 已提交
463
        st += ((ts - et + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
464
      }
465

466
      w.skey = st;
H
Haojun Liao 已提交
467
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
468
    }
469
  }
470

471 472 473 474
  /*
   * query border check, skey should not be bounded by the query time range, since the value skey will
   * be used as the time window index value. So we only change ekey of time window accordingly.
   */
H
Haojun Liao 已提交
475 476
  if (w.ekey > pQueryAttr->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
    w.ekey = pQueryAttr->window.ekey;
477
  }
478

479 480 481
  return w;
}

H
Haojun Liao 已提交
482 483
// a new buffer page for each table. Needs to opt this design
static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf *pResultBuf, int32_t tid, uint32_t size) {
484
  if (pWindowRes->pageId != -1) {
485 486
    return 0;
  }
487

488
  tFilePage *pData = NULL;
489

490 491
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
492
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
493

H
Haojun Liao 已提交
494
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
495
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
496
  } else {
H
Haojun Liao 已提交
497 498 499
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
500

H
Haojun Liao 已提交
501
    if (pData->num + size > pResultBuf->pageSize) {
H
Haojun Liao 已提交
502 503
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
504
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
505
      if (pData != NULL) {
506
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
507 508 509
      }
    }
  }
510

511 512 513
  if (pData == NULL) {
    return -1;
  }
514

515
  // set the number of rows in current disk page
516 517
  if (pWindowRes->pageId == -1) {  // not allocated yet, allocate new buffer
    pWindowRes->pageId = pageId;
sangshuduo's avatar
sangshuduo 已提交
518
    pWindowRes->offset = (int32_t)pData->num;
H
Haojun Liao 已提交
519

H
Haojun Liao 已提交
520
    pData->num += size;
521
    assert(pWindowRes->pageId >= 0);
522
  }
523

524 525 526
  return 0;
}

527
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
528
                                       bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
529
                                       int32_t numOfOutput, int32_t* rowCellInfoOffset) {
530 531
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
532

533
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
534
  if (pResultRow == NULL) {
535 536
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
537
  }
538

539
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
540
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
541
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQueryAttr->intermediateResultRowSize);
H
Haojun Liao 已提交
542
    if (ret != TSDB_CODE_SUCCESS) {
543 544 545
      return -1;
    }
  }
546

547
  // set time window for current result
H
Haojun Liao 已提交
548
  pResultRow->win = (*win);
549
  *pResult = pResultRow;
H
Haojun Liao 已提交
550
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
551

552 553 554
  return TSDB_CODE_SUCCESS;
}

555 556 557 558 559 560 561 562 563
static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) {
  assert(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
  if (type == RESULT_ROW_START_INTERP) {
    pResult->startInterp = true;
  } else {
    pResult->endInterp   = true;
  }
}

H
Haojun Liao 已提交
564
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
565 566 567 568 569 570 571 572
  assert(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
  if (type == RESULT_ROW_START_INTERP) {
    return pResult->startInterp == true;
  } else {
    return pResult->endInterp   == true;
  }
}

H
Haojun Liao 已提交
573
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
574 575
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
576

H
Haojun Liao 已提交
577 578 579 580
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
581

H
Haojun Liao 已提交
582 583 584 585 586 587 588 589 590 591 592 593
      if (pData[end + pos] == ekey) {
        forwardStep += 1;
      }
    }
  } else {
    int32_t end = searchFn((char *)pData, pos + 1, ekey, order);
    if (end >= 0) {
      forwardStep = pos - end;

      if (pData[end] == ekey) {
        forwardStep += 1;
      }
594 595
    }
  }
596

H
Haojun Liao 已提交
597
  assert(forwardStep > 0);
598 599 600
  return forwardStep;
}

601
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
602
  int64_t skey = TSKEY_INITIAL_VAL;
603 604 605
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
606
    if (pResult->closed) {
607
      break;
H
Haojun Liao 已提交
608 609
    }

610
    // new closed result rows
611 612 613 614 615 616 617 618 619 620
    if (timeWindowInterpo) {
      if (pResult->endInterp && ((pResult->win.skey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery))) {
        if (i > 0) { // the first time window, the startInterp is false.
          assert(pResult->startInterp);
        }

        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
621
    } else {
622 623 624 625 626
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
627 628 629
    }
  }

630
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
631
  if (skey == TSKEY_INITIAL_VAL) {
632
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
633 634
  } else {

635 636 637 638 639
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
640
    }
641

D
fix bug  
dapan1121 已提交
642
    if (i == pResultRowInfo->size - 1) {
643
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
644 645 646 647
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

648
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
649
  }
650
}
651

H
Haojun Liao 已提交
652 653 654
static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, SQueryAttr* pQueryAttr, TSKEY lastKey) {
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
  if ((lastKey > pQueryAttr->window.ekey && ascQuery) || (lastKey < pQueryAttr->window.ekey && (!ascQuery))) {
655 656 657
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
658
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
659
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQueryAttr->timeWindowInterpo);
660
  }
661 662
}

H
Haojun Liao 已提交
663
static int32_t getNumOfRowsInTimeWindow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo *pDataBlockInfo, TSKEY *pPrimaryColumn,
H
hjxilinx 已提交
664
                                        int32_t startPos, TSKEY ekey, __block_search_fn_t searchFn, bool updateLastKey) {
665
  assert(startPos >= 0 && startPos < pDataBlockInfo->rows);
H
Haojun Liao 已提交
666
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
667
  STableQueryInfo* item = pRuntimeEnv->current;
668

H
Haojun Liao 已提交
669
  int32_t num   = -1;
H
Haojun Liao 已提交
670
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
671
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
672

H
Haojun Liao 已提交
673
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
674
    if (ekey < pDataBlockInfo->window.ekey) {
675
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
676 677
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
678 679
      }
    } else {
680
      num = pDataBlockInfo->rows - startPos;
681
      if (updateLastKey) {
H
hjxilinx 已提交
682
        item->lastKey = pDataBlockInfo->window.ekey + step;
683 684 685 686
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
687
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
688 689
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
690 691 692 693
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
694
        item->lastKey = pDataBlockInfo->window.skey + step;
695 696 697
      }
    }
  }
698

H
Haojun Liao 已提交
699
  assert(num > 0);
700 701 702
  return num;
}

H
Haojun Liao 已提交
703 704
static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, STimeWindow* pWin, int32_t offset,
                             int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput) {
H
Haojun Liao 已提交
705
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
706 707
  bool hasPrev = pCtx[0].preAggVals.isSet;

708
  for (int32_t k = 0; k < numOfOutput; ++k) {
709
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
710
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
711

712
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
713

H
Haojun Liao 已提交
714
    int32_t pos = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? offset : offset - (forwardStep - 1);
715 716
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
717 718 719 720 721
    }

    if (tsCol != NULL) {
      pCtx[k].ptsList = &tsCol[pos];
    }
722

H
Haojun Liao 已提交
723
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
724

725 726 727 728 729
    // not a whole block involved in query processing, statistics data can not be used
    // NOTE: the original value of isSet have been changed here
    if (pCtx[k].preAggVals.isSet && forwardStep < numOfTotal) {
      pCtx[k].preAggVals.isSet = false;
    }
H
Haojun Liao 已提交
730

731 732
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
733
    }
734 735 736

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
737
    pCtx[k].pInput = start;
738 739 740 741
  }
}


H
Haojun Liao 已提交
742
static int32_t getNextQualifiedWindow(SQueryAttr* pQueryAttr, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
743
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
744
  getNextTimeWindow(pQueryAttr, pNext);
745

H
Haojun Liao 已提交
746
  // next time window is not in current block
H
Haojun Liao 已提交
747 748
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
H
Haojun Liao 已提交
749 750
    return -1;
  }
751

H
Haojun Liao 已提交
752
  TSKEY startKey = -1;
H
Haojun Liao 已提交
753
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
754
    startKey = pNext->skey;
H
Haojun Liao 已提交
755 756
    if (startKey < pQueryAttr->window.skey) {
      startKey = pQueryAttr->window.skey;
757
    }
H
Haojun Liao 已提交
758
  } else {
H
Haojun Liao 已提交
759
    startKey = pNext->ekey;
H
Haojun Liao 已提交
760 761
    if (startKey > pQueryAttr->window.skey) {
      startKey = pQueryAttr->window.skey;
762
    }
H
Haojun Liao 已提交
763
  }
764

H
Haojun Liao 已提交
765
  int32_t startPos = 0;
H
Haojun Liao 已提交
766

H
Haojun Liao 已提交
767
  // tumbling time window query, a special case of sliding time window query
H
Haojun Liao 已提交
768 769
  if (pQueryAttr->interval.sliding == pQueryAttr->interval.interval && prevPosition != -1) {
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
770 771
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
772
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
773
      startPos = 0;
H
Haojun Liao 已提交
774
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
775 776
      startPos = pDataBlockInfo->rows - 1;
    } else {
H
Haojun Liao 已提交
777
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQueryAttr->order.order);
H
Haojun Liao 已提交
778
    }
H
Haojun Liao 已提交
779
  }
780

H
Haojun Liao 已提交
781 782 783 784
  /*
   * This time window does not cover any data, try next time window,
   * this case may happen when the time window is too small
   */
H
Haojun Liao 已提交
785
  if (primaryKeys == NULL) {
H
Haojun Liao 已提交
786
    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
787
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
788
    } else {
H
Haojun Liao 已提交
789
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
790
    }
H
Haojun Liao 已提交
791
  } else {
H
Haojun Liao 已提交
792
    if (QUERY_IS_ASC_QUERY(pQueryAttr) && primaryKeys[startPos] > pNext->ekey) {
H
Haojun Liao 已提交
793
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
794 795 796
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQueryAttr->interval, pQueryAttr->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
797
      } else {
H
Haojun Liao 已提交
798 799
        pNext->ekey += ((next - pNext->ekey + pQueryAttr->interval.sliding - 1)/pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
        pNext->skey = pNext->ekey - pQueryAttr->interval.interval + 1;
H
Haojun Liao 已提交
800
      }
H
Haojun Liao 已提交
801
    } else if ((!QUERY_IS_ASC_QUERY(pQueryAttr)) && primaryKeys[startPos] < pNext->skey) {
H
Haojun Liao 已提交
802
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
803 804 805
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQueryAttr->interval, pQueryAttr->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
806
      } else {
H
Haojun Liao 已提交
807 808
        pNext->skey -= ((pNext->skey - next + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
        pNext->ekey = pNext->skey + pQueryAttr->interval.interval - 1;
H
Haojun Liao 已提交
809
      }
810
    }
811
  }
812

H
Haojun Liao 已提交
813
  return startPos;
814 815
}

H
Haojun Liao 已提交
816
static FORCE_INLINE TSKEY reviseWindowEkey(SQueryAttr *pQueryAttr, STimeWindow *pWindow) {
817
  TSKEY ekey = -1;
H
Haojun Liao 已提交
818
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
819
    ekey = pWindow->ekey;
H
Haojun Liao 已提交
820 821
    if (ekey > pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
822 823 824
    }
  } else {
    ekey = pWindow->skey;
H
Haojun Liao 已提交
825 826
    if (ekey < pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
827 828
    }
  }
829

830 831 832
  return ekey;
}

H
Haojun Liao 已提交
833 834 835 836 837 838 839 840 841 842 843 844
static void setNotInterpoWindowKey(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t type) {
  if (type == RESULT_ROW_START_INTERP) {
    for (int32_t k = 0; k < numOfOutput; ++k) {
      pCtx[k].start.key = INT64_MIN;
    }
  } else {
    for (int32_t k = 0; k < numOfOutput; ++k) {
      pCtx[k].end.key = INT64_MIN;
    }
  }
}

845
// window start key interpolation
H
Haojun Liao 已提交
846

847

H
Haojun Liao 已提交
848
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
849
    int32_t rowIndex) {
850 851 852 853
  if (pDataBlock == NULL) {
    return;
  }

H
Haojun Liao 已提交
854 855
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  for (int32_t k = 0; k < pQueryAttr->numOfCols; ++k) {
856
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, k);
H
Haojun Liao 已提交
857
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
858 859 860
  }
}

H
Haojun Liao 已提交
861
static TSKEY getStartTsKey(SQueryAttr* pQueryAttr, STimeWindow* win, const TSKEY* tsCols, int32_t rows) {
862 863
  TSKEY ts = TSKEY_INITIAL_VAL;

H
Haojun Liao 已提交
864
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
865
  if (tsCols == NULL) {
H
Haojun Liao 已提交
866
    ts = ascQuery? win->skey : win->ekey;
867
  } else {
H
Haojun Liao 已提交
868
    int32_t offset = ascQuery? 0:rows-1;
869 870 871 872 873 874
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
875 876
static void setArithParams(SArithmeticSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
  sas->numOfCols = (int32_t) pSDataBlock->info.numOfCols;
H
Haojun Liao 已提交
877
  sas->pExprInfo = pExprInfo;
H
Haojun Liao 已提交
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897

  sas->colList = calloc(1, pSDataBlock->info.numOfCols*sizeof(SColumnInfo));
  for(int32_t i = 0; i < sas->numOfCols; ++i) {
    SColumnInfoData* pColData = taosArrayGet(pSDataBlock->pDataBlock, i);
    sas->colList[i] = pColData->info;
  }

  sas->data = calloc(sas->numOfCols, POINTER_BYTES);

  // set the input column data
  for (int32_t f = 0; f < pSDataBlock->info.numOfCols; ++f) {
    SColumnInfoData *pColumnInfoData = taosArrayGet(pSDataBlock->pDataBlock, f);
    sas->data[f] = pColumnInfoData->pData;
  }
}

static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order);
static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
    pCtx[i].order = order;
H
Haojun Liao 已提交
898
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
899
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
900

H
Haojun Liao 已提交
901 902 903 904
    setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);
  }
}

H
Haojun Liao 已提交
905
void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
H
Haojun Liao 已提交
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
  if (pCtx[0].functionId == TSDB_FUNC_ARITHM) {
    SArithmeticSupport* pSupport = (SArithmeticSupport*) pCtx[0].param[1].pz;
    if (pSupport->colList == NULL) {
      doSetInputDataBlock(pOperator, pCtx, pBlock, order);
    } else {
      doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
    }
  } else {
    if (pCtx[0].pInput == NULL && pBlock->pDataBlock != NULL) {
      doSetInputDataBlock(pOperator, pCtx, pBlock, order);
    } else {
      doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
    }
  }
}

static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
    pCtx[i].order = order;
H
Haojun Liao 已提交
925
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
926
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
927 928 929 930 931 932 933

    setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);

    if (pCtx[i].functionId == TSDB_FUNC_ARITHM) {
      setArithParams((SArithmeticSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock);
    } else {
      SColIndex* pCol = &pOperator->pExpr[i].base.colInfo;
H
Haojun Liao 已提交
934 935
      if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || (pCol->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) ||
          (TSDB_COL_IS_TAG(pCol->flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
H
Haojun Liao 已提交
936 937
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
H
Haojun Liao 已提交
938

H
Haojun Liao 已提交
939
        // in case of the block distribution query, the inputBytes is not a constant value.
H
Haojun Liao 已提交
940
        pCtx[i].pInput = p->pData;
941
        assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);
H
Haojun Liao 已提交
942

H
Haojun Liao 已提交
943
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
944
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
945
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
946
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
947
        }
H
Haojun Liao 已提交
948 949 950 951 952 953 954 955 956 957
      } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);

        pCtx[i].pInput = p->pData;
        assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);
        for(int32_t j = 0; j < pBlock->info.rows; ++j) {
          char* dst = p->pData + j * p->info.bytes;
          tVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
        }
H
Haojun Liao 已提交
958 959 960 961 962
      }
    }
  }
}

H
Haojun Liao 已提交
963
static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) {
H
Haojun Liao 已提交
964
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
965

H
Haojun Liao 已提交
966
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
967
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
968
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
969
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
970 971 972 973 974
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

H
Haojun Liao 已提交
975
static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
976
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
977

H
Haojun Liao 已提交
978
  for (int32_t k = 0; k < numOfOutput; ++k) {
H
Haojun Liao 已提交
979
    pCtx[k].startTs = pQueryAttr->window.skey;
H
Haojun Liao 已提交
980 981 982 983 984 985

    // Always set the asc order for merge stage process
    if (pCtx[k].currentStage == MERGE_STAGE) {
      pCtx[k].order = TSDB_ORDER_ASC;
    }

986
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
987 988 989
  }
}

H
Haojun Liao 已提交
990 991
void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, SArray* pDataBlock, TSKEY prevTs,
                               int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type) {
H
Haojun Liao 已提交
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
  SExprInfo* pExpr = pOperator->pExpr;

  SQLFunctionCtx* pCtx = pInfo->pCtx;

  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
    int32_t functionId = pCtx[k].functionId;
    if (functionId != TSDB_FUNC_TWA && functionId != TSDB_FUNC_INTERP) {
      pCtx[k].start.key = INT64_MIN;
      continue;
    }

    SColIndex *      pColIndex = &pExpr[k].base.colInfo;
    int16_t          index = pColIndex->colIndex;
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index);

    assert(pColInfo->info.colId == pColIndex->colId && curTs != windowKey);
    double v1 = 0, v2 = 0, v = 0;

    if (prevRowIndex == -1) {
      GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pRuntimeEnv->prevRow[index]);
    } else {
      GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pColInfo->pData + prevRowIndex * pColInfo->info.bytes);
    }

    GET_TYPED_DATA(v2, double, pColInfo->info.type, (char *)pColInfo->pData + curRowIndex * pColInfo->info.bytes);

H
Haojun Liao 已提交
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
    if (functionId == TSDB_FUNC_INTERP) {
      if (type == RESULT_ROW_START_INTERP) {
        pCtx[k].start.key = prevTs;
        pCtx[k].start.val = v1;

        pCtx[k].end.key = curTs;
        pCtx[k].end.val = v2;
      }
    } else if (functionId == TSDB_FUNC_TWA) {
      SPoint point1 = (SPoint){.key = prevTs,    .val = &v1};
      SPoint point2 = (SPoint){.key = curTs,     .val = &v2};
      SPoint point  = (SPoint){.key = windowKey, .val = &v };
H
Haojun Liao 已提交
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044

      taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE);

      if (type == RESULT_ROW_START_INTERP) {
        pCtx[k].start.key = point.key;
        pCtx[k].start.val = v;
      } else {
        pCtx[k].end.key = point.key;
        pCtx[k].end.val = v;
      }
    }
  }
}

H
Haojun Liao 已提交
1045 1046
static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, int32_t pos,
                                              int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols, STimeWindow* win) {
H
Haojun Liao 已提交
1047
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
1048
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1049

H
Haojun Liao 已提交
1050
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1051

H
Haojun Liao 已提交
1052 1053 1054 1055 1056
  TSKEY curTs  = tsCols[pos];
  TSKEY lastTs = *(TSKEY *) pRuntimeEnv->prevRow[0];

  // lastTs == INT64_MIN and pos == 0 means this is the first time window, interpolation is not needed.
  // start exactly from this point, no need to do interpolation
H
Haojun Liao 已提交
1057
  TSKEY key = ascQuery? win->skey:win->ekey;
H
Haojun Liao 已提交
1058 1059 1060 1061 1062
  if (key == curTs) {
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1063
  if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
H
Haojun Liao 已提交
1064 1065 1066 1067
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1068
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1069
  TSKEY   prevTs = ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))? lastTs:tsCols[pos - step];
H
Haojun Liao 已提交
1070

H
Haojun Liao 已提交
1071 1072
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1073 1074 1075 1076
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1077
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1078
  SQueryRuntimeEnv *pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
1079
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1080 1081 1082 1083
  int32_t numOfOutput = pOperatorInfo->numOfOutput;

  TSKEY   actualEndKey = tsCols[endRowIndex];

H
Haojun Liao 已提交
1084
  TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? win->ekey:win->skey;
H
Haojun Liao 已提交
1085 1086

  // not ended in current data block, do not invoke interpolation
H
Haojun Liao 已提交
1087
  if ((key > blockEkey && QUERY_IS_ASC_QUERY(pQueryAttr)) || (key < blockEkey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
H
Haojun Liao 已提交
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
    setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP);
    return false;
  }

  // there is actual end point of current time window, no interpolation need
  if (key == actualEndKey) {
    setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1098
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1099 1100 1101 1102
  int32_t nextRowIndex = endRowIndex + step;
  assert(nextRowIndex >= 0);

  TSKEY nextKey = tsCols[nextRowIndex];
H
Haojun Liao 已提交
1103 1104
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1105 1106 1107 1108 1109 1110
  return true;
}

static void doWindowBorderInterpolation(SOperatorInfo* pOperatorInfo, SSDataBlock* pBlock, SQLFunctionCtx* pCtx,
    SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
1111 1112
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  if (!pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1113 1114 1115 1116
    return;
  }

  assert(pBlock != NULL);
H
Haojun Liao 已提交
1117
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1118 1119 1120 1121 1122 1123 1124 1125

  SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, 0);

  TSKEY  *tsCols = (TSKEY *)(pColInfo->pData);
  bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
  if (!done) { // it is not interpolated, now start to generated the interpolated value
    int32_t startRowIndex = startPos;
    bool interp = setTimeWindowInterpolationStartTs(pOperatorInfo, pCtx, startRowIndex, pBlock->info.rows, pBlock->pDataBlock,
H
Haojun Liao 已提交
1126
        tsCols, win);
H
Haojun Liao 已提交
1127 1128 1129 1130
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    }
  } else {
H
Haojun Liao 已提交
1131
    setNotInterpoWindowKey(pCtx, pQueryAttr->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1132 1133 1134
  }

  // point interpolation does not require the end key time window interpolation.
H
Haojun Liao 已提交
1135
  if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
1136 1137 1138 1139 1140 1141 1142 1143
    return;
  }

  // interpolation query does not generate the time window end interpolation
  done = resultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
  if (!done) {
    int32_t endRowIndex = startPos + (forwardStep - 1) * step;

H
Haojun Liao 已提交
1144
    TSKEY endKey = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey:pBlock->info.window.skey;
H
Haojun Liao 已提交
1145 1146 1147 1148 1149
    bool  interp = setTimeWindowInterpolationEndTs(pOperatorInfo, pCtx, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
    }
  } else {
H
Haojun Liao 已提交
1150
    setNotInterpoWindowKey(pCtx, pQueryAttr->numOfOutput, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1151 1152 1153
  }
}

H
Haojun Liao 已提交
1154 1155 1156
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
  STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info;

H
Haojun Liao 已提交
1157 1158
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
H
Haojun Liao 已提交
1159
  SQueryAttr*           pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1160

H
Haojun Liao 已提交
1161 1162
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1163

H
Haojun Liao 已提交
1164
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1165

H
Haojun Liao 已提交
1166 1167 1168
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1169
    tsCols = (int64_t*) pColDataInfo->pData;
H
Haojun Liao 已提交
1170 1171
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1172 1173
  }

H
Haojun Liao 已提交
1174
  int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1);
H
Haojun Liao 已提交
1175
  TSKEY ts = getStartTsKey(pQueryAttr, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1176

H
Haojun Liao 已提交
1177
  STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQueryAttr);
H
Haojun Liao 已提交
1178
  bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);
H
Haojun Liao 已提交
1179

H
Haojun Liao 已提交
1180 1181 1182
  SResultRow* pResult = NULL;
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                        numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1183
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1184
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1185 1186 1187
  }

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1188
  TSKEY   ekey = reviseWindowEkey(pQueryAttr, &win);
H
Haojun Liao 已提交
1189
  forwardStep =
H
Haojun Liao 已提交
1190
      getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1191 1192

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1193
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1194
  if (prevIndex != -1 && prevIndex < curIndex && pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1195
    for (int32_t j = prevIndex; j < curIndex; ++j) {  // previous time window may be all closed already.
H
Haojun Liao 已提交
1196
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1197
      if (pRes->closed) {
H
Haojun Liao 已提交
1198 1199
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1200
        continue;
H
Haojun Liao 已提交
1201
      }
H
Haojun Liao 已提交
1202 1203

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1204 1205
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1206 1207 1208 1209 1210
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

      assert(!resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1211

H
Haojun Liao 已提交
1212
      doTimeWindowInterpolation(pOperatorInfo, pInfo, pSDataBlock->pDataBlock, *(TSKEY *)pRuntimeEnv->prevRow[0],
H
Haojun Liao 已提交
1213 1214
            -1, tsCols[startPos], startPos, w.ekey, RESULT_ROW_END_INTERP);

H
Haojun Liao 已提交
1215
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1216
      setNotInterpoWindowKey(pInfo->pCtx, pQueryAttr->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1217

1218
      doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &w, startPos, 0, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1219 1220
    }

H
Haojun Liao 已提交
1221
    // restore current time window
H
Haojun Liao 已提交
1222 1223
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1224 1225 1226
    if (ret != TSDB_CODE_SUCCESS) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
H
Haojun Liao 已提交
1227 1228 1229
  }

  // window start key interpolation
H
Haojun Liao 已提交
1230
  doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
1231
  doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1232 1233 1234 1235

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1236
    startPos = getNextQualifiedWindow(pQueryAttr, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1237 1238
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1239 1240
    }

H
Haojun Liao 已提交
1241
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1242 1243
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1244
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1245
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1246 1247
    }

H
Haojun Liao 已提交
1248
    ekey = reviseWindowEkey(pQueryAttr, &nextWin);
H
Haojun Liao 已提交
1249
    forwardStep = getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1250 1251

    // window start(end) key interpolation
H
Haojun Liao 已提交
1252
    doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &nextWin, startPos, forwardStep);
1253
    doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &nextWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1254
  }
H
Haojun Liao 已提交
1255

H
Haojun Liao 已提交
1256
  if (pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1257
    int32_t rowIndex = ascQuery? (pSDataBlock->info.rows-1):0;
H
Haojun Liao 已提交
1258 1259
    saveDataBlockLastRow(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, rowIndex);
  }
H
Haojun Liao 已提交
1260

H
Haojun Liao 已提交
1261
  updateResultRowInfoActiveIndex(pResultRowInfo, pQueryAttr, pRuntimeEnv->current->lastKey);
H
Haojun Liao 已提交
1262 1263
}

H
Haojun Liao 已提交
1264 1265
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
1266
  STableQueryInfo*  item = pRuntimeEnv->current;
H
Haojun Liao 已提交
1267

H
Haojun Liao 已提交
1268
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1269 1270 1271 1272

  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int16_t     bytes = pColInfoData->info.bytes;
  int16_t     type = pColInfoData->info.type;
H
Haojun Liao 已提交
1273 1274

  if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) {
H
Haojun Liao 已提交
1275
    qError("QInfo:%"PRIu64" group by not supported on double/float columns, abort", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1276 1277
    return;
  }
H
Haojun Liao 已提交
1278

H
Haojun Liao 已提交
1279
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
sangshuduo's avatar
sangshuduo 已提交
1280
    char* val = ((char*)pColInfoData->pData) + bytes * j;
H
Haojun Liao 已提交
1281
    if (isNull(val, type)) {
H
Haojun Liao 已提交
1282 1283 1284
      continue;
    }

1285
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1286 1287 1288 1289 1290 1291 1292
    if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) {
      if (pInfo->prevData == NULL) {
        pInfo->prevData = malloc(bytes);
      }

      memcpy(pInfo->prevData, val, bytes);

H
Haojun Liao 已提交
1293 1294 1295 1296
      if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
        setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, val, bytes);
      }

H
Haojun Liao 已提交
1297 1298 1299 1300 1301
      int32_t ret =
          setGroupResultOutputBuf(pRuntimeEnv, pInfo, pOperator->numOfOutput, val, type, bytes, item->groupIndex);
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
      }
H
Haojun Liao 已提交
1302 1303
    }

H
Haojun Liao 已提交
1304
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1305
      pInfo->binfo.pCtx[k].size = 1;
H
Haojun Liao 已提交
1306 1307
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1308
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1309 1310 1311 1312 1313
      }
    }
  }
}

1314 1315
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSWindowOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
1316
  STableQueryInfo*  item = pRuntimeEnv->current;
1317 1318 1319 1320 1321 1322 1323

  // primary timestamp column
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, 0);

  bool    masterScan = IS_MASTER_SCAN(pRuntimeEnv);
  SOptrBasicInfo* pBInfo = &pInfo->binfo;

H
Haojun Liao 已提交
1324
  int64_t gap = pOperator->pRuntimeEnv->pQueryAttr->sw.gap;
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 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 1368 1369 1370 1371 1372 1373
  pInfo->numOfRows = 0;

  TSKEY* tsList = (TSKEY*)pColInfoData->pData;
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
    if (pInfo->prevTs == INT64_MIN) {
      pInfo->curWindow.skey = tsList[j];
      pInfo->curWindow.ekey = tsList[j];
      pInfo->prevTs = tsList[j];
      pInfo->numOfRows = 1;
      pInfo->start = j;
    } else if (tsList[j] - pInfo->prevTs <= gap) {
      pInfo->curWindow.ekey = tsList[j];
      pInfo->prevTs = tsList[j];
      pInfo->numOfRows += 1;
      pInfo->start = j;
    } else {  // start a new session window
      SResultRow* pResult = NULL;

      int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, &pBInfo->resultRowInfo, &pInfo->curWindow, masterScan,
                                            &pResult, item->groupIndex, pBInfo->pCtx, pOperator->numOfOutput,
                                            pBInfo->rowCellInfoOffset);
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
      }

      doApplyFunctions(pRuntimeEnv, pBInfo->pCtx, &pInfo->curWindow, pInfo->start, pInfo->numOfRows, tsList,
                       pSDataBlock->info.rows, pOperator->numOfOutput);

      pInfo->curWindow.skey = tsList[j];
      pInfo->curWindow.ekey = tsList[j];
      pInfo->prevTs = tsList[j];
      pInfo->numOfRows = 1;
      pInfo->start = j;
    }
  }

  SResultRow* pResult = NULL;

  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, &pBInfo->resultRowInfo, &pInfo->curWindow, masterScan,
                                        &pResult, item->groupIndex, pBInfo->pCtx, pOperator->numOfOutput,
                                        pBInfo->rowCellInfoOffset);
  if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
  }

  doApplyFunctions(pRuntimeEnv, pBInfo->pCtx, &pInfo->curWindow, pInfo->start, pInfo->numOfRows, tsList,
                   pSDataBlock->info.rows, pOperator->numOfOutput);
}

H
Haojun Liao 已提交
1374
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
  int64_t v = -1;
  GET_TYPED_DATA(v, int64_t, type, pData);
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
    if (pResultRow->key == NULL) {
      pResultRow->key = malloc(varDataTLen(pData));
      varDataCopy(pResultRow->key, pData);
    } else {
      assert(memcmp(pResultRow->key, pData, varDataTLen(pData)) == 0);
    }
  } else {
    pResultRow->win.skey = v;
    pResultRow->win.ekey = v;
  }
H
Haojun Liao 已提交
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
}

static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SGroupbyOperatorInfo *pInfo, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex) {
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;

  int32_t        *rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
  SResultRowInfo *pResultRowInfo    = &pInfo->binfo.resultRowInfo;
  SQLFunctionCtx *pCtx              = pInfo->binfo.pCtx;

  // not assign result buffer yet, add new result buffer, TODO remove it
  char* d = pData;
  int16_t len = bytes;
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
    d = varDataVal(pData);
    len = varDataLen(pData);
  }

  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, d, len, true, groupIndex);
  assert (pResultRow != NULL);
H
Haojun Liao 已提交
1407

H
Haojun Liao 已提交
1408
  setResultRowKey(pResultRow, pData, type);
H
Haojun Liao 已提交
1409
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
1410
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
H
Haojun Liao 已提交
1411 1412 1413 1414 1415
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1416 1417
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1418 1419
  return TSDB_CODE_SUCCESS;
}
1420

H
Haojun Liao 已提交
1421
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
  for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) {
    SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, k);
    if (TSDB_COL_IS_TAG(pColIndex->flag)) {
      continue;
    }

    int32_t colId = pColIndex->colId;

    for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
      if (pColInfo->info.colId == colId) {
        return i;
      }
    }
  }

  assert(0);
sangshuduo's avatar
sangshuduo 已提交
1439
  return -1;
H
Haojun Liao 已提交
1440 1441
}

1442
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1443
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
Haojun Liao 已提交
1444
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1445 1446 1447 1448 1449

  // in case of timestamp column, always generated results.
  if (functionId == TSDB_FUNC_TS) {
    return true;
  }
1450

1451 1452 1453
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1454

1455
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
Haojun Liao 已提交
1456
    return QUERY_IS_ASC_QUERY(pQueryAttr);
H
hjxilinx 已提交
1457
  }
1458

H
Haojun Liao 已提交
1459
  // denote the order type
1460
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
H
Haojun Liao 已提交
1461
    return pCtx->param[0].i64 == pQueryAttr->order.order;
1462 1463
  }

1464 1465 1466
  // in the reverse table scan, only the following functions need to be executed
  if (IS_REVERSE_SCAN(pRuntimeEnv) ||
      (pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != TSDB_FUNC_STDDEV && functionId != TSDB_FUNC_PERCT)) {
1467 1468
    return false;
  }
1469

1470 1471 1472
  return true;
}

H
Haojun Liao 已提交
1473 1474
void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex) {
  SDataStatis *pStatis = NULL;
H
Haojun Liao 已提交
1475

H
Haojun Liao 已提交
1476 1477 1478 1479
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1480 1481 1482 1483 1484 1485
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1486
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1487 1488

  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1489
  if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
1490
    pCtx->preAggVals.isSet  = true;
H
Haojun Liao 已提交
1491 1492
    pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey;
    pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey;
H
Haojun Liao 已提交
1493
  }
H
Haojun Liao 已提交
1494 1495
}

H
Haojun Liao 已提交
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
// set the output buffer for the selectivity + tag query
static int32_t setCtxTagColumnInfo(SQLFunctionCtx *pCtx, int32_t numOfOutput) {
  if (!isSelectivityWithTagsQuery(pCtx, numOfOutput)) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t num = 0;
  int16_t tagLen = 0;

  SQLFunctionCtx*  p = NULL;
  SQLFunctionCtx** pTagCtx = calloc(numOfOutput, POINTER_BYTES);
  if (pTagCtx == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functionId = pCtx[i].functionId;

    if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
      tagLen += pCtx[i].outputBytes;
      pTagCtx[num++] = &pCtx[i];
    } else if ((aAggs[functionId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
      p = &pCtx[i];
    } else if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG) {
      // tag function may be the group by tag column
      // ts may be the required primary timestamp column
      continue;
    } else {
      // the column may be the normal column, group by normal_column, the functionId is TSDB_FUNC_PRJ
    }
  }
  if (p != NULL) {
    p->tagInfo.pTagCtxList = pTagCtx;
    p->tagInfo.numOfTagCols = num;
    p->tagInfo.tagsLen = tagLen;
  } else {
    tfree(pTagCtx);
  }

  return TSDB_CODE_SUCCESS;
}
1537

H
Haojun Liao 已提交
1538
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1539
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1540
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1541

1542 1543
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1544
    return NULL;
1545 1546
  }

H
Haojun Liao 已提交
1547
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1548 1549 1550 1551
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1552

H
Haojun Liao 已提交
1553
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
1554
    SSqlExpr *pSqlExpr = &pExpr[i].base;
1555
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1556

H
Haojun Liao 已提交
1557
    SColIndex *pIndex = &pSqlExpr->colInfo;
1558

Y
TD-1230  
yihaoDeng 已提交
1559
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1560 1561
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1562
    } else {
1563 1564
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1565

H
Haojun Liao 已提交
1566 1567
    pCtx->inputBytes = pSqlExpr->colBytes;
    pCtx->inputType  = pSqlExpr->colType;
H
Haojun Liao 已提交
1568

1569
    pCtx->ptsOutputBuf = NULL;
1570

H
Haojun Liao 已提交
1571 1572
    pCtx->outputBytes  = pSqlExpr->resBytes;
    pCtx->outputType   = pSqlExpr->resType;
1573

H
Haojun Liao 已提交
1574
    pCtx->order        = pQueryAttr->order.order;
H
Haojun Liao 已提交
1575
    pCtx->functionId   = pSqlExpr->functionId;
H
Haojun Liao 已提交
1576
    pCtx->stableQuery  = pQueryAttr->stableQuery;
H
Haojun Liao 已提交
1577
    pCtx->interBufBytes = pSqlExpr->interBytes;
1578 1579
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1580

H
Haojun Liao 已提交
1581
    pCtx->numOfParams  = pSqlExpr->numOfParams;
1582
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
H
Haojun Liao 已提交
1583 1584 1585
      int16_t type = pSqlExpr->param[j].nType;
      int16_t bytes = pSqlExpr->param[j].nLen;
      if (pSqlExpr->functionId == TSDB_FUNC_STDDEV_DST) {
1586 1587 1588
        continue;
      }

1589
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
1590
        tVariantCreateFromBinary(&pCtx->param[j], pSqlExpr->param[j].pz, bytes, type);
1591
      } else {
H
Haojun Liao 已提交
1592
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlExpr->param[j].i64, bytes, type);
1593 1594
      }
    }
1595

1596 1597
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1598

1599
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1600
      int32_t f = pExpr[0].base.functionId;
1601
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1602

H
Haojun Liao 已提交
1603
      pCtx->param[2].i64 = pQueryAttr->order.order;
1604
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1605
      pCtx->param[3].i64 = functionId;
1606
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1607

H
Haojun Liao 已提交
1608
      pCtx->param[1].i64 = pQueryAttr->order.orderColId;
H
Haojun Liao 已提交
1609
    } else if (functionId == TSDB_FUNC_INTERP) {
H
Haojun Liao 已提交
1610 1611 1612
      pCtx->param[2].i64 = (int8_t)pQueryAttr->fillType;
      if (pQueryAttr->fillVal != NULL) {
        if (isNull((const char *)&pQueryAttr->fillVal[i], pCtx->inputType)) {
H
Haojun Liao 已提交
1613 1614 1615
          pCtx->param[1].nType = TSDB_DATA_TYPE_NULL;
        } else {  // todo refactor, tVariantCreateFromBinary should handle the NULL value
          if (pCtx->inputType != TSDB_DATA_TYPE_BINARY && pCtx->inputType != TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
1616
            tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQueryAttr->fillVal[i], pCtx->inputBytes, pCtx->inputType);
H
Haojun Liao 已提交
1617 1618 1619 1620
          }
        }
      }
    } else if (functionId == TSDB_FUNC_TS_COMP) {
H
Haojun Liao 已提交
1621
      pCtx->param[0].i64 = pQueryAttr->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1622 1623
      pCtx->param[0].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_TWA) {
H
Haojun Liao 已提交
1624
      pCtx->param[1].i64 = pQueryAttr->window.skey;
H
Haojun Liao 已提交
1625
      pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT;
H
Haojun Liao 已提交
1626
      pCtx->param[2].i64 = pQueryAttr->window.ekey;
H
Haojun Liao 已提交
1627 1628 1629
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_ARITHM) {
      pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i];
1630
    }
H
Haojun Liao 已提交
1631
  }
1632

H
Haojun Liao 已提交
1633
  for(int32_t i = 1; i < numOfOutput; ++i) {
sangshuduo's avatar
sangshuduo 已提交
1634
    (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) +
H
Haojun Liao 已提交
1635
        pExpr[i - 1].base.interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
1636
  }
1637

H
Haojun Liao 已提交
1638 1639
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1640
  return pFuncCtx;
H
Haojun Liao 已提交
1641 1642
}

H
Haojun Liao 已提交
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
static void* destroySQLFunctionCtx(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  if (pCtx == NULL) {
    return NULL;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) {
      tVariantDestroy(&pCtx[i].param[j]);
    }

    tVariantDestroy(&pCtx[i].tag);
    tfree(pCtx[i].tagInfo.pTagCtxList);
  }

  tfree(pCtx);
  return NULL;
}

H
Haojun Liao 已提交
1661
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables, SArray* pOperator, void* merger) {
H
Haojun Liao 已提交
1662
  qDebug("QInfo:%"PRIu64" setup runtime env", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1663
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1664 1665

  pRuntimeEnv->prevGroupId = INT32_MIN;
H
Haojun Liao 已提交
1666
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
1667 1668

  pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
H
Haojun Liao 已提交
1669
  pRuntimeEnv->keyBuf  = malloc(pQueryAttr->maxTableColumnWidth + sizeof(int64_t));
H
Haojun Liao 已提交
1670
  pRuntimeEnv->pool    = initResultRowPool(getResultRowSize(pRuntimeEnv));
H
Haojun Liao 已提交
1671 1672 1673
  pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQueryAttr->numOfCols + pQueryAttr->srcRowSize);
  pRuntimeEnv->tagVal  = malloc(pQueryAttr->tagLen);
  pRuntimeEnv->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
1674

H
Haojun Liao 已提交
1675 1676 1677
  // NOTE: pTableCheckInfo need to update the query time range and the lastKey info
  pRuntimeEnv->pTableRetrieveTsMap = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);

H
Haojun Liao 已提交
1678
  pRuntimeEnv->sasArray = calloc(pQueryAttr->numOfOutput, sizeof(SArithmeticSupport));
H
Haojun Liao 已提交
1679

H
Haojun Liao 已提交
1680 1681
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1682 1683 1684
    goto _clean;
  }

H
Haojun Liao 已提交
1685 1686
  if (pQueryAttr->numOfCols) {
    char* start = POINTER_BYTES * pQueryAttr->numOfCols + (char*) pRuntimeEnv->prevRow;
H
Haojun Liao 已提交
1687
    pRuntimeEnv->prevRow[0] = start;
H
Haojun Liao 已提交
1688
    for(int32_t i = 1; i < pQueryAttr->numOfCols; ++i) {
H
Haojun Liao 已提交
1689
      pRuntimeEnv->prevRow[i] = pRuntimeEnv->prevRow[i - 1] + pQueryAttr->tableCols[i-1].bytes;
H
Haojun Liao 已提交
1690
    }
H
Haojun Liao 已提交
1691

H
Haojun Liao 已提交
1692 1693
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1694

H
Haojun Liao 已提交
1695
  qDebug("QInfo:%"PRIu64" init runtime environment completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1696 1697

  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
1698
  // interval (down sampling operation)
H
Haojun Liao 已提交
1699 1700 1701 1702 1703 1704
  int32_t numOfOperator = taosArrayGetSize(pOperator);
  for(int32_t i = 0; i < numOfOperator; ++i) {
    int32_t* op = taosArrayGet(pOperator, i);

    switch (*op) {
      case OP_TagScan: {
H
Haojun Liao 已提交
1705
        pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1706 1707 1708 1709
        break;
      }
      case OP_MultiTableTimeInterval: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1710
            createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1711 1712 1713 1714 1715
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        break;
      }
      case OP_TimeWindow: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1716
            createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1717 1718 1719 1720 1721
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        break;
      }
      case OP_Groupby: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1722
            createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1723 1724 1725 1726 1727
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        break;
      }
      case OP_SessionWindow: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1728
            createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1729 1730 1731 1732 1733
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        break;
      }
      case OP_MultiTableAggregate: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1734
            createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1735 1736 1737 1738 1739
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        break;
      }
      case OP_Aggregate: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1740
            createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1741 1742 1743
        if (pRuntimeEnv->pTableScanner->operatorType != OP_DummyInput) {
          setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
        }
H
Haojun Liao 已提交
1744 1745 1746
        break;
      }

H
Haojun Liao 已提交
1747
      case OP_Arithmetic: {  // TODO refactor to remove arith operator.
H
Haojun Liao 已提交
1748
        SOperatorInfo* prev = pRuntimeEnv->pTableScanner;
H
Haojun Liao 已提交
1749
        if (i == 0) {
H
Haojun Liao 已提交
1750
          pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1751
          if (pRuntimeEnv->pTableScanner != NULL && pRuntimeEnv->pTableScanner->operatorType != OP_DummyInput) {  // TODO refactor
H
Haojun Liao 已提交
1752 1753
            setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
          }
H
Haojun Liao 已提交
1754
        } else {
H
Haojun Liao 已提交
1755
          prev = pRuntimeEnv->proot;
H
Haojun Liao 已提交
1756
          assert(pQueryAttr->pExpr2 != NULL);
H
Haojun Liao 已提交
1757
          pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
H
Haojun Liao 已提交
1758 1759 1760 1761 1762 1763 1764 1765 1766
        }
        break;
      }

      case OP_Limit: {
        pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
        break;
      }

1767 1768 1769 1770 1771 1772
      case OP_Condition: {  // todo refactor
        assert(pQueryAttr->havingNum > 0);
        if (pQueryAttr->stableQuery) {
          pRuntimeEnv->proot = createConditionOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
        } else {
          pRuntimeEnv->proot = createConditionOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1773 1774 1775
        }
        break;
      }
H
Haojun Liao 已提交
1776

H
Haojun Liao 已提交
1777 1778 1779 1780 1781 1782
      case OP_Fill: {
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
        break;
      }

H
Haojun Liao 已提交
1783
      case OP_MultiwaySort: {
H
Haojun Liao 已提交
1784 1785 1786 1787
        bool groupMix = true;
        if(pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) {
          groupMix = false;
        }
H
Haojun Liao 已提交
1788
        pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput,
H
Haojun Liao 已提交
1789
            4096, merger, groupMix); // TODO hack it
H
Haojun Liao 已提交
1790
        break;
H
Haojun Liao 已提交
1791
      }
H
Haojun Liao 已提交
1792

H
Haojun Liao 已提交
1793
      case OP_GlobalAggregate: {
H
Haojun Liao 已提交
1794 1795
        pRuntimeEnv->proot =
            createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
H
Haojun Liao 已提交
1796
                                              pQueryAttr->numOfExpr3, merger);
H
Haojun Liao 已提交
1797 1798 1799 1800
        break;
      }

      case OP_SLimit: {
H
Haojun Liao 已提交
1801 1802
        pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
            pQueryAttr->numOfExpr3, merger);
H
Haojun Liao 已提交
1803
        break;
H
Haojun Liao 已提交
1804
      }
H
Haojun Liao 已提交
1805

H
Haojun Liao 已提交
1806 1807
      default: {
        assert(0);
H
Haojun Liao 已提交
1808
      }
H
Haojun Liao 已提交
1809
    }
H
Haojun Liao 已提交
1810
  }
H
Haojun Liao 已提交
1811

H
Haojun Liao 已提交
1812
  return TSDB_CODE_SUCCESS;
1813

1814
_clean:
1815
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1816 1817 1818 1819
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1820

1821
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1822 1823
}

H
Haojun Liao 已提交
1824
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1825
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1826 1827 1828 1829

  tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
  pRuntimeEnv->pQueryHandle = NULL;

H
Haojun Liao 已提交
1830
  SMemRef* pMemRef = &pQueryAttr->memRef;
1831
  assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
H
Haojun Liao 已提交
1832 1833
}

H
Haojun Liao 已提交
1834 1835
static void destroyTsComp(SQueryRuntimeEnv *pRuntimeEnv, SQueryAttr *pQueryAttr) {
  if (pQueryAttr->tsCompQuery) {
D
dapan1121 已提交
1836 1837 1838 1839 1840 1841 1842 1843 1844
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
    if (f) {
      fclose(f);
      *(FILE **)pColInfoData->pData = NULL;
    }
  }
}

H
Haojun Liao 已提交
1845
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
H
Haojun Liao 已提交
1846
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1847
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1848

H
Haojun Liao 已提交
1849
  qDebug("QInfo:%"PRIu64" teardown runtime env", pQInfo->qId);
1850

1851
  if (pRuntimeEnv->sasArray != NULL) {
H
Haojun Liao 已提交
1852
    for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
1853
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1854
      tfree(pRuntimeEnv->sasArray[i].colList);
1855 1856 1857 1858 1859
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1860
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1861
  doFreeQueryHandle(pRuntimeEnv);
1862

H
Haojun Liao 已提交
1863 1864
  destroyTsComp(pRuntimeEnv, pQueryAttr);

H
Haojun Liao 已提交
1865
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1866

S
TD-1848  
Shengliang Guan 已提交
1867
  tfree(pRuntimeEnv->keyBuf);
1868
  tfree(pRuntimeEnv->prevRow);
1869 1870
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1871 1872
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1873

H
Haojun Liao 已提交
1874 1875 1876
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1877
  destroyOperatorInfo(pRuntimeEnv->proot);
D
dapan1121 已提交
1878 1879 1880 1881 1882

  pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool);
  taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult);
  pRuntimeEnv->prevResult = NULL;

1883 1884
}

1885 1886 1887 1888
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1889
bool isQueryKilled(SQInfo *pQInfo) {
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899
  if (IS_QUERY_KILLED(pQInfo)) {
    return true;
  }

  // query has been executed more than tsShellActivityTimer, and the retrieve has not arrived
  // abort current query execution.
  if (pQInfo->owner != 0 && ((taosGetTimestampSec() - pQInfo->startExecTs) > getMaximumIdleDurationSec()) &&
      (!needBuildResAfterQueryComplete(pQInfo))) {

    assert(pQInfo->startExecTs != 0);
H
Haojun Liao 已提交
1900 1901
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1902 1903 1904 1905 1906 1907
    return true;
  }

  return false;
}

H
Haojun Liao 已提交
1908
void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED;}
H
hjxilinx 已提交
1909

H
Haojun Liao 已提交
1910 1911
//static bool isFixedOutputQuery(SQueryAttr* pQueryAttr) {
//  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
1912 1913 1914 1915
//    return false;
//  }
//
//  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1916
//  if (pQueryAttr->topBotQuery || pQueryAttr->groupbyColumn || pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
1917 1918 1919
//    return true;
//  }
//
H
Haojun Liao 已提交
1920 1921
//  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
//    SSqlExpr *pExpr = &pQueryAttr->pExpr1[i].base;
H
Haojun Liao 已提交
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
//
//    if (pExpr->functionId == TSDB_FUNC_TS || pExpr->functionId == TSDB_FUNC_TS_DUMMY) {
//      continue;
//    }
//
//    if (!IS_MULTIOUTPUT(aAggs[pExpr->functionId].status)) {
//      return true;
//    }
//  }
//
//  return false;
//}
1934

1935
// todo refactor with isLastRowQuery
H
Haojun Liao 已提交
1936 1937 1938
//bool isPointInterpoQuery(SQueryAttr *pQueryAttr) {
//  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
//    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
H
Haojun Liao 已提交
1939 1940 1941 1942 1943 1944 1945
//    if (functionId == TSDB_FUNC_INTERP) {
//      return true;
//    }
//  }
//
//  return false;
//}
1946 1947

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
H
Haojun Liao 已提交
1948 1949 1950
static UNUSED_FUNC bool isSumAvgRateQuery(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
1951 1952 1953
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
1954

1955 1956 1957 1958 1959
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
1960

1961 1962 1963
  return false;
}

H
Haojun Liao 已提交
1964 1965 1966
static bool isFirstLastRowQuery(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionID = pQueryAttr->pExpr1[i].base.functionId;
1967 1968 1969 1970
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
1971

1972 1973 1974
  return false;
}

H
Haojun Liao 已提交
1975 1976 1977 1978
/**
 * The following 4 kinds of query are treated as the tags query
 * tagprj, tid_tag query, count(tbname), 'abc' (user defined constant value column) query
 */
H
Haojun Liao 已提交
1979 1980 1981
bool onlyQueryTags(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pQueryAttr->pExpr1[i];
H
Haojun Liao 已提交
1982 1983

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
1984 1985 1986 1987

    if (functionId != TSDB_FUNC_TAGPRJ &&
        functionId != TSDB_FUNC_TID_TAG &&
        (!(functionId == TSDB_FUNC_COUNT && pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX)) &&
Y
TD-1230  
yihaoDeng 已提交
1988
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
1989 1990 1991
      return false;
    }
  }
1992

H
hjxilinx 已提交
1993 1994 1995
  return true;
}

1996 1997
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
1998 1999 2000
void getAlignQueryTimeWindow(SQueryAttr *pQueryAttr, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
  assert(key >= keyFirst && key <= keyLast && pQueryAttr->interval.sliding <= pQueryAttr->interval.interval);
  win->skey = taosTimeTruncate(key, &pQueryAttr->interval, pQueryAttr->precision);
H
Haojun Liao 已提交
2001 2002

  /*
H
Haojun Liao 已提交
2003
   * if the realSkey > INT64_MAX - pQueryAttr->interval.interval, the query duration between
H
Haojun Liao 已提交
2004 2005
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
H
Haojun Liao 已提交
2006 2007
  if (keyFirst > (INT64_MAX - pQueryAttr->interval.interval)) {
    assert(keyLast - keyFirst < pQueryAttr->interval.interval);
2008
    win->ekey = INT64_MAX;
H
Haojun Liao 已提交
2009 2010
  } else if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
    win->ekey = taosTimeAdd(win->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
2011
  } else {
H
Haojun Liao 已提交
2012
    win->ekey = win->skey + pQueryAttr->interval.interval - 1;
2013 2014 2015 2016 2017 2018
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2019
bool colIdCheck(SQueryAttr *pQueryAttr, uint64_t qId) {
2020
  // load data column information is incorrect
H
Haojun Liao 已提交
2021
  for (int32_t i = 0; i < pQueryAttr->numOfCols - 1; ++i) {
H
Haojun Liao 已提交
2022
    if (pQueryAttr->tableCols[i].colId == pQueryAttr->tableCols[i + 1].colId) {
H
Haojun Liao 已提交
2023
      qError("QInfo:%"PRIu64" invalid data load column for query", qId);
2024 2025 2026
      return false;
    }
  }
2027

2028 2029 2030 2031 2032
  return true;
}

// todo ignore the avg/sum/min/max/count/stddev/top/bottom functions, of which
// the scan order is not matter
H
Haojun Liao 已提交
2033 2034 2035
static bool onlyOneQueryType(SQueryAttr *pQueryAttr, int32_t functId, int32_t functIdDst) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
2036

2037 2038 2039 2040
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2041

2042 2043 2044 2045
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2046

2047 2048 2049
  return true;
}

H
Haojun Liao 已提交
2050
static bool onlyFirstQuery(SQueryAttr *pQueryAttr) { return onlyOneQueryType(pQueryAttr, TSDB_FUNC_FIRST, TSDB_FUNC_FIRST_DST); }
2051

H
Haojun Liao 已提交
2052
static bool onlyLastQuery(SQueryAttr *pQueryAttr) { return onlyOneQueryType(pQueryAttr, TSDB_FUNC_LAST, TSDB_FUNC_LAST_DST); }
2053

H
Haojun Liao 已提交
2054
static int32_t updateBlockLoadStatus(SQueryAttr *pQuery, int32_t status) {
H
Haojun Liao 已提交
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
  bool hasFirstLastFunc = false;
  bool hasOtherFunc = false;

  if (status == BLK_DATA_ALL_NEEDED || status == BLK_DATA_DISCARD) {
    return status;
  }

  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;

    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }

    if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) {
      hasFirstLastFunc = true;
    } else {
      hasOtherFunc = true;
    }
  }

  if (hasFirstLastFunc && status == BLK_DATA_NO_NEEDED) {
    if(!hasOtherFunc) {
      return BLK_DATA_DISCARD;
    } else{
      return BLK_DATA_ALL_NEEDED;
    }
  }

  return status;
}

2088
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2089 2090
  SQueryAttr* pQueryAttr = &pQInfo->query;
  size_t t = taosArrayGetSize(pQueryAttr->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2091
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2092
    SArray* p1 = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2093 2094 2095

    size_t len = taosArrayGetSize(p1);
    for(int32_t j = 0; j < len; ++j) {
2096
      STableKeyInfo* pInfo = taosArrayGet(p1, j);
H
Haojun Liao 已提交
2097

2098 2099 2100 2101
      // update the new lastkey if it is equalled to the value of the old skey
      if (pInfo->lastKey == win->ekey) {
        pInfo->lastKey = win->skey;
      }
H
Haojun Liao 已提交
2102 2103 2104 2105
    }
  }
}

2106
static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bool stableQuery) {
H
Haojun Liao 已提交
2107
  SQueryAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
2108

2109
  // in case of point-interpolation query, use asc order scan
H
Haojun Liao 已提交
2110
  char msg[] = "QInfo:%"PRIu64" scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64
2111
               "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64;
2112

2113 2114
  // todo handle the case the the order irrelevant query type mixed up with order critical query type
  // descending order query for last_row query
H
Haojun Liao 已提交
2115
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
2116 2117
    qDebug("QInfo:%"PRIu64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId,
        pQueryAttr->order.order, TSDB_ORDER_ASC);
2118

H
Haojun Liao 已提交
2119 2120 2121
    pQueryAttr->order.order = TSDB_ORDER_ASC;
    if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2122
    }
2123

2124 2125
    return;
  }
2126

H
Haojun Liao 已提交
2127 2128 2129 2130
  if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) {
    pQueryAttr->order.order = TSDB_ORDER_ASC;
    if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2131
    }
H
Haojun Liao 已提交
2132

H
Haojun Liao 已提交
2133
    doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
H
Haojun Liao 已提交
2134 2135 2136
    return;
  }

H
Haojun Liao 已提交
2137 2138 2139 2140
  if (pQueryAttr->pointInterpQuery && pQueryAttr->interval.interval == 0) {
    if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
      qDebug(msg, pQInfo, "interp", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2141
    }
2142

H
Haojun Liao 已提交
2143
    pQueryAttr->order.order = TSDB_ORDER_ASC;
2144 2145
    return;
  }
2146

H
Haojun Liao 已提交
2147 2148 2149 2150 2151
  if (pQueryAttr->interval.interval == 0) {
    if (onlyFirstQuery(pQueryAttr)) {
      if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
        qDebug(msg, pQInfo, "only-first", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey,
               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2152

H
Haojun Liao 已提交
2153 2154
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2155
      }
2156

H
Haojun Liao 已提交
2157 2158 2159 2160 2161
      pQueryAttr->order.order = TSDB_ORDER_ASC;
    } else if (onlyLastQuery(pQueryAttr)) {
      if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
        qDebug(msg, pQInfo, "only-last", pQueryAttr->order.order, TSDB_ORDER_DESC, pQueryAttr->window.skey,
               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2162

H
Haojun Liao 已提交
2163 2164
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2165
      }
2166

H
Haojun Liao 已提交
2167
      pQueryAttr->order.order = TSDB_ORDER_DESC;
2168
    }
2169

2170
  } else {  // interval query
2171
    if (stableQuery) {
H
Haojun Liao 已提交
2172 2173 2174 2175
      if (onlyFirstQuery(pQueryAttr)) {
        if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
          qDebug(msg, pQInfo, "only-first stable", pQueryAttr->order.order, TSDB_ORDER_ASC,
                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2176

H
Haojun Liao 已提交
2177 2178
          SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
          doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2179
        }
2180

H
Haojun Liao 已提交
2181 2182 2183 2184 2185
        pQueryAttr->order.order = TSDB_ORDER_ASC;
      } else if (onlyLastQuery(pQueryAttr)) {
        if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
          qDebug(msg, pQInfo, "only-last stable", pQueryAttr->order.order, TSDB_ORDER_DESC,
                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2186

H
Haojun Liao 已提交
2187 2188
          SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
          doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2189
        }
2190

H
Haojun Liao 已提交
2191
        pQueryAttr->order.order = TSDB_ORDER_DESC;
2192 2193 2194 2195 2196
      }
    }
  }
}

2197
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
H
Haojun Liao 已提交
2198
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2199
  int32_t MIN_ROWS_PER_PAGE = 4;
2200

H
Haojun Liao 已提交
2201
  *rowsize = (int32_t)(pQueryAttr->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
2202 2203 2204 2205
  int32_t overhead = sizeof(tFilePage);

  // one page contains at least two rows
  *ps = DEFAULT_INTERN_BUF_PAGE_SIZE;
H
Haojun Liao 已提交
2206
  while(((*rowsize) * MIN_ROWS_PER_PAGE) > (*ps) - overhead) {
H
Haojun Liao 已提交
2207
    *ps = ((*ps) << 1u);
2208 2209
  }

H
Haojun Liao 已提交
2210 2211
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2212 2213
}

H
Haojun Liao 已提交
2214
#define IS_PREFILTER_TYPE(_t) ((_t) != TSDB_DATA_TYPE_BINARY && (_t) != TSDB_DATA_TYPE_NCHAR)
2215

H
Haojun Liao 已提交
2216
static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) {
H
Haojun Liao 已提交
2217
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2218

H
Haojun Liao 已提交
2219
  if (pDataStatis == NULL || pQueryAttr->numOfFilterCols == 0) {
2220 2221 2222
    return true;
  }

H
Haojun Liao 已提交
2223 2224
  for (int32_t k = 0; k < pQueryAttr->numOfFilterCols; ++k) {
    SSingleColumnFilterInfo *pFilterInfo = &pQueryAttr->pFilterInfo[k];
2225

H
Haojun Liao 已提交
2226
    int32_t index = -1;
H
Haojun Liao 已提交
2227
    for(int32_t i = 0; i < pQueryAttr->numOfCols; ++i) {
H
Haojun Liao 已提交
2228 2229 2230 2231 2232 2233
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2234
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2235
    if (index == -1) {
H
Haojun Liao 已提交
2236
      return true;
2237
    }
2238

2239
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2240
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2241
      return true;
2242
    }
2243

2244
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2245
    if (pDataStatis[index].numOfNull == numOfRows) {
2246 2247 2248 2249

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2250
        if (pFilterElem->fp == isNullOperator) {
2251 2252 2253 2254
          return true;
        }
      }

2255 2256
      continue;
    }
2257

H
Haojun Liao 已提交
2258 2259 2260
    SDataStatis* pDataBlockst = &pDataStatis[index];

    if (pFilterInfo->info.type == TSDB_DATA_TYPE_FLOAT) {
S
TD-1057  
Shengliang Guan 已提交
2261 2262
      float minval = (float)(*(double *)(&pDataBlockst->min));
      float maxval = (float)(*(double *)(&pDataBlockst->max));
2263

2264
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2265
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2266 2267 2268 2269 2270
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2271
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2272 2273 2274 2275 2276
          return true;
        }
      }
    }
  }
2277

H
Haojun Liao 已提交
2278
  return false;
2279 2280
}

H
Haojun Liao 已提交
2281
static bool overlapWithTimeWindow(SQueryAttr* pQueryAttr, SDataBlockInfo* pBlockInfo) {
H
Haojun Liao 已提交
2282 2283
  STimeWindow w = {0};

H
Haojun Liao 已提交
2284 2285
  TSKEY sk = MIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
  TSKEY ek = MAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
2286

H
Haojun Liao 已提交
2287 2288
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
2289
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2290

H
Haojun Liao 已提交
2291
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2292 2293 2294 2295
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2296
      getNextTimeWindow(pQueryAttr, &w);
H
Haojun Liao 已提交
2297
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2298 2299 2300
        break;
      }

H
Haojun Liao 已提交
2301 2302
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2303 2304 2305 2306
        return true;
      }
    }
  } else {
H
Haojun Liao 已提交
2307
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2308 2309 2310
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2311 2312 2313 2314
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2315
      getNextTimeWindow(pQueryAttr, &w);
H
Haojun Liao 已提交
2316 2317 2318 2319
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2320 2321
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2322 2323 2324 2325 2326 2327 2328 2329
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2330 2331 2332 2333 2334
static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key, bool ascQuery) {
  STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf);

#if defined(_DEBUG_VIEW)
  printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n",
H
Haojun Liao 已提交
2335
         elem.ts, key, elem.tag.i64, pQueryAttr->order.order, pRuntimeEnv->pTsBuf->tsOrder,
H
Haojun Liao 已提交
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
         pRuntimeEnv->pTsBuf->cur.order, pRuntimeEnv->pTsBuf->cur.tsIndex);
#endif

  if (ascQuery) {
    if (key < elem.ts) {
      return TS_JOIN_TS_NOT_EQUALS;
    } else if (key > elem.ts) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN);
    }
  } else {
    if (key > elem.ts) {
      return TS_JOIN_TS_NOT_EQUALS;
    } else if (key < elem.ts) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN);
    }
  }

  return TS_JOIN_TS_EQUAL;
}
2355

H
Haojun Liao 已提交
2356
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
2357
                           SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2358 2359 2360 2361 2362
  int32_t numOfRows = pBlock->info.rows;

  int8_t *p = calloc(numOfRows, sizeof(int8_t));
  bool    all = true;

H
Haojun Liao 已提交
2363
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

    TSKEY* k = (TSKEY*) pColInfoData->pData;
    for (int32_t i = 0; i < numOfRows; ++i) {
      int32_t offset = ascQuery? i:(numOfRows - i - 1);
      int32_t ret = doTSJoinFilter(pRuntimeEnv, k[offset], ascQuery);
      if (ret == TS_JOIN_TAG_NOT_EQUALS) {
        break;
      } else if (ret == TS_JOIN_TS_NOT_EQUALS) {
        all = false;
        continue;
      } else {
        assert(ret == TS_JOIN_TS_EQUAL);
        p[offset] = true;
      }

      if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) {
        break;
      }
    }
H
Haojun Liao 已提交
2384 2385

    // save the cursor status
H
Haojun Liao 已提交
2386
    pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
2387 2388 2389
  } else {
    for (int32_t i = 0; i < numOfRows; ++i) {
      bool qualified = false;
H
Haojun Liao 已提交
2390

H
Haojun Liao 已提交
2391 2392
      for (int32_t k = 0; k < numOfFilterCols; ++k) {
        char* pElem = (char*)pFilterInfo[k].pData + pFilterInfo[k].info.bytes * i;
H
Haojun Liao 已提交
2393

H
Haojun Liao 已提交
2394 2395 2396
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2397

H
Haojun Liao 已提交
2398 2399 2400 2401 2402 2403 2404 2405
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2406
          } else {
H
Haojun Liao 已提交
2407 2408 2409 2410 2411 2412
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2413
          }
H
Haojun Liao 已提交
2414 2415

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2416 2417 2418 2419 2420
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2421
        if (!qualified) {
H
Haojun Liao 已提交
2422 2423 2424 2425
          break;
        }
      }

H
Haojun Liao 已提交
2426
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2427
      if (!qualified) {
H
Haojun Liao 已提交
2428
        all = false;
H
Haojun Liao 已提交
2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
      }
    }
  }

  if (!all) {
    int32_t start = 0;
    int32_t len = 0;
    for (int32_t j = 0; j < numOfRows; ++j) {
      if (p[j] == 1) {
        len++;
      } else {
        if (len > 0) {
          int32_t cstart = j - len;
          for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
            SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i);

            int16_t bytes = pColumnInfoData->info.bytes;
sangshuduo's avatar
sangshuduo 已提交
2446
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2447 2448 2449
          }

          start += len;
2450
          len = 0;
H
Haojun Liao 已提交
2451 2452 2453 2454
        }
      }
    }

2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467
    if (len > 0) {
      int32_t cstart = numOfRows - len;
      for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
        SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i);

        int16_t bytes = pColumnInfoData->info.bytes;
        memmove(pColumnInfoData->pData + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
      }

      start += len;
      len = 0;
    }

H
Haojun Liao 已提交
2468 2469 2470 2471
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

    if (start > 0) {
H
Haojun Liao 已提交
2472
      SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
2473 2474 2475 2476 2477
      if (pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP &&
             pColumnInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
        pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
        pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
      }
H
Haojun Liao 已提交
2478 2479 2480 2481 2482 2483
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2484 2485 2486
static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId);
static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes);

H
Haojun Liao 已提交
2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505
static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) {
  SQLFunctionCtx* pCtx = pTableScanInfo->pCtx;
  uint32_t status = BLK_DATA_NO_NEEDED;

  int32_t numOfOutput = pTableScanInfo->numOfOutput;
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functionId = pCtx[i].functionId;
    int32_t colId = pTableScanInfo->pExpr[i].base.colInfo.colId;

    // group by + first/last should not apply the first/last block filter
    status |= aAggs[functionId].dataReqFunc(&pTableScanInfo->pCtx[i], &pBlock->info.window, colId);
    if ((status & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) {
      return status;
    }
  }

  return status;
}

2506 2507
static void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock) {
  if (numOfFilterCols > 0 && pFilterInfo[0].pData != NULL) {
H
Haojun Liao 已提交
2508 2509 2510 2511
    return;
  }

  // set the initial static data value filter expression
2512
  for (int32_t i = 0; i < numOfFilterCols; ++i) {
H
Haojun Liao 已提交
2513 2514 2515
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j);

2516 2517
      if (pFilterInfo[i].info.colId == pColInfo->info.colId) {
        pFilterInfo[i].pData = pColInfo->pData;
H
Haojun Liao 已提交
2518 2519 2520 2521 2522 2523
        break;
      }
    }
  }
}

H
Haojun Liao 已提交
2524 2525
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2526
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2527
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2528
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2529

H
Haojun Liao 已提交
2530
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2531
  int64_t groupId = pRuntimeEnv->current->groupIndex;
H
Haojun Liao 已提交
2532
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
2533

H
Haojun Liao 已提交
2534
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2535 2536
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2537
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2538
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2539

H
Haojun Liao 已提交
2540
    if (pQueryAttr->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2541
      SExprInfo*   pExprInfo = &pTableScanInfo->pExpr[0];
H
Haojun Liao 已提交
2542
      int16_t      tagId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
2543
      SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagId);
H
Haojun Liao 已提交
2544 2545 2546

      // compare tag first
      tVariant t = {0};
H
Haojun Liao 已提交
2547 2548
      doSetTagValueInParam(pRuntimeEnv->current->pTable, tagId, &t, pColInfo->type, pColInfo->bytes);
      setTimestampListJoinInfo(pRuntimeEnv, &t, pRuntimeEnv->current);
H
Haojun Liao 已提交
2549 2550 2551 2552 2553 2554

      STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf);
      if (!tsBufIsValidElem(&elem) || (tsBufIsValidElem(&elem) && (tVariantCompare(&t, elem.tag) != 0))) {
        (*status) = BLK_DATA_DISCARD;
        return TSDB_CODE_SUCCESS;
      }
H
Haojun Liao 已提交
2555 2556 2557
    }
  }

H
Haojun Liao 已提交
2558 2559
  // Calculate all time windows that are overlapping or contain current data block.
  // If current data block is contained by all possible time window, do not load current data block.
H
Haojun Liao 已提交
2560 2561
  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 ||
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) {
H
Haojun Liao 已提交
2562 2563
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2564

H
Haojun Liao 已提交
2565 2566 2567 2568
  // check if this data block is required to load
  if ((*status) != BLK_DATA_ALL_NEEDED) {
    // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet,
    // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer
H
Haojun Liao 已提交
2569
    if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2570
      SResultRow* pResult = NULL;
H
Haojun Liao 已提交
2571

H
Haojun Liao 已提交
2572 2573
      bool  masterScan = IS_MASTER_SCAN(pRuntimeEnv);
      TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey;
H
Haojun Liao 已提交
2574

H
Haojun Liao 已提交
2575
      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2576 2577 2578 2579
      if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                  pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                  pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
2580
      }
H
Haojun Liao 已提交
2581
    } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
2582 2583
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
H
Haojun Liao 已提交
2584
                               pRuntimeEnv->current->groupIndex);
H
Haojun Liao 已提交
2585
    }
H
Haojun Liao 已提交
2586 2587

    (*status) = doFilterByBlockTimeWindow(pTableScanInfo, pBlock);
H
Haojun Liao 已提交
2588 2589
  }

H
Haojun Liao 已提交
2590
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2591
  *status = updateBlockLoadStatus(pRuntimeEnv->pQueryAttr, *status);
H
Haojun Liao 已提交
2592

2593
  if ((*status) == BLK_DATA_NO_NEEDED || (*status) == BLK_DATA_DISCARD) {
H
Haojun Liao 已提交
2594
    qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2595
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2596 2597 2598 2599
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2600
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2601

H
Haojun Liao 已提交
2602
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2603
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2604
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2605 2606 2607 2608 2609 2610
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

    // load the data block statistics to perform further filter
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2611
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2612

H
Haojun Liao 已提交
2613
    if (pQueryAttr->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2614
      { // set previous window
H
Haojun Liao 已提交
2615
        if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2616 2617 2618 2619 2620
          SResultRow* pResult = NULL;

          bool  masterScan = IS_MASTER_SCAN(pRuntimeEnv);
          TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey;

H
Haojun Liao 已提交
2621
          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2622 2623 2624 2625 2626 2627 2628
          if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                      pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                      pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
            longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
          }
        }
      }
H
Haojun Liao 已提交
2629
      bool load = false;
H
Haojun Liao 已提交
2630
      for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
H
Haojun Liao 已提交
2631
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2632
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2633 2634
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2635
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2636
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2637
            qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2638
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2639 2640 2641 2642 2643 2644 2645 2646
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2647
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2648
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2649
      qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2650
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2651
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2652
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2653 2654 2655 2656
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2657
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2658
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2659 2660
      return terrno;
    }
H
Haojun Liao 已提交
2661

2662
    doSetFilterColumnInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock);
H
Haojun Liao 已提交
2663 2664
    if (pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
      filterRowsInDataBlock(pRuntimeEnv, pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2665
    }
H
Haojun Liao 已提交
2666 2667 2668 2669 2670
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2671
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2672
  int32_t midPos = -1;
H
Haojun Liao 已提交
2673
  int32_t numOfRows;
2674

2675 2676 2677
  if (num <= 0) {
    return -1;
  }
2678

2679
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2680 2681

  TSKEY * keyList = (TSKEY *)pValue;
2682
  int32_t firstPos = 0;
2683
  int32_t lastPos = num - 1;
2684

2685
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2686 2687 2688 2689 2690
    // find the first position which is smaller than the key
    while (1) {
      if (key >= keyList[lastPos]) return lastPos;
      if (key == keyList[firstPos]) return firstPos;
      if (key < keyList[firstPos]) return firstPos - 1;
2691

H
Haojun Liao 已提交
2692 2693
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2694

H
hjxilinx 已提交
2695 2696 2697 2698 2699 2700 2701 2702
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2703

H
hjxilinx 已提交
2704 2705 2706 2707 2708
  } else {
    // find the first position which is bigger than the key
    while (1) {
      if (key <= keyList[firstPos]) return firstPos;
      if (key == keyList[lastPos]) return lastPos;
2709

H
hjxilinx 已提交
2710 2711 2712 2713 2714 2715 2716
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2717

H
Haojun Liao 已提交
2718
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2719
      midPos = (numOfRows >> 1u) + firstPos;
2720

H
hjxilinx 已提交
2721 2722 2723 2724 2725 2726 2727 2728 2729
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2730

H
hjxilinx 已提交
2731 2732 2733
  return midPos;
}

H
Haojun Liao 已提交
2734 2735 2736 2737 2738 2739
/*
 * set tag value in SQLFunctionCtx
 * e.g.,tag information into input buffer
 */
static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes) {
  tVariantDestroy(tag);
2740

H
Haojun Liao 已提交
2741
  char* val = NULL;
H
Haojun Liao 已提交
2742
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2743
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2744 2745
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2746 2747
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2748

H
Haojun Liao 已提交
2749 2750 2751 2752
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2753

H
Haojun Liao 已提交
2754
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2755 2756 2757 2758
    int32_t maxLen = bytes - VARSTR_HEADER_SIZE;
    int32_t len = (varDataLen(val) > maxLen)? maxLen:varDataLen(val);
    tVariantCreateFromBinary(tag, varDataVal(val), len, type);
    //tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
H
Haojun Liao 已提交
2759 2760
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2761
  }
2762 2763
}

2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId) {
  assert(pTagColList != NULL && numOfTags > 0);

  for(int32_t i = 0; i < numOfTags; ++i) {
    if (pTagColList[i].colId == colId) {
      return &pTagColList[i];
    }
  }

  return NULL;
}

H
Haojun Liao 已提交
2776
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2777
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2778

H
Haojun Liao 已提交
2779 2780
  SExprInfo  *pExpr      = pOperatorInfo->pExpr;
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2781 2782

  SExprInfo* pExprInfo = &pExpr[0];
H
Haojun Liao 已提交
2783
  if (pQueryAttr->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQueryAttr->stableQuery) {
H
Haojun Liao 已提交
2784 2785
    assert(pExprInfo->base.numOfParams == 1);

H
Haojun Liao 已提交
2786
    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
2787
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);
H
Haojun Liao 已提交
2788

2789
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2790
    return;
H
Haojun Liao 已提交
2791 2792 2793
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
H
Haojun Liao 已提交
2794
    memset(pRuntimeEnv->tagVal, 0, pQueryAttr->tagLen);
H
Haojun Liao 已提交
2795

H
Haojun Liao 已提交
2796 2797 2798 2799 2800 2801 2802 2803 2804
    for (int32_t idx = 0; idx < numOfOutput; ++idx) {
      SExprInfo* pLocalExprInfo = &pExpr[idx];

      // ts_comp column required the tag value for join filter
      if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) {
        continue;
      }

      // todo use tag column index to optimize performance
H
Haojun Liao 已提交
2805 2806
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resType,
                           pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2807

H
Haojun Liao 已提交
2808 2809
      if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resType) || pLocalExprInfo->base.resType == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2810
      } else {
2811
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2812 2813
      }

H
Haojun Liao 已提交
2814
      offset += pLocalExprInfo->base.resBytes;
H
Haojun Liao 已提交
2815 2816
    }

H
Haojun Liao 已提交
2817
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2818
    if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2819
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2820
    }
H
Haojun Liao 已提交
2821
  }
H
Haojun Liao 已提交
2822

H
Haojun Liao 已提交
2823 2824 2825
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2826 2827
  }
}
2828

2829
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) {
    switch (srcDataType) {
      case TSDB_DATA_TYPE_BINARY:
        printf("%" PRId64 ",%s\t", *(TSKEY *)data, (data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_TINYINT:
      case TSDB_DATA_TYPE_BOOL:
        printf("%" PRId64 ",%d\t", *(TSKEY *)data, *(int8_t *)(data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_SMALLINT:
        printf("%" PRId64 ",%d\t", *(TSKEY *)data, *(int16_t *)(data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_BIGINT:
      case TSDB_DATA_TYPE_TIMESTAMP:
        printf("%" PRId64 ",%" PRId64 "\t", *(TSKEY *)data, *(TSKEY *)(data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_INT:
        printf("%" PRId64 ",%d\t", *(TSKEY *)data, *(int32_t *)(data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_FLOAT:
        printf("%" PRId64 ",%f\t", *(TSKEY *)data, *(float *)(data + TSDB_KEYSIZE + 1));
        break;
      case TSDB_DATA_TYPE_DOUBLE:
        printf("%" PRId64 ",%lf\t", *(TSKEY *)data, *(double *)(data + TSDB_KEYSIZE + 1));
        break;
    }
  } else if (functionId == TSDB_FUNC_AVG) {
    printf("%lf,%d\t", *(double *)data, *(int32_t *)(data + sizeof(double)));
  } else if (functionId == TSDB_FUNC_SPREAD) {
    printf("%lf,%lf\t", *(double *)data, *(double *)(data + sizeof(double)));
  } else if (functionId == TSDB_FUNC_TWA) {
    data += 1;
    printf("%lf,%" PRId64 ",%" PRId64 ",%" PRId64 "\t", *(double *)data, *(int64_t *)(data + 8),
           *(int64_t *)(data + 16), *(int64_t *)(data + 24));
  } else if (functionId == TSDB_FUNC_MIN || functionId == TSDB_FUNC_MAX) {
    switch (srcDataType) {
      case TSDB_DATA_TYPE_TINYINT:
      case TSDB_DATA_TYPE_BOOL:
        printf("%d\t", *(int8_t *)data);
        break;
      case TSDB_DATA_TYPE_SMALLINT:
        printf("%d\t", *(int16_t *)data);
        break;
      case TSDB_DATA_TYPE_BIGINT:
      case TSDB_DATA_TYPE_TIMESTAMP:
        printf("%" PRId64 "\t", *(int64_t *)data);
        break;
      case TSDB_DATA_TYPE_INT:
        printf("%d\t", *(int *)data);
        break;
      case TSDB_DATA_TYPE_FLOAT:
        printf("%f\t", *(float *)data);
        break;
      case TSDB_DATA_TYPE_DOUBLE:
        printf("%f\t", *(float *)data);
        break;
    }
  } else if (functionId == TSDB_FUNC_SUM) {
    if (srcDataType == TSDB_DATA_TYPE_FLOAT || srcDataType == TSDB_DATA_TYPE_DOUBLE) {
      printf("%lf\t", *(float *)data);
    } else {
      printf("%" PRId64 "\t", *(int64_t *)data);
    }
  } else {
    printf("%s\t", data);
  }
}

2898
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
H
Haojun Liao 已提交
2899 2900
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfCols = pQueryAttr->numOfOutput;
2901
  printf("super table query intermediate result, total:%d\n", numOfRows);
2902

2903 2904
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2905

H
Haojun Liao 已提交
2906
      switch (pQueryAttr->pExpr1[i].base.resType) {
2907
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2908 2909
          int32_t type = pQueryAttr->pExpr1[i].base.resType;
          printBinaryData(pQueryAttr->pExpr1[i].base.functionId, pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j,
2910 2911 2912 2913 2914
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2915
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2916 2917
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2918
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2919 2920
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2921
          printf("%f\t", *(float *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2922 2923
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2924
          printf("%lf\t", *(double *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2925 2926 2927 2928 2929 2930 2931
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2932
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2933
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2934
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2935 2936

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2937
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2938 2939 2940
    // all results in current group have been returned to client, try next group
    if ((pGroupResInfo->pRows == NULL) || taosArrayGetSize(pGroupResInfo->pRows) == 0) {
      assert(pGroupResInfo->index == 0);
H
Haojun Liao 已提交
2941
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2942 2943 2944 2945
        return;
      }
    }

H
Haojun Liao 已提交
2946
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2947 2948

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2949
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2950 2951
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2952
        break;
H
Haojun Liao 已提交
2953 2954 2955
      }
    }

H
Haojun Liao 已提交
2956 2957 2958 2959
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2960
    }
H
Haojun Liao 已提交
2961

H
Haojun Liao 已提交
2962 2963
}

H
Haojun Liao 已提交
2964
static void updateTableQueryInfoForReverseScan(SQueryAttr *pQueryAttr, STableQueryInfo *pTableQueryInfo) {
2965 2966 2967
  if (pTableQueryInfo == NULL) {
    return;
  }
2968

2969 2970
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
2971

2972 2973
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
2974

H
Haojun Liao 已提交
2975
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
2976
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
2977 2978
}

H
Haojun Liao 已提交
2979
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
2980
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2981

H
Haojun Liao 已提交
2982
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
2983 2984
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
2985
    SArray *tableKeyGroup = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2986

H
Haojun Liao 已提交
2987 2988 2989
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
2990
      updateTableQueryInfoForReverseScan(pQueryAttr, pCheckInfo);
H
Haojun Liao 已提交
2991

H
Haojun Liao 已提交
2992 2993 2994 2995
      // update the last key in tableKeyInfo list, the tableKeyInfo is used to build the tsdbQueryHandle and decide
      // the start check timestamp of tsdbQueryHandle
      STableKeyInfo *pTableKeyInfo = taosArrayGet(tableKeyGroup, j);
      pTableKeyInfo->lastKey = pCheckInfo->lastKey;
H
Haojun Liao 已提交
2996

H
Haojun Liao 已提交
2997
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
2998
    }
H
Haojun Liao 已提交
2999 3000
  }
}
H
Haojun Liao 已提交
3001

H
Haojun Liao 已提交
3002 3003 3004
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3005 3006 3007
  }
}

H
Haojun Liao 已提交
3008 3009 3010 3011 3012 3013
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3014

H
Haojun Liao 已提交
3015 3016 3017 3018 3019 3020 3021 3022
/*
 * The start of each column SResultRowCellInfo is denote by RowCellInfoOffset.
 * Note that in case of top/bottom query, the whole multiple rows of result is treated as only one row of results.
 * +------------+-----------------result column 1-----------+-----------------result column 2-----------+
 * + SResultRow | SResultRowCellInfo | intermediate buffer1 | SResultRowCellInfo | intermediate buffer 2|
 * +------------+-------------------------------------------+-------------------------------------------+
 *           offset[0]                                  offset[1]
 */
H
Haojun Liao 已提交
3023
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid, int32_t stage) {
H
Haojun Liao 已提交
3024 3025 3026 3027 3028
  SQLFunctionCtx* pCtx           = pInfo->pCtx;
  SSDataBlock* pDataBlock        = pInfo->pRes;
  int32_t* rowCellInfoOffset     = pInfo->rowCellInfoOffset;
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;

H
Haojun Liao 已提交
3029 3030
  int32_t tid = 0;
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
3031

H
Haojun Liao 已提交
3032 3033
  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
    SColumnInfoData* pData = taosArrayGet(pDataBlock->pDataBlock, i);
3034

H
Haojun Liao 已提交
3035 3036 3037 3038 3039 3040 3041
    /*
     * set the output buffer information and intermediate buffer
     * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc.
     */
    SResultRowCellInfo* pCellInfo = getResultCell(pRow, i, rowCellInfoOffset);
    RESET_RESULT_INFO(pCellInfo);

H
Haojun Liao 已提交
3042 3043 3044
    pCtx[i].resultInfo   = pCellInfo;
    pCtx[i].pOutput      = pData->pData;
    pCtx[i].currentStage = stage;
H
Haojun Liao 已提交
3045
    assert(pCtx[i].pOutput != NULL);
3046

H
Haojun Liao 已提交
3047 3048 3049 3050 3051
    // set the timestamp output buffer for top/bottom/diff query
    int32_t functionId = pCtx[i].functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
    }
3052
  }
3053

H
Haojun Liao 已提交
3054
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3055
}
3056

H
Haojun Liao 已提交
3057
void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOfInputRows) {
H
Haojun Liao 已提交
3058
  SSDataBlock* pDataBlock = pBInfo->pRes;
3059

H
Haojun Liao 已提交
3060
  int32_t newSize = pDataBlock->info.rows + numOfInputRows + 5; // extra output buffer
H
Haojun Liao 已提交
3061
  if ((*bufCapacity) < newSize) {
H
Haojun Liao 已提交
3062 3063
    for(int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
H
Haojun Liao 已提交
3064

H
Haojun Liao 已提交
3065 3066 3067
      char* p = realloc(pColInfo->pData, newSize * pColInfo->info.bytes);
      if (p != NULL) {
        pColInfo->pData = p;
3068

H
Haojun Liao 已提交
3069 3070
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
H
Haojun Liao 已提交
3071
        (*bufCapacity) = newSize;
H
Haojun Liao 已提交
3072 3073
      } else {
        // longjmp
3074 3075
      }
    }
H
Haojun Liao 已提交
3076
  }
3077

H
Haojun Liao 已提交
3078 3079 3080
  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
    pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows;
3081

H
Haojun Liao 已提交
3082 3083 3084 3085
    // re-estabilish output buffer pointer.
    int32_t functionId = pBInfo->pCtx[i].functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
      pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[0].pOutput;
B
Bomin Zhang 已提交
3086
    }
H
Haojun Liao 已提交
3087 3088
  }
}
3089

H
Haojun Liao 已提交
3090
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3091 3092 3093 3094
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3095 3096
    }

H
Haojun Liao 已提交
3097
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3098
  }
H
Haojun Liao 已提交
3099
}
3100

H
Haojun Liao 已提交
3101
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3102
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3103
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3104 3105
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3106 3107
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3108 3109
  }
}
3110

H
Haojun Liao 已提交
3111
static void setupEnvForReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
3112
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3113

H
Haojun Liao 已提交
3114 3115 3116 3117
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3118
  }
3119

H
Haojun Liao 已提交
3120
  // reverse order time range
H
Haojun Liao 已提交
3121
  SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
3122 3123

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3124
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3125

H
Haojun Liao 已提交
3126
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3127
  SWITCH_ORDER(pQueryAttr->order.order);
H
Haojun Liao 已提交
3128 3129

  setupQueryRangeForReverseScan(pRuntimeEnv);
3130 3131
}

H
Haojun Liao 已提交
3132
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3133
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3134
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3135 3136

  int32_t numOfOutput = pOperator->numOfOutput;
H
Haojun Liao 已提交
3137
  if (pQueryAttr->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQueryAttr) || pQueryAttr->sw.gap > 0) {
H
Haojun Liao 已提交
3138
    // for each group result, call the finalize function for each column
H
Haojun Liao 已提交
3139
    if (pQueryAttr->groupbyColumn) {
H
Haojun Liao 已提交
3140 3141 3142 3143 3144 3145 3146 3147 3148
      closeAllResultRows(pResultRowInfo);
    }

    for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
      SResultRow *buf = pResultRowInfo->pResult[i];
      if (!isResultRowClosed(pResultRowInfo, i)) {
        continue;
      }

H
Haojun Liao 已提交
3149
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3150 3151 3152 3153 3154 3155 3156 3157 3158

      for (int32_t j = 0; j < numOfOutput; ++j) {
        aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]);
      }

      /*
       * set the number of output results for group by normal columns, the number of output rows usually is 1 except
       * the top and bottom query
       */
H
Haojun Liao 已提交
3159
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3160 3161 3162 3163 3164 3165 3166 3167 3168
    }

  } else {
    for (int32_t j = 0; j < numOfOutput; ++j) {
      aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]);
    }
  }
}

H
Haojun Liao 已提交
3169 3170 3171
static bool hasMainOutput(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
3172

3173 3174 3175 3176
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3177

3178 3179 3180
  return false;
}

H
Haojun Liao 已提交
3181
STableQueryInfo *createTableQueryInfo(SQueryAttr* pQueryAttr, void* pTable, bool groupbyColumn, STimeWindow win, void* buf) {
H
Haojun Liao 已提交
3182
  STableQueryInfo *pTableQueryInfo = buf;
3183

H
hjxilinx 已提交
3184 3185
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3186

3187
  pTableQueryInfo->pTable = pTable;
3188
  pTableQueryInfo->cur.vgroupIndex = -1;
3189

H
Haojun Liao 已提交
3190
  // set more initial size of interval/groupby query
H
Haojun Liao 已提交
3191
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr) || groupbyColumn) {
H
Haojun Liao 已提交
3192
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3193
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3194 3195 3196
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3197
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3198 3199
  }

3200 3201 3202
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3203
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3204 3205 3206
  if (pTableQueryInfo == NULL) {
    return;
  }
3207

H
Haojun Liao 已提交
3208
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3209
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3210 3211
}

H
Haojun Liao 已提交
3212 3213
void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
    int32_t numOfOutput, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3214
  // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group
3215
  tFilePage* bufPage = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId);
H
Haojun Liao 已提交
3216

H
Haojun Liao 已提交
3217
  int16_t offset = 0;
3218
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3219
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3220 3221 3222

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3223
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3224 3225
      continue;
    }
3226

H
Haojun Liao 已提交
3227
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQueryAttr, bufPage, pResult->offset, offset);
H
Haojun Liao 已提交
3228
    offset += pCtx[i].outputBytes;
3229

3230
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3231
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3232
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3233
    }
3234

3235
    if (!pResInfo->initialized) {
3236
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3237 3238 3239 3240
    }
  }
}

3241 3242
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3243
  int64_t uid = 0;
H
Haojun Liao 已提交
3244
  SResultRow* pResultRow =
3245
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3246
  assert (pResultRow != NULL);
3247

3248 3249 3250 3251 3252
  /*
   * not assign result buffer yet, add new result buffer
   * all group belong to one result set, and each group result has different group id so set the id to be one
   */
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
3253
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
3254
    if (ret != TSDB_CODE_SUCCESS) {
3255
      return;
3256 3257 3258
    }
  }

3259 3260 3261 3262 3263
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
}

void setExecutionContext(SQueryRuntimeEnv* pRuntimeEnv, SOptrBasicInfo* pInfo, int32_t numOfOutput, int32_t groupIndex,
                         TSKEY nextKey) {
H
Haojun Liao 已提交
3264
  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3265 3266 3267 3268 3269 3270 3271 3272 3273

  // lastKey needs to be updated
  pTableQueryInfo->lastKey = nextKey;
  if (pRuntimeEnv->prevGroupId != INT32_MIN && pRuntimeEnv->prevGroupId == groupIndex) {
    return;
  }

  doSetTableGroupOutputBuf(pRuntimeEnv, &pInfo->resultRowInfo, pInfo->pCtx, pInfo->rowCellInfoOffset, numOfOutput, groupIndex);

3274 3275
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3276 3277
}

H
Haojun Liao 已提交
3278
void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
3279
    int32_t numOfCols, int32_t* rowCellInfoOffset) {
3280 3281
  // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group
  tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId);
3282

H
Haojun Liao 已提交
3283
  int16_t offset = 0;
3284
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3285
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQueryAttr, page, pResult->offset, offset);
H
Haojun Liao 已提交
3286
    offset += pCtx[i].outputBytes;
3287

3288 3289 3290
    int32_t functionId = pCtx[i].functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
3291 3292
    }

3293 3294 3295 3296
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3297
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3298 3299 3300
  }
}

H
Haojun Liao 已提交
3301
void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable) {
H
Haojun Liao 已提交
3302
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
3303

H
Haojun Liao 已提交
3304
  SSqlExpr* pExpr = &pExprInfo->base;
H
Haojun Liao 已提交
3305
  if (pQueryAttr->stableQuery && (pRuntimeEnv->pTsBuf != NULL) &&
H
Haojun Liao 已提交
3306 3307 3308
      (pExpr->functionId == TSDB_FUNC_TS || pExpr->functionId == TSDB_FUNC_PRJ) &&
      (pExpr->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
    assert(pExpr->numOfParams == 1);
H
Haojun Liao 已提交
3309

H
Haojun Liao 已提交
3310
    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
3311
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);
H
Haojun Liao 已提交
3312 3313 3314 3315 3316 3317

    doSetTagValueInParam(pTable, tagColId, &pCtx->tag, pColInfo->type, pColInfo->bytes);

    int16_t tagType = pCtx[0].tag.nType;
    if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) {
      qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%s", pRuntimeEnv->qinfo,
H
Haojun Liao 已提交
3318
             pExprInfo->base.param[0].i64, pCtx[0].tag.pz);
H
Haojun Liao 已提交
3319 3320
    } else {
      qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pRuntimeEnv->qinfo,
H
Haojun Liao 已提交
3321
             pExprInfo->base.param[0].i64, pCtx[0].tag.i64);
H
Haojun Liao 已提交
3322 3323 3324 3325 3326
    }
  }
}

int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo) {
H
Haojun Liao 已提交
3327
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3328

H
Haojun Liao 已提交
3329 3330 3331 3332 3333 3334
  assert(pRuntimeEnv->pTsBuf != NULL);

  // both the master and supplement scan needs to set the correct ts comp start position
  if (pTableQueryInfo->cur.vgroupIndex == -1) {
    tVariantAssign(&pTableQueryInfo->tag, pTag);

H
Haojun Liao 已提交
3335
    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQueryAttr->vgId, &pTableQueryInfo->tag);
H
Haojun Liao 已提交
3336 3337 3338 3339

    // failed to find data with the specified tag value and vnodeId
    if (!tsBufIsValidElem(&elem)) {
      if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3340
        qError("QInfo:%"PRIu64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3341
      } else {
H
Haojun Liao 已提交
3342
        qError("QInfo:%"PRIu64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3343 3344 3345 3346 3347 3348 3349 3350
      }

      return -1;
    }

    // Keep the cursor info of current table
    pTableQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3351
      qDebug("QInfo:%"PRIu64" find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3352
    } else {
H
Haojun Liao 已提交
3353
      qDebug("QInfo:%"PRIu64" find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3354 3355 3356 3357 3358
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3359
      qDebug("QInfo:%"PRIu64" find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3360
    } else {
H
Haojun Liao 已提交
3361
      qDebug("QInfo:%"PRIu64" find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3362
    }
H
Haojun Liao 已提交
3363 3364
  }

H
Haojun Liao 已提交
3365 3366 3367
  return 0;
}

H
Haojun Liao 已提交
3368
void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExprInfo) {
H
Haojun Liao 已提交
3369
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3370

H
Haojun Liao 已提交
3371
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3372
  for(int32_t i = 0; i < numOfExprs; ++i) {
H
Haojun Liao 已提交
3373
    SExprInfo* pExprInfo1 = &(pExprInfo[i]);
H
Haojun Liao 已提交
3374
    if (pExprInfo1->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3375 3376 3377
      continue;
    }

H
Haojun Liao 已提交
3378
    SSqlExpr* pExpr = &pExprInfo1->base;
H
Haojun Liao 已提交
3379 3380

    pCtx[i].param[0].arr = NULL;
H
Haojun Liao 已提交
3381
    pCtx[i].param[0].nType = TSDB_DATA_TYPE_INT;  // avoid freeing the memory by setting the type to be int
H
Haojun Liao 已提交
3382 3383

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3384 3385 3386
    int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult);
    for (int32_t j = 0; j < numOfGroup; ++j) {
      SInterResult* p = taosArrayGet(pRuntimeEnv->prevResult, j);
H
Haojun Liao 已提交
3387
      if (pQueryAttr->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQueryAttr->tagLen) == 0) {
H
Haojun Liao 已提交
3388 3389
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3390
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
H
Haojun Liao 已提交
3391
          if (pres->colId == pExpr->colInfo.colId) {
H
Haojun Liao 已提交
3392 3393 3394 3395 3396 3397 3398 3399 3400
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3401

H
Haojun Liao 已提交
3402
void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes) {
H
Haojun Liao 已提交
3403
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3404

H
Haojun Liao 已提交
3405
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SSqlExpr* pExpr1 = &pExpr[i].base;
    if (pExpr1->functionId != TSDB_FUNC_STDDEV_DST) {
      continue;
    }

    pCtx[i].param[0].arr = NULL;
    pCtx[i].param[0].nType = TSDB_DATA_TYPE_INT;  // avoid freeing the memory by setting the type to be int

    // TODO use hash to speedup this loop
    int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult);
    for (int32_t j = 0; j < numOfGroup; ++j) {
      SInterResult* p = taosArrayGet(pRuntimeEnv->prevResult, j);
      if (bytes == 0 || memcmp(p->tags, val, bytes) == 0) {
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pExpr1->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }
}
D
fix bug  
dapan1121 已提交
3432

3433 3434 3435
/*
 * There are two cases to handle:
 *
H
Haojun Liao 已提交
3436 3437
 * 1. Query range is not set yet (queryRangeSet = 0). we need to set the query range info, including pQueryAttr->lastKey,
 *    pQueryAttr->window.skey, and pQueryAttr->eKey.
3438 3439 3440 3441
 * 2. Query range is set and query is in progress. There may be another result with the same query ranges to be
 *    merged during merge stage. In this case, we need the pTableQueryInfo->lastResRows to decide if there
 *    is a previous result generated or not.
 */
H
Haojun Liao 已提交
3442
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3443
  SQueryAttr           *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3444
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
3445
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3446

H
Haojun Liao 已提交
3447 3448 3449
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3450

H
Haojun Liao 已提交
3451
  pTableQueryInfo->win.skey = key;
H
Haojun Liao 已提交
3452
  STimeWindow win = {.skey = key, .ekey = pQueryAttr->window.ekey};
3453

H
Haojun Liao 已提交
3454 3455 3456 3457 3458 3459
  /**
   * In handling the both ascending and descending order super table query, we need to find the first qualified
   * timestamp of this table, and then set the first qualified start timestamp.
   * In ascending query, the key is the first qualified timestamp. However, in the descending order query, additional
   * operations involve.
   */
H
Haojun Liao 已提交
3460
  STimeWindow w = TSWINDOW_INITIALIZER;
3461

H
Haojun Liao 已提交
3462 3463
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
H
Haojun Liao 已提交
3464
  getAlignQueryTimeWindow(pQueryAttr, win.skey, sk, ek, &w);
3465

H
Haojun Liao 已提交
3466
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3467 3468
    if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
      assert(win.ekey == pQueryAttr->window.ekey);
3469
    }
H
Haojun Liao 已提交
3470

H
Haojun Liao 已提交
3471
    pWindowResInfo->prevSKey = w.skey;
3472
  }
H
Haojun Liao 已提交
3473 3474

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3475 3476 3477
}

/**
H
Haojun Liao 已提交
3478
 * copyToOutputBuf support copy data in ascending/descending order
3479 3480 3481 3482 3483 3484 3485
 * For interval query of both super table and table, copy the data in ascending order, since the output results are
 * ordered in SWindowResutl already. While handling the group by query for both table and super table,
 * all group result are completed already.
 *
 * @param pQInfo
 * @param result
 */
H
Haojun Liao 已提交
3486

H
Haojun Liao 已提交
3487
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3488
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3489 3490

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3491
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3492 3493 3494 3495

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3496
  qDebug("QInfo:%"PRIu64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516
  if (orderType == TSDB_ORDER_ASC) {
    start = pGroupResInfo->index;
    step = 1;
  } else {  // desc order copy all data
    start = numOfRows - pGroupResInfo->index - 1;
    step = -1;
  }

  for (int32_t i = start; (i < numOfRows) && (i >= 0); i += step) {
    SResultRow* pRow = taosArrayGetP(pGroupResInfo->pRows, i);
    if (pRow->numOfRows == 0) {
      pGroupResInfo->index += 1;
      continue;
    }

    int32_t numOfRowsToCopy = pRow->numOfRows;

    pGroupResInfo->index += 1;

    tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pRow->pageId);
H
Haojun Liao 已提交
3517 3518

    int16_t offset = 0;
H
Haojun Liao 已提交
3519 3520 3521 3522 3523
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, j);
      int32_t bytes = pColInfoData->info.bytes;

      char *out = pColInfoData->pData + numOfResult * bytes;
H
Haojun Liao 已提交
3524
      char *in  = getPosInResultPage(pQueryAttr, page, pRow->offset, offset);
H
Haojun Liao 已提交
3525
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3526 3527

      offset += bytes;
H
Haojun Liao 已提交
3528 3529 3530
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3531
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3532 3533 3534 3535
      break;
    }
  }

H
Haojun Liao 已提交
3536
  qDebug("QInfo:%"PRIu64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3537 3538 3539 3540 3541 3542
  pBlock->info.rows = numOfResult;
  return 0;
}

static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock) {
  assert(pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup);
H
Haojun Liao 已提交
3543

H
Haojun Liao 已提交
3544
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3545
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3546 3547 3548
    return;
  }

H
Haojun Liao 已提交
3549 3550
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t orderType = (pQueryAttr->pGroupbyExpr != NULL) ? pQueryAttr->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3551
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3552

H
Haojun Liao 已提交
3553
  // refactor : extract method
H
Haojun Liao 已提交
3554 3555
  SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0);

H
Haojun Liao 已提交
3556 3557 3558
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3559
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3560
  }
3561 3562
}

H
Haojun Liao 已提交
3563 3564 3565
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput,
                                        SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
3566

3567
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3568
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3569 3570
    return;
  }
3571

3572 3573
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3574

3575 3576
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3577 3578
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3579
      }
H
Haojun Liao 已提交
3580

H
Haojun Liao 已提交
3581
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3582
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3583 3584 3585 3586 3587
    }
  }
}

static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) {
H
Haojun Liao 已提交
3588
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3589
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3590

H
Haojun Liao 已提交
3591
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3592

H
Haojun Liao 已提交
3593 3594
  if (pQueryAttr->pExpr2 == NULL) {
    for (int32_t col = 0; col < pQueryAttr->numOfOutput; ++col) {
H
Haojun Liao 已提交
3595 3596 3597
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * pRes->info.rows);
      data += pColRes->info.bytes * pRes->info.rows;
H
Haojun Liao 已提交
3598 3599
    }
  } else {
H
Haojun Liao 已提交
3600
    for (int32_t col = 0; col < pQueryAttr->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3601 3602 3603
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3604
    }
3605
  }
3606

H
Haojun Liao 已提交
3607
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3608 3609
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3610

3611
  int32_t total = 0;
H
Haojun Liao 已提交
3612
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3613

3614
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3615
    STableIdInfo* pDst = (STableIdInfo*)data;
3616 3617 3618 3619
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3620
    data += sizeof(STableIdInfo);
3621 3622
    total++;

H
Haojun Liao 已提交
3623
    qDebug("QInfo:%"PRIu64" set subscribe info, tid:%d, uid:%"PRIu64", skey:%"PRId64, pQInfo->qId, item->tid, item->uid, item->key);
H
Haojun Liao 已提交
3624
    item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, item);
weixin_48148422's avatar
weixin_48148422 已提交
3625 3626
  }

H
Haojun Liao 已提交
3627
  qDebug("QInfo:%"PRIu64" set %d subscribe info", pQInfo->qId, total);
H
Haojun Liao 已提交
3628
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3629 3630
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3631
  }
3632 3633
}

H
Haojun Liao 已提交
3634
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3635 3636 3637 3638 3639 3640
  void** p = calloc(pFillInfo->numOfCols, POINTER_BYTES);
  for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
    SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i);
    p[i] = pColInfoData->pData;
  }

H
Haojun Liao 已提交
3641
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3642
  tfree(p);
H
Haojun Liao 已提交
3643 3644
  return pOutput->info.rows;
}
3645

H
Haojun Liao 已提交
3646
void queryCostStatis(SQInfo *pQInfo) {
3647
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3648
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3649

H
Haojun Liao 已提交
3650
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3651
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3652 3653
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3654 3655 3656
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3657
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3658 3659 3660 3661 3662 3663 3664
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3665

H
Haojun Liao 已提交
3666
  qDebug("QInfo:%"PRIu64" :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, "
H
Haojun Liao 已提交
3667
         "load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64,
H
Haojun Liao 已提交
3668
         pQInfo->qId, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
H
Haojun Liao 已提交
3669
         pSummary->loadBlocks, pSummary->totalRows, pSummary->totalCheckedRows);
3670

H
Haojun Liao 已提交
3671
  qDebug("QInfo:%"PRIu64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0,
H
Haojun Liao 已提交
3672
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3673 3674
}

3675
//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
H
Haojun Liao 已提交
3676
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3677
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3678
//
H
Haojun Liao 已提交
3679
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3680
//
H
Haojun Liao 已提交
3681 3682 3683
//  if (pQueryAttr->limit.offset == pBlockInfo->rows) {  // current block will ignore completed
//    pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQueryAttr) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step;
//    pQueryAttr->limit.offset = 0;
3684 3685 3686
//    return;
//  }
//
H
Haojun Liao 已提交
3687 3688
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//    pQueryAttr->pos = (int32_t)pQueryAttr->limit.offset;
3689
//  } else {
H
Haojun Liao 已提交
3690
//    pQueryAttr->pos = pBlockInfo->rows - (int32_t)pQueryAttr->limit.offset - 1;
3691 3692
//  }
//
H
Haojun Liao 已提交
3693
//  assert(pQueryAttr->pos >= 0 && pQueryAttr->pos <= pBlockInfo->rows - 1);
3694 3695 3696 3697
//
//  SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//  SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
H
Haojun Liao 已提交
3698
//  // update the pQueryAttr->limit.offset value, and pQueryAttr->pos value
3699 3700 3701
//  TSKEY *keys = (TSKEY *) pColInfoData->pData;
//
//  // update the offset value
H
Haojun Liao 已提交
3702 3703
//  pTableQueryInfo->lastKey = keys[pQueryAttr->pos];
//  pQueryAttr->limit.offset = 0;
3704 3705 3706
//
//  int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//
H
Haojun Liao 已提交
3707
//  qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3708
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQueryAttr->current->lastKey);
3709
//}
H
Haojun Liao 已提交
3710

3711
//void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
H
Haojun Liao 已提交
3712
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3713
//
H
Haojun Liao 已提交
3714
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0) {
3715 3716 3717
//    return;
//  }
//
H
Haojun Liao 已提交
3718 3719
//  pQueryAttr->pos = 0;
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3720
//
H
Haojun Liao 已提交
3721
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3722 3723 3724 3725
//  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pQueryHandle)) {
H
Haojun Liao 已提交
3726
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3727 3728 3729 3730 3731
//      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//    }
//
//    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3732 3733 3734
//    if (pQueryAttr->limit.offset > blockInfo.rows) {
//      pQueryAttr->limit.offset -= blockInfo.rows;
//      pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? blockInfo.window.ekey : blockInfo.window.skey;
3735 3736
//      pTableQueryInfo->lastKey += step;
//
H
Haojun Liao 已提交
3737
//      qDebug("QInfo:%"PRIu64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
H
Haojun Liao 已提交
3738
//             pQueryAttr->limit.offset);
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
//    } else {  // find the appropriated start position in current block
//      updateOffsetVal(pRuntimeEnv, &blockInfo);
//      break;
//    }
//  }
//
//  if (terrno != TSDB_CODE_SUCCESS) {
//    longjmp(pRuntimeEnv->env, terrno);
//  }
//}
H
Haojun Liao 已提交
3749

3750
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
H
Haojun Liao 已提交
3751
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3752 3753
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
H
Haojun Liao 已提交
3754
//  assert(pQueryAttr->limit.offset == 0);
3755
//  STimeWindow tw = *win;
H
Haojun Liao 已提交
3756
//  getNextTimeWindow(pQueryAttr, &tw);
3757
//
H
Haojun Liao 已提交
3758 3759
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
3760 3761 3762 3763 3764 3765 3766 3767
//
//    // load the data block and check data remaining in current data block
//    // TODO optimize performance
//    SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//    SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//    tw = *win;
//    int32_t startPos =
H
Haojun Liao 已提交
3768
//        getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
3769 3770 3771
//    assert(startPos >= 0);
//
//    // set the abort info
H
Haojun Liao 已提交
3772
//    pQueryAttr->pos = startPos;
3773 3774 3775
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
H
Haojun Liao 已提交
3776
//    pQueryAttr->window.skey = pTableQueryInfo->win.skey;
3777 3778 3779 3780 3781 3782 3783 3784
//    TSKEY key = pTableQueryInfo->win.skey;
//
//    pWindowResInfo->prevSKey = tw.skey;
//    int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
//
//    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//    pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
//
H
Haojun Liao 已提交
3785 3786
//    qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
H
Haojun Liao 已提交
3787
//           pQueryAttr->current->lastKey);
3788 3789 3790
//
//    return key;
//  } else {  // do nothing
H
Haojun Liao 已提交
3791
//    pQueryAttr->window.skey      = tw.skey;
3792 3793 3794 3795 3796 3797 3798 3799 3800 3801
//    pWindowResInfo->prevSKey = tw.skey;
//    pTableQueryInfo->lastKey = tw.skey;
//
//    return tw.skey;
//  }
//
//  return true;
//}

//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
H
Haojun Liao 已提交
3802 3803
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3804
//    assert(*start <= pRuntimeEnv->current->lastKey);
3805
//  } else {
H
Haojun Liao 已提交
3806
//    assert(*start >= pRuntimeEnv->current->lastKey);
3807 3808 3809
//  }
//
//  // if queried with value filter, do NOT forward query start position
H
Haojun Liao 已提交
3810
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
3811 3812 3813 3814
//    return true;
//  }
//
//  /*
H
Haojun Liao 已提交
3815 3816 3817
//   * 1. for interval without interpolation query we forward pQueryAttr->interval.interval at a time for
//   *    pQueryAttr->limit.offset times. Since hole exists, pQueryAttr->interval.interval*pQueryAttr->limit.offset value is
//   *    not valid. otherwise, we only forward pQueryAttr->limit.offset number of points
3818 3819 3820 3821
//   */
//  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
//
//  STimeWindow w = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3822
//  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
3823 3824
//
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
3825
//  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3826 3827 3828 3829 3830
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
//    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3831
//    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
3832
//      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3833
//        getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey, &w);
3834 3835 3836
//        pWindowResInfo->prevSKey = w.skey;
//      }
//    } else {
H
Haojun Liao 已提交
3837
//      getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w);
3838 3839 3840 3841
//      pWindowResInfo->prevSKey = w.skey;
//    }
//
//    // the first time window
H
Haojun Liao 已提交
3842
//    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
3843
//
H
Haojun Liao 已提交
3844
//    while (pQueryAttr->limit.offset > 0) {
3845 3846 3847
//      STimeWindow tw = win;
//
//      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
3848
//        pQueryAttr->limit.offset -= 1;
3849 3850 3851 3852 3853 3854 3855 3856 3857
//        pWindowResInfo->prevSKey = win.skey;
//
//        // current time window is aligned with blockInfo.window.ekey
//        // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL;
//        if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) {
//          pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
//        }
//      }
//
H
Haojun Liao 已提交
3858
//      if (pQueryAttr->limit.offset == 0) {
3859 3860 3861 3862 3863
//        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//        return true;
//      }
//
//      // current window does not ended in current data block, try next data block
H
Haojun Liao 已提交
3864
//      getNextTimeWindow(pQueryAttr, &tw);
3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878
//
//      /*
//       * If the next time window still starts from current data block,
//       * load the primary timestamp column first, and then find the start position for the next queried time window.
//       * Note that only the primary timestamp column is required.
//       * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required
//       * time window resides in current data block.
//       */
//      if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) {
//
//        SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//        SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//        if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
3879
//          pQueryAttr->limit.offset -= 1;
3880 3881
//        }
//
H
Haojun Liao 已提交
3882
//        if (pQueryAttr->limit.offset == 0) {
3883 3884 3885 3886 3887
//          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//          return true;
//        } else {
//          tw = win;
//          int32_t startPos =
H
Haojun Liao 已提交
3888
//              getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
3889 3890 3891
//          assert(startPos >= 0);
//
//          // set the abort info
H
Haojun Liao 已提交
3892
//          pQueryAttr->pos = startPos;
3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909
//          pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos];
//          pWindowResInfo->prevSKey = tw.skey;
//          win = tw;
//        }
//      } else {
//        break;  // offset is not 0, and next time window begins or ends in the next block.
//      }
//    }
//  }
//
//  // check for error
//  if (terrno != TSDB_CODE_SUCCESS) {
//    longjmp(pRuntimeEnv->env, terrno);
//  }
//
//  return true;
//}
3910

H
Haojun Liao 已提交
3911 3912
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

H
Haojun Liao 已提交
3913 3914
static int32_t setupQueryHandle(void* tsdb, SQueryRuntimeEnv* pRuntimeEnv, int64_t qId, bool isSTableQuery) {
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3915

H
Haojun Liao 已提交
3916
  // TODO set the tags scan handle
H
Haojun Liao 已提交
3917
  if (onlyQueryTags(pQueryAttr)) {
B
Bomin Zhang 已提交
3918
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3919 3920
  }

H
Haojun Liao 已提交
3921 3922
  STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
  if (pQueryAttr->tsCompQuery || pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
3923 3924
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3925

B
Bomin Zhang 已提交
3926
  if (!isSTableQuery
H
Haojun Liao 已提交
3927
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3928
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3929 3930 3931
    && (!QUERY_IS_INTERVAL_QUERY(pQueryAttr))
    && (!pQueryAttr->groupbyColumn)
    && (!pQueryAttr->simpleAgg)
B
Bomin Zhang 已提交
3932
  ) {
H
Haojun Liao 已提交
3933
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3934 3935
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3936
  }
B
Bomin Zhang 已提交
3937

B
Bomin Zhang 已提交
3938
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3939
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
3940
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3941

H
Haojun Liao 已提交
3942
    // update the query time window
H
Haojun Liao 已提交
3943 3944
    pQueryAttr->window = cond.twindow;
    if (pQueryAttr->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3945
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3946
    } else {
H
Haojun Liao 已提交
3947
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3948
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3949
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3950

H
Haojun Liao 已提交
3951 3952 3953
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3954

H
Haojun Liao 已提交
3955
          pCheckInfo->win = pQueryAttr->window;
H
Haojun Liao 已提交
3956 3957
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
3958 3959
      }
    }
H
Haojun Liao 已提交
3960
  } else if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
3961
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3962
  } else {
H
Haojun Liao 已提交
3963
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3964
  }
3965

B
Bomin Zhang 已提交
3966
  return terrno;
B
Bomin Zhang 已提交
3967 3968
}

H
Haojun Liao 已提交
3969
static SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, int64_t* fillVal) {
3970
  int32_t offset = 0;
3971

H
Haojun Liao 已提交
3972
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
3973 3974 3975 3976
  if (pFillCol == NULL) {
    return NULL;
  }

H
Haojun Liao 已提交
3977 3978
  for(int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo   = &pExpr[i];
3979

H
Haojun Liao 已提交
3980
    pFillCol[i].col.bytes  = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
3981
    pFillCol[i].col.type   = (int8_t)pExprInfo->base.resType;
3982
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
3983
    pFillCol[i].col.colId  = pExprInfo->base.resColId;
H
Haojun Liao 已提交
3984
    pFillCol[i].tagIndex   = -2;
H
Haojun Liao 已提交
3985
    pFillCol[i].flag       = pExprInfo->base.colInfo.flag;    // always be the normal column for table query
3986
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
3987
    pFillCol[i].fillVal.i  = fillVal[i];
3988

H
Haojun Liao 已提交
3989
    offset += pExprInfo->base.resBytes;
3990
  }
3991

3992 3993 3994
  return pFillCol;
}

H
Haojun Liao 已提交
3995
int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, SArray* prevResult, void* tsdb, void* sourceOptr, int32_t tbScanner,
H
Haojun Liao 已提交
3996
                    SArray* pOperator, void* param) {
3997 3998
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

H
Haojun Liao 已提交
3999
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
4000
  pQueryAttr->tsdb = tsdb;
H
Haojun Liao 已提交
4001

4002 4003
  pRuntimeEnv->prevResult = prevResult;

H
Haojun Liao 已提交
4004
  if (tsdb != NULL) {
H
Haojun Liao 已提交
4005
    int32_t code = setupQueryHandle(tsdb, pRuntimeEnv, pQInfo->qId, pQueryAttr->stableQuery);
H
Haojun Liao 已提交
4006 4007 4008
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
B
Bomin Zhang 已提交
4009
  }
4010

H
Haojun Liao 已提交
4011
  pQueryAttr->interBufSize = getOutputInterResultBufSize(pQueryAttr);
H
Haojun Liao 已提交
4012

H
Haojun Liao 已提交
4013
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (pQueryAttr->stableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
4014

H
Haojun Liao 已提交
4015
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
4016
  pRuntimeEnv->pTsBuf = pTsBuf;
4017
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4018
  setResultBufSize(pQueryAttr, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4019

H
Haojun Liao 已提交
4020 4021 4022 4023 4024 4025 4026 4027 4028 4029
  switch(tbScanner) {
    case OP_TableBlockInfoScan: {
      pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
      break;
    }
    case OP_TableSeqScan: {
      pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
      break;
    }
    case OP_DataBlocksOptScan: {
H
Haojun Liao 已提交
4030
      pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), 1);
H
Haojun Liao 已提交
4031 4032 4033
      break;
    }
    case OP_TableScan: {
H
Haojun Liao 已提交
4034
      pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr));
H
Haojun Liao 已提交
4035 4036
      break;
    }
H
Haojun Liao 已提交
4037
    default: { // do nothing
H
Haojun Liao 已提交
4038 4039 4040
      break;
    }
  }
H
Haojun Liao 已提交
4041 4042 4043 4044 4045 4046

  if (sourceOptr != NULL) {
    assert(pRuntimeEnv->pTableScanner == NULL);
    pRuntimeEnv->pTableScanner = sourceOptr;
  }

H
Haojun Liao 已提交
4047
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4048
    int16_t order = (pQueryAttr->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
H
Haojun Liao 已提交
4049
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4050 4051
  }

4052
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
4053
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQueryAttr->intermediateResultRowSize);
4054

H
Haojun Liao 已提交
4055
  int32_t TENMB = 1024*1024*10;
H
Haojun Liao 已提交
4056
  int32_t code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo->qId);
H
Haojun Liao 已提交
4057 4058
  if (code != TSDB_CODE_SUCCESS) {
    return code;
4059 4060
  }

H
Haojun Liao 已提交
4061
  // create runtime environment
H
Haojun Liao 已提交
4062
  int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4063
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
4064

H
Haojun Liao 已提交
4065
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQueryAttr->tableGroupInfo.numOfTables, pOperator, param);
H
Haojun Liao 已提交
4066 4067 4068 4069
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4070
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4071
  return TSDB_CODE_SUCCESS;
4072 4073
}

H
Haojun Liao 已提交
4074 4075
static void doTableQueryInfoTimeWindowCheck(SQueryAttr* pQueryAttr, STableQueryInfo* pTableQueryInfo) {
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
4076 4077 4078
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey >= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4079
        (pTableQueryInfo->win.skey >= pQueryAttr->window.skey && pTableQueryInfo->win.ekey <= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4080 4081 4082 4083
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey <= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4084
        (pTableQueryInfo->win.skey <= pQueryAttr->window.skey && pTableQueryInfo->win.ekey >= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4085 4086 4087
  }
}

H
Haojun Liao 已提交
4088
STsdbQueryCond createTsdbQueryCond(SQueryAttr* pQueryAttr, STimeWindow* win) {
4089
  STsdbQueryCond cond = {
H
Haojun Liao 已提交
4090
      .colList   = pQueryAttr->tableCols,
H
Haojun Liao 已提交
4091 4092
      .order     = pQueryAttr->order.order,
      .numOfCols = pQueryAttr->numOfCols,
H
Haojun Liao 已提交
4093
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4094
      .loadExternalRows = false,
4095 4096
  };

H
Haojun Liao 已提交
4097
  TIME_WINDOW_COPY(cond.twindow, *win);
4098 4099 4100
  return cond;
}

H
Haojun Liao 已提交
4101
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
4102
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
4103
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
4104 4105 4106

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
4107
  tidInfo.key = pTableQueryInfo->lastKey;
4108 4109 4110 4111

  return tidInfo;
}

H
Haojun Liao 已提交
4112 4113 4114 4115
static void updateTableIdInfo(STableQueryInfo* pTableQueryInfo, SSDataBlock* pBlock, SHashObj* pTableIdInfo, int32_t order) {
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);
  pTableQueryInfo->lastKey = ((order == TSDB_ORDER_ASC)? pBlock->info.window.ekey:pBlock->info.window.skey) + step;

H
Haojun Liao 已提交
4116 4117
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4118 4119 4120 4121 4122 4123 4124 4125
  if (idinfo != NULL) {
    assert(idinfo->tid == tidInfo.tid && idinfo->uid == tidInfo.uid);
    idinfo->key = tidInfo.key;
  } else {
    taosHashPut(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo));
  }
}

H
Haojun Liao 已提交
4126 4127 4128 4129
static void doCloseAllTimeWindow(SQueryRuntimeEnv* pRuntimeEnv) {
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  for (int32_t i = 0; i < numOfGroup; ++i) {
    SArray* group = GET_TABLEGROUP(pRuntimeEnv, i);
4130

H
Haojun Liao 已提交
4131 4132 4133 4134
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4135 4136
    }
  }
4137 4138
}

H
Haojun Liao 已提交
4139
static SSDataBlock* doTableScanImpl(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4140 4141 4142
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4143 4144
  SSDataBlock*      pBlock = &pTableScanInfo->block;
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4145 4146
  SQueryAttr*       pQueryAttr = pRuntimeEnv->pQueryAttr;
  STableGroupInfo  *pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4147

H
Haojun Liao 已提交
4148 4149
  *newgroup = false;

H
Haojun Liao 已提交
4150
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4151 4152 4153
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4154

4155
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4156
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4157

4158
    // todo opt
H
Haojun Liao 已提交
4159
    if (pTableGroupInfo->numOfTables > 1 || (pRuntimeEnv->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4160 4161
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4162 4163 4164 4165
      if (pTableQueryInfo == NULL) {
        break;
      }

H
Haojun Liao 已提交
4166
      pRuntimeEnv->current = *pTableQueryInfo;
H
Haojun Liao 已提交
4167
      doTableQueryInfoTimeWindowCheck(pQueryAttr, *pTableQueryInfo);
H
Haojun Liao 已提交
4168 4169
    }

H
Haojun Liao 已提交
4170
    // this function never returns error?
H
Haojun Liao 已提交
4171
    uint32_t status;
H
Haojun Liao 已提交
4172
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4173
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4174
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4175
    }
H
Haojun Liao 已提交
4176

H
Haojun Liao 已提交
4177
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4178
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4179
      continue;
H
Haojun Liao 已提交
4180 4181 4182 4183
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4184 4185

  return NULL;
H
Haojun Liao 已提交
4186 4187
}

H
Haojun Liao 已提交
4188
static SSDataBlock* doTableScan(void* param, bool *newgroup) {
H
Haojun Liao 已提交
4189 4190
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4191
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4192
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4193
  SQueryAttr       *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
4194

H
Haojun Liao 已提交
4195
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;
H
Haojun Liao 已提交
4196
  *newgroup = false;
H
Haojun Liao 已提交
4197

H
Haojun Liao 已提交
4198
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4199
    SSDataBlock* p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4200 4201
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4202 4203
    }

H
Haojun Liao 已提交
4204
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4205 4206 4207 4208 4209
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4210
    }
H
Haojun Liao 已提交
4211

H
Haojun Liao 已提交
4212
    // do prepare for the next round table scan operation
H
Haojun Liao 已提交
4213
    STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
H
Haojun Liao 已提交
4214
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4215

H
Haojun Liao 已提交
4216
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4217
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4218

H
Haojun Liao 已提交
4219 4220 4221 4222 4223
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4224 4225 4226 4227
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4228

H
Haojun Liao 已提交
4229 4230
    qDebug("QInfo:%"PRIu64" start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
           GET_QID(pRuntimeEnv), cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4231 4232
  }

H
Haojun Liao 已提交
4233
  SSDataBlock *p = NULL;
H
Haojun Liao 已提交
4234
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4235
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4236

H
Haojun Liao 已提交
4237
    STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
H
Haojun Liao 已提交
4238
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4239

H
Haojun Liao 已提交
4240 4241
    qDebug("QInfo:%"PRIu64" start to reverse scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
           GET_QID(pRuntimeEnv), cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4242

H
Haojun Liao 已提交
4243 4244
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4245 4246
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4247 4248
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4249

H
Haojun Liao 已提交
4250 4251 4252 4253
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4254

H
Haojun Liao 已提交
4255
    p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4256
  }
H
Haojun Liao 已提交
4257

H
Haojun Liao 已提交
4258
  return p;
H
Haojun Liao 已提交
4259 4260
}

H
Haojun Liao 已提交
4261
static SSDataBlock* doBlockInfoScan(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4262
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4263 4264 4265
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4266 4267

  STableScanInfo *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4268
  *newgroup = false;
H
Haojun Liao 已提交
4269 4270

  STableBlockDist tableBlockDist = {0};
sangshuduo's avatar
sangshuduo 已提交
4271
  tableBlockDist.numOfTables     = (int32_t)pOperator->pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
H
Haojun Liao 已提交
4272 4273
  tableBlockDist.dataBlockInfos  = taosArrayInit(512, sizeof(SFileBlockInfo));

H
Haojun Liao 已提交
4274
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4275
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4276 4277 4278 4279 4280

  SSDataBlock* pBlock = &pTableScanInfo->block;
  pBlock->info.rows   = 1;
  pBlock->info.numOfCols = 1;

H
Haojun Liao 已提交
4281 4282 4283 4284 4285 4286
  SBufferWriter bw = tbufInitWriter(NULL, false);
  blockDistInfoToBinary(&tableBlockDist, &bw);
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);

  int32_t len = (int32_t) tbufTell(&bw);
  pColInfo->pData = malloc(len + sizeof(int32_t));
H
Haojun Liao 已提交
4287

H
Haojun Liao 已提交
4288 4289
  *(int32_t*) pColInfo->pData = len;
  memcpy(pColInfo->pData + sizeof(int32_t), tbufGetData(&bw, false), len);
H
Haojun Liao 已提交
4290

H
Haojun Liao 已提交
4291
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4292

H
Haojun Liao 已提交
4293
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
H
Haojun Liao 已提交
4294
  pOperator->pRuntimeEnv->current = taosArrayGetP(g, 0);
H
Haojun Liao 已提交
4295 4296 4297

  pOperator->status = OP_EXEC_DONE;
  return pBlock;
H
Haojun Liao 已提交
4298 4299
}

H
Haojun Liao 已提交
4300
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4301 4302
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4303 4304
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4305
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4306
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4307
  pInfo->order        = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4308
  pInfo->current      = 0;
H
Haojun Liao 已提交
4309

H
Haojun Liao 已提交
4310
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4311
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4312
  pOperator->operatorType = OP_TableScan;
H
Haojun Liao 已提交
4313
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4314 4315
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4316
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4317
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4318
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4319 4320 4321 4322

  return pOperator;
}

H
Haojun Liao 已提交
4323
SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
4324 4325
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));

H
Haojun Liao 已提交
4326 4327 4328
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
H
Haojun Liao 已提交
4329
  pInfo->order            = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4330
  pInfo->current          = 0;
H
Haojun Liao 已提交
4331 4332

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4333 4334
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4335 4336 4337
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4338
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4339 4340
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4341

H
Haojun Liao 已提交
4342 4343 4344
  return pOperator;
}

H
Haojun Liao 已提交
4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363
SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv) {
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));

  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->block.pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));

  SColumnInfoData infoData = {{0}};
  infoData.info.type = TSDB_DATA_TYPE_BINARY;
  infoData.info.bytes = 1024;
  infoData.info.colId = TSDB_BLOCK_DIST_COLUMN_INDEX;
  taosArrayPush(pInfo->block.pDataBlock, &infoData);

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "TableBlockInfoScanOperator";
  pOperator->operatorType = OP_TableBlockInfoScan;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4364
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4365 4366 4367 4368 4369
  pOperator->exec         = doBlockInfoScan;

  return pOperator;
}

H
Haojun Liao 已提交
4370 4371 4372
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4373 4374 4375
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4376
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4377
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4378

H
Haojun Liao 已提交
4379 4380 4381
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
4382
  } else if (pDownstream->operatorType == OP_TimeWindow) {
H
Haojun Liao 已提交
4383
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4384 4385 4386

    pTableScanInfo->pCtx = pIntervalInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pIntervalInfo->resultRowInfo;
H
Haojun Liao 已提交
4387 4388
    pTableScanInfo->rowCellInfoOffset = pIntervalInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4389
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4390
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4391

H
Haojun Liao 已提交
4392 4393 4394
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4395

H
Haojun Liao 已提交
4396
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4397
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4398

4399 4400
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4401 4402
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4403
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4404
    SArithOperatorInfo *pInfo = pDownstream->info;
4405

4406 4407 4408 4409 4410 4411
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
  } else if (pDownstream->operatorType == OP_SessionWindow) {
    SSWindowOperatorInfo* pInfo = pDownstream->info;

H
Haojun Liao 已提交
4412 4413 4414
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4415 4416 4417
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4418 4419
}

H
Haojun Liao 已提交
4420
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4421 4422 4423 4424
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4425
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4426
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4427
  pInfo->current      = 0;
H
Haojun Liao 已提交
4428
  pInfo->order        = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4429 4430

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4431 4432
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4433
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4434 4435 4436
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4437 4438

  return pOptr;
H
Haojun Liao 已提交
4439 4440
}

H
Haojun Liao 已提交
4441 4442 4443 4444 4445 4446
SArray* getOrderCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4447 4448
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459
  }

  if (pQuery->interval.interval > 0) {
    if (pOrderColumns == NULL) {
      pOrderColumns = taosArrayInit(1, sizeof(SColIndex));
    }

    SColIndex colIndex = {.colIndex = 0, .colId = 0, .flag = TSDB_COL_NORMAL};
    taosArrayPush(pOrderColumns, &colIndex);
  }

H
Haojun Liao 已提交
4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471
  {
    numOfCols = (int32_t) taosArrayGetSize(pOrderColumns);
    for(int32_t i = 0; i < numOfCols; ++i) {
      SColIndex* index = taosArrayGet(pOrderColumns, i);
      for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
        if (index->colId == pQuery->pExpr1[j].base.colInfo.colId) {
          index->colIndex = j;
          index->colId = pQuery->pExpr1[j].base.resColId;
        }
      }
    }
  }
H
Haojun Liao 已提交
4472 4473 4474
  return pOrderColumns;
}

H
Haojun Liao 已提交
4475 4476 4477 4478 4479 4480
SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4481 4482
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4483 4484 4485 4486
  }

  for(int32_t i = 0; i < numOfCols; ++i) {
    SColIndex* index = taosArrayGet(pOrderColumns, i);
H
Haojun Liao 已提交
4487 4488

    bool found = false;
H
Haojun Liao 已提交
4489
    for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4490 4491 4492 4493 4494 4495
      SSqlExpr* pExpr = &pQuery->pExpr1[j].base;

      // TSDB_FUNC_TAG_DUMMY function needs to be ignored
      if (index->colId == pExpr->colInfo.colId &&
          ((TSDB_COL_IS_TAG(pExpr->colInfo.flag) && pExpr->functionId == TSDB_FUNC_TAG) ||
           (TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && pExpr->functionId == TSDB_FUNC_PRJ))) {
H
Haojun Liao 已提交
4496
        index->colIndex = j;
H
Haojun Liao 已提交
4497 4498 4499
        index->colId = pExpr->resColId;
        found = true;
        break;
H
Haojun Liao 已提交
4500 4501
      }
    }
H
Haojun Liao 已提交
4502 4503

    assert(found && index->colIndex >= 0 && index->colIndex < pQuery->numOfOutput);
H
Haojun Liao 已提交
4504 4505 4506 4507
  }

  return pOrderColumns;
}
H
Haojun Liao 已提交
4508

4509 4510 4511
static void destroyGlobalAggOperatorInfo(void* param, int32_t numOfOutput) {
  SMultiwayMergeInfo *pInfo = (SMultiwayMergeInfo*) param;
  destroyBasicOperatorInfo(&pInfo->binfo, numOfOutput);
4512 4513 4514 4515 4516

  taosArrayDestroy(pInfo->orderColumnList);
  taosArrayDestroy(pInfo->groupColumnList);
  tfree(pInfo->prevRow);
  tfree(pInfo->currentGroupColData);
4517 4518
}

H
Haojun Liao 已提交
4519
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream,
H
Haojun Liao 已提交
4520
                                                 SExprInfo* pExpr, int32_t numOfOutput, void* param) {
H
Haojun Liao 已提交
4521 4522
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

4523 4524 4525
  pInfo->resultRowFactor =
      (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery,
                                              false));
H
Haojun Liao 已提交
4526

H
Haojun Liao 已提交
4527 4528
  pRuntimeEnv->scanFlag = MERGE_STAGE;  // TODO init when creating pCtx

H
Haojun Liao 已提交
4529
  pInfo->pMerge = param;
H
Haojun Liao 已提交
4530
  pInfo->bufCapacity = 4096;
4531 4532

  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor);
H
Haojun Liao 已提交
4533 4534
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);

H
Haojun Liao 已提交
4535
  pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4536
  pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4537

H
Haojun Liao 已提交
4538 4539 4540
  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
4541
    len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4542 4543
  }

H
Haojun Liao 已提交
4544
  int32_t numOfCols = (pInfo->orderColumnList != NULL)? taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4545
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4546
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4547 4548

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4549 4550
    pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

H
Haojun Liao 已提交
4551 4552
    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
H
Haojun Liao 已提交
4553 4554
  }

H
Haojun Liao 已提交
4555
  numOfCols = (pInfo->groupColumnList != NULL)? taosArrayGetSize(pInfo->groupColumnList):0;
H
Haojun Liao 已提交
4556
  pInfo->currentGroupColData = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4557
  offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4558 4559

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4560
    pInfo->currentGroupColData[i] = (char*)pInfo->currentGroupColData + offset;
H
Haojun Liao 已提交
4561 4562 4563 4564 4565

    SColIndex* index = taosArrayGet(pInfo->groupColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
  }

H
Haojun Liao 已提交
4566 4567 4568
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  pInfo->seed = rand();
H
Haojun Liao 已提交
4569
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MERGE_STAGE);
H
Haojun Liao 已提交
4570 4571

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4572
  pOperator->name         = "GlobalAggregate";
H
Haojun Liao 已提交
4573 4574
  pOperator->operatorType = OP_GlobalAggregate;
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4575 4576 4577 4578 4579 4580 4581 4582
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;

  pOperator->exec         = doGlobalAggregate;
4583
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4584 4585 4586
  return pOperator;
}

H
Haojun Liao 已提交
4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600
SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SExprInfo *pExpr, int32_t numOfOutput,
                                              int32_t numOfRows, void *merger, bool groupMix) {
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

  pInfo->pMerge     = merger;
  pInfo->groupMix   = groupMix;
  pInfo->bufCapacity = numOfRows;

  pInfo->orderColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);

  {
    int32_t len = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
4601
      len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4602 4603 4604 4605
    }

    int32_t numOfCols = (pInfo->orderColumnList != NULL)? taosArrayGetSize(pInfo->orderColumnList):0;
    pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4606
    int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4607 4608 4609 4610 4611

    for(int32_t i = 0; i < numOfCols; ++i) {
      pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

      SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
4612
      offset += pExpr[index->colIndex].base.colBytes;
H
Haojun Liao 已提交
4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623
    }
  }

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "MultiwaySortOperator";
  pOperator->operatorType = OP_MultiwaySort;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4624
  pOperator->exec         = doMultiwayMergeSort;
4625
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4626 4627 4628
  return pOperator;
}

H
Haojun Liao 已提交
4629
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4630 4631 4632
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4633
// this is a blocking operator
H
Haojun Liao 已提交
4634
static SSDataBlock* doAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4635
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4636
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4637 4638
    return NULL;
  }
H
Haojun Liao 已提交
4639

H
Haojun Liao 已提交
4640
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4641 4642
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4643
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4644

H
Haojun Liao 已提交
4645 4646
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
4647

H
Haojun Liao 已提交
4648
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4649

H
Haojun Liao 已提交
4650
  while(1) {
H
Haojun Liao 已提交
4651
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4652 4653 4654 4655
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4656 4657 4658
    if (pRuntimeEnv->current != NULL) {
      setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
4659

H
Haojun Liao 已提交
4660
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4661
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4662 4663 4664
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4665
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4666
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4667
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4668 4669
  }

H
Haojun Liao 已提交
4670
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4671
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4672

H
Haojun Liao 已提交
4673 4674
  finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset);
  pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4675

H
Haojun Liao 已提交
4676
  return pInfo->pRes;
H
Haojun Liao 已提交
4677 4678
}

H
Haojun Liao 已提交
4679
static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4680
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4681
  if (pOperator->status == OP_EXEC_DONE) {
4682 4683
    return NULL;
  }
H
Haojun Liao 已提交
4684

H
Haojun Liao 已提交
4685
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4686 4687
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4688
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4689

H
Haojun Liao 已提交
4690 4691
  if (pOperator->status == OP_RES_TO_RETURN) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
4692

H
Haojun Liao 已提交
4693 4694
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4695 4696
    }

H
Haojun Liao 已提交
4697
    return pInfo->pRes;
4698
  }
H
Haojun Liao 已提交
4699

H
Haojun Liao 已提交
4700 4701
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
4702 4703 4704 4705

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
4706
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
4707 4708 4709 4710
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4711
    setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
4712

H
Haojun Liao 已提交
4713
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4714
      STableScanInfo* pScanInfo = upstream->info;
4715 4716 4717 4718
      order = getTableScanOrder(pScanInfo);
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4719
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
4720

H
Haojun Liao 已提交
4721
    TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
H
Haojun Liao 已提交
4722
    setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pRuntimeEnv->current->groupIndex, key);
H
Haojun Liao 已提交
4723
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
4724
  }
H
Haojun Liao 已提交
4725

H
Haojun Liao 已提交
4726 4727
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4728

H
Haojun Liao 已提交
4729
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4730
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4731

H
Haojun Liao 已提交
4732
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->resultRowInfo);
4733

H
Haojun Liao 已提交
4734 4735 4736
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4737 4738
  }

H
Haojun Liao 已提交
4739
  return pInfo->pRes;
4740 4741
}

H
Haojun Liao 已提交
4742
static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
4743 4744
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4745 4746
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4747
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4748

H
Haojun Liao 已提交
4749
  SSDataBlock* pRes = pInfo->pRes;
H
Haojun Liao 已提交
4750
  int32_t order = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4751 4752

  pRes->info.rows = 0;
H
Haojun Liao 已提交
4753

H
Haojun Liao 已提交
4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782
  if (pArithInfo->existDataBlock) {  // TODO refactor
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;

    SSDataBlock* pBlock = pArithInfo->existDataBlock;
    pArithInfo->existDataBlock = NULL;
    *newgroup = true;

    // todo dynamic set tags
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }

    // the pDataBlock are always the same one, no need to call this again
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);

    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);

    if (pTableQueryInfo != NULL) { // TODO refactor
      updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
    }

    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
      clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
      return pRes;
    }
  }

H
Haojun Liao 已提交
4783
  while(1) {
H
Haojun Liao 已提交
4784 4785 4786 4787
    bool prevVal = *newgroup;

    // The upstream exec may change the value of the newgroup, so use a local variable instead.
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4788
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4789 4790 4791
      assert(*newgroup == false);

      *newgroup = prevVal;
H
Haojun Liao 已提交
4792
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4793
      break;
H
Haojun Liao 已提交
4794 4795
    }

H
Haojun Liao 已提交
4796 4797 4798 4799 4800 4801 4802
    // Return result of the previous group in the firstly.
    if (newgroup && pRes->info.rows > 0) {
      pArithInfo->existDataBlock = pBlock;
      clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
      return pInfo->pRes;
    }

H
Haojun Liao 已提交
4803
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
4804 4805

    // todo dynamic set tags
H
Haojun Liao 已提交
4806 4807 4808
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
H
Haojun Liao 已提交
4809

H
Haojun Liao 已提交
4810
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4811
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4812
    updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);
4813

H
Haojun Liao 已提交
4814
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4815 4816 4817 4818

    if (pTableQueryInfo != NULL) { // TODO refactor
      updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
    }
H
Haojun Liao 已提交
4819

H
Haojun Liao 已提交
4820 4821
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4822 4823 4824 4825
      break;
    }
  }

H
Haojun Liao 已提交
4826
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4827
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4828 4829
}

H
Haojun Liao 已提交
4830
static SSDataBlock* doLimit(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4831
  SOperatorInfo* pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4832
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4833
    return NULL;
H
Haojun Liao 已提交
4834 4835
  }

H
Haojun Liao 已提交
4836
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4837
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4838

H
Haojun Liao 已提交
4839
  SSDataBlock* pBlock = NULL;
H
Haojun Liao 已提交
4840
  while (1) {
H
Haojun Liao 已提交
4841
    pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4842
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4843
      setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4844
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4845 4846 4847
      return NULL;
    }

H
Haojun Liao 已提交
4848
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4849
      break;
4850
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4851
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4852
    } else {
sangshuduo's avatar
sangshuduo 已提交
4853
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4854 4855 4856
      pBlock->info.rows = remain;

      for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
H
Haojun Liao 已提交
4857
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
H
Haojun Liao 已提交
4858 4859

        int16_t bytes = pColInfoData->info.bytes;
H
Haojun Liao 已提交
4860
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4861 4862
      }

H
Haojun Liao 已提交
4863
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4864
      break;
H
Haojun Liao 已提交
4865 4866
    }
  }
H
Haojun Liao 已提交
4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878

  if (pInfo->total + pBlock->info.rows >= pInfo->limit) {
    pBlock->info.rows = (int32_t)(pInfo->limit - pInfo->total);
    pInfo->total = pInfo->limit;

    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
    pOperator->status = OP_EXEC_DONE;
  } else {
    pInfo->total += pBlock->info.rows;
  }

  return pBlock;
H
Haojun Liao 已提交
4879 4880
}

D
dapan1121 已提交
4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893

bool doFilterData(SColumnInfoData* p, int32_t rid, SColumnFilterElem *filterElem, __filter_func_t fp) {
  char* input = p->pData + p->info.bytes * rid;
  bool isnull = isNull(input, p->info.type);
  if (isnull) {
    return (fp == isNullOperator) ? true : false;
  } else {
    if (fp == notNullOperator) {
      return true;
    } else if (fp == isNullOperator) {
      return false;
    }
  }
H
Haojun Liao 已提交
4894

D
dapan1121 已提交
4895 4896 4897 4898 4899 4900 4901
  if (fp(filterElem, input, input, p->info.type)) {
    return true;
  }

  return false;
}

4902
static SSDataBlock* doFilter(void* param, bool* newgroup) {
D
dapan1121 已提交
4903 4904 4905 4906 4907
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

4908
  SConditionOperatorInfo* pCondInfo = pOperator->info;
D
dapan1121 已提交
4909 4910 4911
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

  while (1) {
H
Haojun Liao 已提交
4912
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
D
dapan1121 已提交
4913
    if (pBlock == NULL) {
4914
      break;
D
dapan1121 已提交
4915
    }
H
Haojun Liao 已提交
4916

4917 4918 4919
    doSetFilterColumnInfo(pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock);
    assert(pRuntimeEnv->pTsBuf == NULL);
    filterRowsInDataBlock(pRuntimeEnv, pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock, true);
D
dapan1121 已提交
4920

4921 4922 4923
    if (pBlock->info.rows > 0) {
      return pBlock;
    }
D
dapan1121 已提交
4924 4925
  }

4926 4927 4928 4929
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  pOperator->status = OP_EXEC_DONE;
  return NULL;
}
D
dapan1121 已提交
4930

H
Haojun Liao 已提交
4931
static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4932
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4933
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4934 4935 4936
    return NULL;
  }

H
Haojun Liao 已提交
4937
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4938

H
Haojun Liao 已提交
4939
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4940
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4941 4942
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4943
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4944
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4945 4946 4947 4948
    }

    return pIntervalInfo->pRes;
  }
H
Haojun Liao 已提交
4949

H
Haojun Liao 已提交
4950 4951 4952
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
H
Haojun Liao 已提交
4953

H
Haojun Liao 已提交
4954
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4955 4956

  while(1) {
H
Haojun Liao 已提交
4957
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4958 4959 4960 4961 4962
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4963
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
H
Haojun Liao 已提交
4964
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4965 4966
  }

4967
  // restore the value
H
Haojun Liao 已提交
4968 4969
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
4970

H
Haojun Liao 已提交
4971
  pOperator->status = OP_RES_TO_RETURN;
4972
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4973
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4974
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4975

H
Haojun Liao 已提交
4976
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4977
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4978

H
Haojun Liao 已提交
4979
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4980
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4981 4982
  }

H
Haojun Liao 已提交
4983
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4984 4985
}

H
Haojun Liao 已提交
4986
static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4987
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4988
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4989 4990 4991
    return NULL;
  }

H
Haojun Liao 已提交
4992
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4993
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4994

H
Haojun Liao 已提交
4995
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4996
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4997
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4998
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4999 5000 5001 5002 5003
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
5004 5005
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
5006

H
Haojun Liao 已提交
5007
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
5008 5009

  while(1) {
H
Haojun Liao 已提交
5010
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5011
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5012
      break;
H
Haojun Liao 已提交
5013 5014
    }

H
Haojun Liao 已提交
5015
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5016
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
5017

H
Haojun Liao 已提交
5018
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5019
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
5020
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
5021

H
Haojun Liao 已提交
5022
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
5023
  }
H
Haojun Liao 已提交
5024

H
Haojun Liao 已提交
5025
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5026
  pQueryAttr->order.order = order;   // TODO : restore the order
5027
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
5028
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
5029

H
Haojun Liao 已提交
5030
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5031
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5032
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5033 5034 5035 5036
  }

  return pIntervalInfo->pRes;
}
H
Haojun Liao 已提交
5037

H
Haojun Liao 已提交
5038
static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SSWindowOperatorInfo* pWindowInfo = pOperator->info;
  SOptrBasicInfo* pBInfo = &pWindowInfo->binfo;

  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  if (pOperator->status == OP_RES_TO_RETURN) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pBInfo->pRes);

    if (pBInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
    }

    return pBInfo->pRes;
  }

H
Haojun Liao 已提交
5058 5059 5060
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
5061 5062 5063 5064

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5065
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
5066 5067 5068 5069 5070
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5071
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQueryAttr->order.order);
5072 5073 5074 5075
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

  // restore the value
H
Haojun Liao 已提交
5076 5077
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093

  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pBInfo->resultRowInfo);
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  finalizeQueryResult(pOperator, pBInfo->pCtx, &pBInfo->resultRowInfo, pBInfo->rowCellInfoOffset);

  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pBInfo->resultRowInfo);
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pBInfo->pRes);

  if (pBInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
  }

  return pBInfo->pRes->info.rows == 0? NULL:pBInfo->pRes;
}

H
Haojun Liao 已提交
5094
static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5095
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5096
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5097 5098 5099
    return NULL;
  }

H
Haojun Liao 已提交
5100
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5101

H
Haojun Liao 已提交
5102
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5103
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5104
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5105 5106

    if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5107
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5108
    }
H
Haojun Liao 已提交
5109

H
Haojun Liao 已提交
5110
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5111 5112 5113 5114 5115
  }

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5116
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5117 5118 5119 5120 5121
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5122
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQueryAttr->order.order);
H
Haojun Liao 已提交
5123
    setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5124
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
5125
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQueryAttr->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
5126 5127
    }

H
Haojun Liao 已提交
5128
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5129 5130
  }

H
Haojun Liao 已提交
5131
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5132
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5133
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5134

H
Haojun Liao 已提交
5135
  if (!pRuntimeEnv->pQueryAttr->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5136 5137 5138
    finalizeQueryResult(pOperator, pInfo->binfo.pCtx, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
  } else {
    updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
5139 5140
  }

H
Haojun Liao 已提交
5141
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5142
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5143

H
Haojun Liao 已提交
5144
  if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5145
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5146 5147
  }

H
Haojun Liao 已提交
5148
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5149 5150
}

H
Haojun Liao 已提交
5151
static SSDataBlock* doFill(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5152
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5153
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5154 5155 5156
    return NULL;
  }

H
Haojun Liao 已提交
5157
  SFillOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5158
  SQueryRuntimeEnv  *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5159

H
Haojun Liao 已提交
5160
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
H
Haojun Liao 已提交
5161
    *newgroup = false;
sangshuduo's avatar
sangshuduo 已提交
5162
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5163 5164 5165
    return pInfo->pRes;
  }

H
Haojun Liao 已提交
5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180
  // handle the cached new group data block
  if (pInfo->existNewGroupBlock) {
    pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
    int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey;
    taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);

    taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
    taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
    pInfo->existNewGroupBlock = NULL;
    *newgroup = true;
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
  }

H
Haojun Liao 已提交
5181
  while(1) {
H
Haojun Liao 已提交
5182 5183 5184 5185 5186 5187 5188 5189
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
    if (*newgroup) {
      assert(pBlock != NULL);
    }

    if (*newgroup && pInfo->totalInputRows > 0) {  // there are already processed current group data block
      pInfo->existNewGroupBlock = pBlock;
      *newgroup = false;
H
Haojun Liao 已提交
5190

H
Haojun Liao 已提交
5191 5192
      // fill the previous group data block
      // before handle a new data block, close the fill operation for previous group data block
H
Haojun Liao 已提交
5193
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
H
Haojun Liao 已提交
5194
    } else {
H
Haojun Liao 已提交
5195 5196 5197 5198 5199 5200 5201 5202 5203
      if (pBlock == NULL) {
        if (pInfo->totalInputRows == 0) {
          pOperator->status = OP_EXEC_DONE;
          return NULL;
        }

        taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
      } else {
        pInfo->totalInputRows += pBlock->info.rows;
H
Haojun Liao 已提交
5204

H
Haojun Liao 已提交
5205 5206
        int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
                                                                            : */pBlock->info.window.ekey;
H
Haojun Liao 已提交
5207

H
Haojun Liao 已提交
5208 5209 5210
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
H
Haojun Liao 已提交
5211 5212
    }

H
Haojun Liao 已提交
5213
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233
    if (pInfo->pRes->info.rows > 0) {  // current group has no more result to return
      return pInfo->pRes;
    } else if (pInfo->existNewGroupBlock) {  // try next group
      pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
      int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
                                                                          :*/ pInfo->existNewGroupBlock->info.window.ekey;
      taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);

      taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

      doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
      pInfo->existNewGroupBlock = NULL;
      *newgroup = true;

      return (pInfo->pRes->info.rows > 0) ? pInfo->pRes : NULL;
    } else {
      return NULL;
    }
    //    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
5234 5235
  }
}
H
Haojun Liao 已提交
5236

H
Haojun Liao 已提交
5237
// todo set the attribute of query scan count
H
Haojun Liao 已提交
5238 5239 5240
static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
H
Haojun Liao 已提交
5241 5242 5243 5244 5245 5246 5247 5248
    if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) {
      return 2;
    }
  }

  return 1;
}

H
Haojun Liao 已提交
5249 5250 5251 5252 5253
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5254
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5255
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5256 5257
  }

H
Haojun Liao 已提交
5258
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5259
  tfree(pOperator->info);
H
Haojun Liao 已提交
5260 5261 5262
  tfree(pOperator);
}

H
Haojun Liao 已提交
5263
SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5264 5265
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5266 5267
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
H
Haojun Liao 已提交
5268 5269

  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
H
Haojun Liao 已提交
5270
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5271

H
Haojun Liao 已提交
5272
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5273

H
Haojun Liao 已提交
5274
  pInfo->seed = rand();
H
Haojun Liao 已提交
5275
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5276

H
Haojun Liao 已提交
5277
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5278
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5279
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5280
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5281
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5282
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5283
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5284 5285 5286
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5287

H
Haojun Liao 已提交
5288 5289
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5290 5291 5292
  return pOperator;
}

H
Haojun Liao 已提交
5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309
static void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) {
  assert(pInfo != NULL);

  destroySQLFunctionCtx(pInfo->pCtx, numOfOutput);
  tfree(pInfo->rowCellInfoOffset);

  cleanupResultRowInfo(&pInfo->resultRowInfo);
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) {
  SOptrBasicInfo* pInfo = (SOptrBasicInfo*) param;
  doDestroyBasicInfo(pInfo, numOfOutput);
}

static void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
  SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param;
H
Haojun Liao 已提交
5310
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5311 5312 5313 5314
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5315
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5316
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5317
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5318 5319 5320 5321 5322 5323 5324
}

static void destroyArithOperatorInfo(void* param, int32_t numOfOutput) {
  SArithOperatorInfo* pInfo = (SArithOperatorInfo*) param;
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}

H
Haojun Liao 已提交
5325 5326 5327 5328 5329
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

5330 5331 5332
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
  SConditionOperatorInfo* pInfo = (SConditionOperatorInfo*) param;
  doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
D
dapan1121 已提交
5333 5334
}

H
Haojun Liao 已提交
5335
SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
5336 5337
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5338
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5339

H
Haojun Liao 已提交
5340
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) tableGroup);
H
Haojun Liao 已提交
5341
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
sangshuduo's avatar
sangshuduo 已提交
5342
  initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)tableGroup, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5343

5344
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5345 5346
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5347
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5348
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5349
  pOperator->info         = pInfo;
5350
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5351 5352 5353
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5354

H
Haojun Liao 已提交
5355 5356 5357
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5358
  return pOperator;
H
Haojun Liao 已提交
5359 5360
}

H
Haojun Liao 已提交
5361
SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5362 5363
  SArithOperatorInfo* pInfo = calloc(1, sizeof(SArithOperatorInfo));

H
Haojun Liao 已提交
5364
  pInfo->seed = rand();
H
Haojun Liao 已提交
5365
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5366

H
Haojun Liao 已提交
5367
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5368
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5369 5370 5371
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5372
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5373 5374

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5375 5376
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5377
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5378
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5379
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5380
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5381 5382 5383
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5384

H
Haojun Liao 已提交
5385 5386 5387
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5388 5389 5390
  return pOperator;
}

5391 5392 5393
SOperatorInfo* createConditionOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
                                           int32_t numOfOutput) {
  SConditionOperatorInfo* pInfo = calloc(1, sizeof(SConditionOperatorInfo));
D
dapan1121 已提交
5394

5395 5396
  {
    SColumnInfo* pCols = calloc(numOfOutput, sizeof(SColumnInfo));
D
dapan1121 已提交
5397

5398 5399 5400 5401 5402
    int32_t numOfFilter = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
      if (pExpr[i].base.flist.numOfFilters > 0) {
        numOfFilter += 1;
      }
D
dapan1121 已提交
5403

5404 5405 5406
      pCols[i].type = pExpr[i].base.resType;
      pCols[i].bytes = pExpr[i].base.resBytes;
      pCols[i].colId = pExpr[i].base.resColId;
H
Haojun Liao 已提交
5407

5408 5409 5410
      pCols[i].flist.numOfFilters = pExpr[i].base.flist.numOfFilters;
      pCols[i].flist.filterInfo = calloc(pCols[i].flist.numOfFilters, sizeof(SColumnFilterInfo));
      memcpy(pCols[i].flist.filterInfo, pExpr[i].base.flist.filterInfo, pCols[i].flist.numOfFilters * sizeof(SColumnFilterInfo));
D
dapan1121 已提交
5411 5412
    }

5413 5414 5415
    assert(numOfFilter > 0);
    doCreateFilterInfo(pCols, numOfOutput, numOfFilter, &pInfo->pFilterInfo, 0);
    pInfo->numOfFilterCols = numOfFilter;
D
dapan1121 已提交
5416

5417 5418
    for(int32_t i = 0; i < numOfOutput; ++i) {
      tfree(pCols[i].flist.filterInfo);
D
dapan1121 已提交
5419 5420
    }

5421
    tfree(pCols);
D
dapan1121 已提交
5422 5423 5424 5425
  }

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

5426 5427
  pOperator->name         = "ConditionOperator";
  pOperator->operatorType = OP_Condition;
D
dapan1121 已提交
5428 5429 5430 5431 5432
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
5433
  pOperator->exec         = doFilter;
D
dapan1121 已提交
5434 5435
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5436
  pOperator->cleanup      = destroyConditionOperatorInfo;
D
dapan1121 已提交
5437 5438 5439 5440

  return pOperator;
}

H
Haojun Liao 已提交
5441
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5442
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
H
Haojun Liao 已提交
5443
  pInfo->limit = pRuntimeEnv->pQueryAttr->limit.limit;
H
Haojun Liao 已提交
5444 5445 5446

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5447 5448
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5449
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5450
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5451
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5452
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5453 5454
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5455 5456 5457 5458

  return pOperator;
}

H
Haojun Liao 已提交
5459
SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5460
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5461

H
Haojun Liao 已提交
5462
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5463
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5464
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5465 5466 5467

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5468
  pOperator->name         = "TimeIntervalAggOperator";
5469
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5470
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5471
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5472
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5473 5474 5475 5476
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5477
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5478 5479
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5480 5481 5482
  return pOperator;
}

5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507
SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
  SSWindowOperatorInfo* pInfo = calloc(1, sizeof(SSWindowOperatorInfo));

  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  pInfo->prevTs = INT64_MIN;
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "SessionWindowAggOperator";
  pOperator->operatorType = OP_SessionWindow;
  pOperator->blockingOptr = true;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doSessionWindowAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

  return pOperator;
}

H
Haojun Liao 已提交
5508
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5509
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5510

H
Haojun Liao 已提交
5511
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5512
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5513
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5514 5515

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5516 5517
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5518
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5519
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5520
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5521 5522
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5523 5524
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5525

H
Haojun Liao 已提交
5526 5527 5528
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5529 5530 5531
  return pOperator;
}

H
Haojun Liao 已提交
5532
SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5533
  SGroupbyOperatorInfo* pInfo = calloc(1, sizeof(SGroupbyOperatorInfo));
H
Haojun Liao 已提交
5534
  pInfo->colIndex = -1;  // group by column index
H
Haojun Liao 已提交
5535

H
Haojun Liao 已提交
5536
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5537
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5538
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5539 5540

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5541
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5542
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5543 5544
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5545
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5546 5547 5548 5549
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5550
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5551 5552
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5553 5554
  return pOperator;
}
H
Haojun Liao 已提交
5555

H
Haojun Liao 已提交
5556
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5557
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5558
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5559 5560 5561
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);

  {
H
Haojun Liao 已提交
5562 5563
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQueryAttr->fillVal);
H
Haojun Liao 已提交
5564 5565
    STimeWindow w = TSWINDOW_INITIALIZER;

H
Haojun Liao 已提交
5566 5567 5568
    TSKEY sk = MIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
    TSKEY ek = MAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
    getAlignQueryTimeWindow(pQueryAttr, pQueryAttr->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
5569

H
Haojun Liao 已提交
5570 5571 5572 5573
    pInfo->pFillInfo =
        taosCreateFillInfo(pQueryAttr->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput,
                           pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit,
                           (int8_t)pQueryAttr->precision, pQueryAttr->fillType, pColInfo, pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
5574
  }
H
Haojun Liao 已提交
5575 5576 5577

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5578
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5579
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5580 5581 5582
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5583
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5584 5585 5586 5587
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5588

H
Haojun Liao 已提交
5589 5590 5591
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5592 5593 5594
  return pOperator;
}

H
Haojun Liao 已提交
5595
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) {
H
Haojun Liao 已提交
5596 5597
  SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo));

H
Haojun Liao 已提交
5598 5599 5600 5601 5602 5603 5604 5605 5606
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;

  pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr);
  pInfo->pMerger = pMerger;
  pInfo->slimit = pQueryAttr->slimit;
  pInfo->limit  = pQueryAttr->limit;

  pInfo->currentGroupOffset = pQueryAttr->slimit.offset;
  pInfo->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
5607 5608 5609 5610 5611 5612 5613 5614 5615

  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
    len += pExpr[i].base.resBytes;
  }

  int32_t numOfCols = pInfo->orderColumnList != NULL? taosArrayGetSize(pInfo->orderColumnList):0;
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
5616
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
5617 5618 5619 5620 5621 5622 5623

  for(int32_t i = 0; i < numOfCols; ++i) {
    pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
  }
H
Haojun Liao 已提交
5624 5625 5626 5627 5628 5629 5630 5631

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "SLimitOperator";
  pOperator->operatorType = OP_SLimit;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5632
  pOperator->exec         = doSLimit;
H
Haojun Liao 已提交
5633 5634 5635 5636 5637 5638 5639
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;

  return pOperator;
}


H
Haojun Liao 已提交
5640
static SSDataBlock* doTagScan(void* param, bool* newgroup) {
5641
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5642
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5643 5644
    return NULL;
  }
5645

H
Haojun Liao 已提交
5646
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5647

H
Haojun Liao 已提交
5648
  int32_t maxNumOfTables = (int32_t)pRuntimeEnv->resultInfo.capacity;
5649

H
Haojun Liao 已提交
5650 5651
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
H
Haojun Liao 已提交
5652
  *newgroup = false;
5653 5654

  int32_t count = 0;
H
Haojun Liao 已提交
5655 5656 5657 5658
  SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);

  int32_t functionId = pOperator->pExpr[0].base.functionId;
  if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id
H
Haojun Liao 已提交
5659 5660
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    assert(pQueryAttr->numOfOutput == 1);
5661 5662

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
H
Haojun Liao 已提交
5663
    int32_t rsize = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
5664

5665 5666
    count = 0;

H
Haojun Liao 已提交
5667 5668
    int16_t bytes = pExprInfo->base.resBytes;
    int16_t type  = pExprInfo->base.resType;
5669

H
Haojun Liao 已提交
5670 5671 5672 5673
    for(int32_t i = 0; i < pQueryAttr->numOfTags; ++i) {
      if (pQueryAttr->tagColList[i].colId == pExprInfo->base.colInfo.colId) {
        bytes = pQueryAttr->tagColList[i].bytes;
        type = pQueryAttr->tagColList[i].type;
5674 5675 5676 5677
        break;
      }
    }

H
Haojun Liao 已提交
5678 5679 5680 5681
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5682 5683
      STableQueryInfo *item = taosArrayGetP(pa, i);

H
Haojun Liao 已提交
5684
      char *output = pColInfo->pData + count * rsize;
5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698
      varDataSetLen(output, rsize - VARSTR_HEADER_SIZE);

      output = varDataVal(output);
      STableId* id = TSDB_TABLEID(item->pTable);

      *(int16_t *)output = 0;
      output += sizeof(int16_t);

      *(int64_t *)output = id->uid;  // memory align problem, todo serialize
      output += sizeof(id->uid);

      *(int32_t *)output = id->tid;
      output += sizeof(id->tid);

H
Haojun Liao 已提交
5699 5700
      *(int32_t *)output = pQueryAttr->vgId;
      output += sizeof(pQueryAttr->vgId);
5701

H
Haojun Liao 已提交
5702
      char* data = NULL;
5703
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5704
        data = tsdbGetTableName(item->pTable);
5705
      } else {
H
Haojun Liao 已提交
5706
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5707 5708
      }

H
Haojun Liao 已提交
5709
      doSetTagValueToResultBuf(output, data, type, bytes);
5710 5711 5712
      count += 1;
    }

H
Haojun Liao 已提交
5713
    qDebug("QInfo:%"PRIu64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5714 5715 5716
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5717
    count = 1;
H
Haojun Liao 已提交
5718 5719

    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5720
    qDebug("QInfo:%"PRIu64" create count(tbname) query, res:%d rows:1", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5721
  } else {  // return only the tags|table name etc.
H
Haojun Liao 已提交
5722
    SExprInfo* pExprInfo = pOperator->pExpr;  // todo use the column list instead of exprinfo
5723

H
Haojun Liao 已提交
5724 5725 5726
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737

      STableQueryInfo* item = taosArrayGetP(pa, i);

      char *data = NULL, *dst = NULL;
      int16_t type = 0, bytes = 0;
      for(int32_t j = 0; j < pOperator->numOfOutput; ++j) {
        // not assign value in case of user defined constant output column
        if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) {
          continue;
        }

H
Haojun Liao 已提交
5738
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5739 5740
        type  = pExprInfo[j].base.resType;
        bytes = pExprInfo[j].base.resBytes;
5741 5742 5743 5744 5745 5746 5747

        if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
          data = tsdbGetTableName(item->pTable);
        } else {
          data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes);
        }

H
Haojun Liao 已提交
5748
        dst  = pColInfo->pData + count * pExprInfo[j].base.resBytes;
5749 5750
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5751

5752 5753 5754
      count += 1;
    }

H
Haojun Liao 已提交
5755 5756 5757 5758
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

H
Haojun Liao 已提交
5759
    qDebug("QInfo:%"PRIu64" create tag values results completed, rows:%d", GET_QID(pRuntimeEnv), count);
5760 5761
  }

H
Haojun Liao 已提交
5762
  pRes->info.rows = count;
H
Haojun Liao 已提交
5763
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5764 5765
}

H
Haojun Liao 已提交
5766
SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput) {
5767
  STagScanInfo* pInfo = calloc(1, sizeof(STagScanInfo));
H
Haojun Liao 已提交
5768
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
5769

H
Haojun Liao 已提交
5770 5771 5772 5773 5774 5775
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

  pInfo->totalTables = pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
  pInfo->currentIndex = 0;

5776
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5777
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5778
  pOperator->operatorType = OP_TagScan;
5779
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5780
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5781 5782
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5783 5784
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5785
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5786
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5787

5788 5789
  return pOperator;
}
H
Haojun Liao 已提交
5790

H
Haojun Liao 已提交
5791
static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
5792
  int32_t j = 0;
5793

H
Haojun Liao 已提交
5794 5795
  if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
    if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5796
      return TSDB_TBNAME_COLUMN_INDEX;
H
Haojun Liao 已提交
5797
    } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
Y
yihaoDeng 已提交
5798
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5799
    }
Y
yihaoDeng 已提交
5800
    
H
Haojun Liao 已提交
5801

H
Haojun Liao 已提交
5802 5803
    while(j < pTableInfo->numOfTags) {
      if (pExpr->colInfo.colId == pTagCols[j].colId) {
5804 5805
        return j;
      }
5806

5807 5808
      j += 1;
    }
5809

H
Haojun Liao 已提交
5810
  } else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5811
    return TSDB_UD_COLUMN_INDEX;
5812
  } else {
H
Haojun Liao 已提交
5813 5814
    while (j < pTableInfo->numOfCols) {
      if (pExpr->colInfo.colId == pTableInfo->colList[j].colId) {
5815 5816
        return j;
      }
5817

5818
      j += 1;
5819 5820
    }
  }
5821 5822

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5823 5824
}

H
Haojun Liao 已提交
5825 5826
bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols);
5827
  return j != INT32_MIN;
5828 5829
}

5830
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5831 5832
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5833
    return false;
5834 5835
  }

5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846
  if (pQueryMsg->sw.gap < 0 || pQueryMsg->sw.primaryColId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
    qError("qmsg:%p illegal value of session window time %" PRId64, pQueryMsg, pQueryMsg->sw.gap);
    return false;
  }

  if (pQueryMsg->sw.gap > 0 && pQueryMsg->interval.interval > 0) {
    qError("qmsg:%p illegal value of session window time %" PRId64" and interval value %"PRId64, pQueryMsg,
        pQueryMsg->sw.gap, pQueryMsg->interval.interval);
    return false;
  }

H
hjxilinx 已提交
5847
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5848
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5849
    return false;
5850 5851
  }

H
hjxilinx 已提交
5852
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5853
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5854
    return false;
5855 5856
  }

5857 5858
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5859
    return false;
5860 5861
  }

5862 5863 5864
  return true;
}

H
Haojun Liao 已提交
5865 5866 5867 5868 5869
static UNUSED_FUNC bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SSqlExpr** pExpr, int32_t numOfOutput,
                                   SColumnInfo* pTagCols, void* pMsg) {
  int32_t numOfTotal = pTableInfo->numOfCols + pTableInfo->numOfTags;
  if (pTableInfo->numOfCols < 0 || pTableInfo->numOfTags < 0 || numOfTotal > TSDB_MAX_COLUMNS) {
    qError("qmsg:%p illegal value of numOfCols %d numOfTags:%d", pMsg, pTableInfo->numOfCols, pTableInfo->numOfTags);
5870
    return false;
5871 5872
  }

H
Haojun Liao 已提交
5873 5874 5875 5876 5877 5878 5879
  if (numOfTotal == 0) {  // table total columns are not required.
    for(int32_t i = 0; i < numOfOutput; ++i) {
      SSqlExpr* p = pExpr[i];
      if ((p->functionId == TSDB_FUNC_TAGPRJ) ||
          (p->functionId == TSDB_FUNC_TID_TAG && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (p->functionId == TSDB_FUNC_COUNT && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (p->functionId == TSDB_FUNC_BLKINFO)) {
5880
        continue;
5881
      }
5882

5883
      return false;
5884 5885
    }
  }
5886

H
Haojun Liao 已提交
5887 5888
  for(int32_t i = 0; i < numOfOutput; ++i) {
    if (!validateExprColumnInfo(pTableInfo, pExpr[i], pTagCols)) {
5889 5890 5891 5892
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5893
  return true;
5894 5895
}

5896
static char *createTableIdList(SQueryTableMsg *pQueryMsg, char *pMsg, SArray **pTableIdList) {
H
hjxilinx 已提交
5897
  assert(pQueryMsg->numOfTables > 0);
5898

weixin_48148422's avatar
weixin_48148422 已提交
5899
  *pTableIdList = taosArrayInit(pQueryMsg->numOfTables, sizeof(STableIdInfo));
5900

weixin_48148422's avatar
weixin_48148422 已提交
5901 5902
  for (int32_t j = 0; j < pQueryMsg->numOfTables; ++j) {
    STableIdInfo* pTableIdInfo = (STableIdInfo *)pMsg;
5903

5904
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5905 5906
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5907

H
hjxilinx 已提交
5908 5909 5910
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5911

H
hjxilinx 已提交
5912 5913
  return pMsg;
}
5914

5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945
static int32_t deserializeColFilterInfo(SColumnFilterInfo* pColFilters, int16_t numOfFilters, char** pMsg) {
  for (int32_t f = 0; f < numOfFilters; ++f) {
    SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)(*pMsg);

    SColumnFilterInfo *pColFilter = &pColFilters[f];
    pColFilter->filterstr = htons(pFilterMsg->filterstr);

    (*pMsg) += sizeof(SColumnFilterInfo);

    if (pColFilter->filterstr) {
      pColFilter->len = htobe64(pFilterMsg->len);

      pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
      if (pColFilter->pz == 0) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }

      memcpy((void *)pColFilter->pz, (*pMsg), (size_t)pColFilter->len);
      (*pMsg) += (pColFilter->len + 1);
    } else {
      pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
      pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
    }

    pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
    pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
  }

  return TSDB_CODE_SUCCESS;
}

5946
/**
H
hjxilinx 已提交
5947
 * pQueryMsg->head has been converted before this function is called.
5948
 *
H
hjxilinx 已提交
5949
 * @param pQueryMsg
5950 5951 5952 5953
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5954
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5955 5956
  int32_t code = TSDB_CODE_SUCCESS;

5957 5958 5959 5960
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5961 5962 5963
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);
  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5964 5965 5966
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5967 5968
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5969
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5970

5971 5972
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5973
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5974
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5975 5976

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5977
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5978
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5979
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
H
Haojun Liao 已提交
5980 5981 5982 5983
  pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset);
  pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen);
  pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks);
  pQueryMsg->tsBuf.tsOrder = htonl(pQueryMsg->tsBuf.tsOrder);
5984
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5985
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5986
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5987
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5988
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5989 5990
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
H
Haojun Liao 已提交
5991 5992
  pQueryMsg->tableScanOperator = htonl(pQueryMsg->tableScanOperator);
  pQueryMsg->numOfOperator = htonl(pQueryMsg->numOfOperator);
5993

5994
  // query msg safety check
5995
  if (!validateQueryMsg(pQueryMsg)) {
5996 5997
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5998 5999
  }

H
Haojun Liao 已提交
6000
  char *pMsg = (char *)(pQueryMsg->tableCols) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
H
hjxilinx 已提交
6001
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
H
Haojun Liao 已提交
6002
    SColumnInfo *pColInfo = &pQueryMsg->tableCols[col];
6003

H
hjxilinx 已提交
6004
    pColInfo->colId = htons(pColInfo->colId);
6005
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
6006
    pColInfo->bytes = htons(pColInfo->bytes);
6007
    pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters);
6008

6009 6010 6011 6012 6013
    if (!isValidDataType(pColInfo->type)) {
      qDebug("qmsg:%p, invalid data type in source column, index:%d, type:%d", pQueryMsg, col, pColInfo->type);
      code = TSDB_CODE_QRY_INVALID_MSG;
      goto _cleanup;
    }
6014

6015
    int32_t numOfFilters = pColInfo->flist.numOfFilters;
6016
    if (numOfFilters > 0) {
6017 6018
      pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo));
      if (pColInfo->flist.filterInfo == NULL) {
H
Haojun Liao 已提交
6019 6020 6021
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
6022 6023
    }

6024 6025 6026
    code = deserializeColFilterInfo(pColInfo->flist.filterInfo, numOfFilters, &pMsg);
    if (code != TSDB_CODE_SUCCESS) {
      goto _cleanup;
6027 6028 6029
    }
  }

H
Haojun Liao 已提交
6030
  param->tableScanOperator = pQueryMsg->tableScanOperator;
H
Haojun Liao 已提交
6031 6032
  param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExpr == NULL) {
H
Haojun Liao 已提交
6033 6034 6035 6036
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

H
Haojun Liao 已提交
6037
  SSqlExpr *pExprMsg = (SSqlExpr *)pMsg;
6038

6039
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
6040
    param->pExpr[i] = pExprMsg;
6041

6042
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
6043
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6044
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6045
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6046 6047 6048 6049
    pExprMsg->colType       = htons(pExprMsg->colType);

    pExprMsg->resType       = htons(pExprMsg->resType);
    pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6050

H
Haojun Liao 已提交
6051 6052 6053
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
6054
    pExprMsg->flist.numOfFilters  = htons(pExprMsg->flist.numOfFilters);
H
Haojun Liao 已提交
6055
    pMsg += sizeof(SSqlExpr);
6056 6057

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6058 6059
      pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
      pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
6060

H
Haojun Liao 已提交
6061 6062 6063
      if (pExprMsg->param[j].nType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->param[j].pz = pMsg;
        pMsg += pExprMsg->param[j].nLen;  // one more for the string terminated char.
6064
      } else {
H
Haojun Liao 已提交
6065
        pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
6066 6067 6068
      }
    }

H
Haojun Liao 已提交
6069 6070
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
6071
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
6072 6073
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
6074 6075 6076
      }
    }

6077 6078 6079 6080 6081
    if (pExprMsg->flist.numOfFilters > 0) {
      pExprMsg->flist.filterInfo = calloc(pExprMsg->flist.numOfFilters, sizeof(SColumnFilterInfo));
    }

    deserializeColFilterInfo(pExprMsg->flist.filterInfo, pExprMsg->flist.numOfFilters, &pMsg);
H
Haojun Liao 已提交
6082
    pExprMsg = (SSqlExpr *)pMsg;
6083
  }
6084

H
Haojun Liao 已提交
6085
  if (pQueryMsg->secondStageOutput) {
H
Haojun Liao 已提交
6086 6087
    pExprMsg = (SSqlExpr *)pMsg;
    param->pSecExpr = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
6088

H
Haojun Liao 已提交
6089
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
H
Haojun Liao 已提交
6090
      param->pSecExpr[i] = pExprMsg;
H
Haojun Liao 已提交
6091 6092 6093

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6094
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6095 6096
      pExprMsg->resType       = htons(pExprMsg->resType);
      pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6097
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6098
      pExprMsg->colType       = htons(pExprMsg->colType);
H
Haojun Liao 已提交
6099

H
Haojun Liao 已提交
6100 6101 6102
      pExprMsg->functionId = htons(pExprMsg->functionId);
      pExprMsg->numOfParams = htons(pExprMsg->numOfParams);

H
Haojun Liao 已提交
6103
      pMsg += sizeof(SSqlExpr);
H
Haojun Liao 已提交
6104 6105

      for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6106 6107
        pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
        pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
H
Haojun Liao 已提交
6108

H
Haojun Liao 已提交
6109 6110 6111
        if (pExprMsg->param[j].nType == TSDB_DATA_TYPE_BINARY) {
          pExprMsg->param[j].pz = pMsg;
          pMsg += pExprMsg->param[j].nLen;  // one more for the string terminated char.
H
Haojun Liao 已提交
6112
        } else {
H
Haojun Liao 已提交
6113
          pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
H
Haojun Liao 已提交
6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124
        }
      }

      int16_t functionId = pExprMsg->functionId;
      if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
        if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
          code = TSDB_CODE_QRY_INVALID_MSG;
          goto _cleanup;
        }
      }

H
Haojun Liao 已提交
6125
      pExprMsg = (SSqlExpr *)pMsg;
H
Haojun Liao 已提交
6126 6127 6128
    }
  }

6129
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
6130

H
hjxilinx 已提交
6131
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
6132 6133
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
6134 6135 6136
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6137 6138

    for (int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
6139 6140
      param->pGroupColIndex[i].colId = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colId);
6141

6142 6143
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
6144

6145 6146
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
6147

6148 6149
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
6150
    }
6151

H
hjxilinx 已提交
6152 6153
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
6154 6155
  }

6156 6157
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
6158
    pQueryMsg->fillVal = (uint64_t)(pMsg);
6159 6160

    int64_t *v = (int64_t *)pMsg;
6161
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
6162 6163
      v[i] = htobe64(v[i]);
    }
6164

6165
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
6166
  }
6167

6168
  if (pQueryMsg->numOfTags > 0) {
6169 6170
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
6171 6172 6173 6174
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6175 6176
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6177

6178 6179 6180
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
6181
      pTagCol->flist.numOfFilters = 0;
6182

6183
      param->pTagColumnInfo[i] = *pTagCol;
6184
      pMsg += sizeof(SColumnInfo);
6185
    }
H
hjxilinx 已提交
6186
  }
6187

6188 6189
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6190 6191
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6192 6193 6194
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6195 6196

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6197 6198
    pMsg += pQueryMsg->tagCondLen;
  }
6199

6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210
  if (pQueryMsg->prevResultLen > 0) {
    param->prevResult = calloc(1, pQueryMsg->prevResultLen);
    if (param->prevResult == NULL) {
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

    memcpy(param->prevResult, pMsg, pQueryMsg->prevResultLen);
    pMsg += pQueryMsg->prevResultLen;
  }

H
Haojun Liao 已提交
6211
  if (pQueryMsg->tbnameCondLen > 0) {
6212 6213
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6214 6215 6216 6217
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6218
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6219
    pMsg += pQueryMsg->tbnameCondLen;
6220 6221
  }

D
dapan1121 已提交
6222
  //skip ts buf
H
Haojun Liao 已提交
6223 6224
  if ((pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen;
D
dapan1121 已提交
6225 6226
  }

H
Haojun Liao 已提交
6227 6228 6229 6230 6231 6232 6233 6234
  param->pOperator = taosArrayInit(pQueryMsg->numOfOperator, sizeof(int32_t));
  for(int32_t i = 0; i < pQueryMsg->numOfOperator; ++i) {
    int32_t op = htonl(*(int32_t*)pMsg);
    taosArrayPush(param->pOperator, &op);

    pMsg += sizeof(int32_t);
  }

6235
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6236

H
Haojun Liao 已提交
6237
  SQueriedTableInfo info = { .numOfTags = pQueryMsg->numOfTags, .numOfCols = pQueryMsg->numOfCols, .colList = pQueryMsg->tableCols};
H
Haojun Liao 已提交
6238
  if (!validateQueryTableCols(&info, param->pExpr, pQueryMsg->numOfOutput, param->pTagColumnInfo, pQueryMsg)) {
6239 6240
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6241
  }
6242

6243
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6244 6245
         "outputCols:%d, numOfCols:%d, interval:%" PRId64 ", fillType:%d, comptsLen:%d, compNumOfBlocks:%d, limit:%" PRId64 ", offset:%" PRId64,
         pQueryMsg, pQueryMsg->numOfTables, pQueryMsg->queryType, pQueryMsg->window.skey, pQueryMsg->window.ekey, pQueryMsg->numOfGroupCols,
6246
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6247
         pQueryMsg->fillType, pQueryMsg->tsBuf.tsLen, pQueryMsg->tsBuf.tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6248

6249
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6250
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6251 6252

_cleanup:
6253
  freeParam(param);
6254
  return code;
6255 6256
}

H
Haojun Liao 已提交
6257 6258 6259 6260
  int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
    if (filterNum <= 0) {
      return TSDB_CODE_SUCCESS;
    }
D
dapan1121 已提交
6261

H
Haojun Liao 已提交
6262 6263 6264 6265
    *dst = calloc(filterNum, sizeof(*src));
    if (*dst == NULL) {
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
D
dapan1121 已提交
6266

H
Haojun Liao 已提交
6267
    memcpy(*dst, src, sizeof(*src) * filterNum);
D
dapan1121 已提交
6268

H
Haojun Liao 已提交
6269 6270 6271
    for (int32_t i = 0; i < filterNum; i++) {
      if ((*dst)[i].filterstr && dst[i]->len > 0) {
        void *pz = calloc(1, (size_t)(*dst)[i].len + 1);
D
dapan1121 已提交
6272

H
Haojun Liao 已提交
6273 6274 6275 6276 6277 6278
        if (pz == NULL) {
          if (i == 0) {
            free(*dst);
          } else {
            freeColumnFilterInfo(*dst, i);
          }
D
dapan1121 已提交
6279

H
Haojun Liao 已提交
6280 6281
          return TSDB_CODE_QRY_OUT_OF_MEMORY;
        }
D
dapan1121 已提交
6282

H
Haojun Liao 已提交
6283
        memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6284

H
Haojun Liao 已提交
6285 6286 6287
        (*dst)[i].pz = (int64_t)pz;
      }
    }
D
dapan1121 已提交
6288

H
Haojun Liao 已提交
6289 6290 6291
    return TSDB_CODE_SUCCESS;
  }

6292
int32_t buildArithmeticExprFromMsg(SExprInfo *pExprInfo, void *pQueryMsg) {
H
Haojun Liao 已提交
6293
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6294 6295

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6296
  TRY(TSDB_MAX_TAG_CONDITIONS) {
6297
    pExprNode = exprTreeFromBinary(pExprInfo->base.param[0].pz, pExprInfo->base.param[0].nLen);
weixin_48148422's avatar
weixin_48148422 已提交
6298 6299
  } CATCH( code ) {
    CLEANUP_EXECUTE();
6300
    qError("qmsg:%p failed to create arithmetic expression string from:%s, reason: %s", pQueryMsg, pExprInfo->base.param[0].pz, tstrerror(code));
weixin_48148422's avatar
weixin_48148422 已提交
6301 6302 6303
    return code;
  } END_TRY

H
hjxilinx 已提交
6304
  if (pExprNode == NULL) {
6305
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pExprInfo->base.param[0].pz);
6306
    return TSDB_CODE_QRY_APP_ERROR;
6307
  }
6308

6309
  pExprInfo->pExpr = pExprNode;
6310 6311 6312
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6313 6314

static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6315 6316 6317 6318
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int16_t functId = pExprs[i].base.functionId;

    if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
6319 6320
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
      if (j < 0 || j >= pTableInfo->numOfCols) {
H
Haojun Liao 已提交
6321 6322
        return TSDB_CODE_QRY_INVALID_MSG;
      } else {
H
Haojun Liao 已提交
6323 6324 6325
        SColumnInfo* pCol = &pTableInfo->colList[j];
        int32_t ret = getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.param[0].i64,
                                        &pExprs[i].base.resType, &pExprs[i].base.resBytes, &pExprs[i].base.interBytes, tagLen, superTable);
H
Haojun Liao 已提交
6326 6327 6328 6329 6330 6331 6332 6333
        assert(ret == TSDB_CODE_SUCCESS);
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6334
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6335 6336
int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo,
                        SSqlExpr** pExprMsg, SColumnInfo* pTagCols, int32_t queryType, void* pMsg) {
6337
  *pExprInfo = NULL;
H
hjxilinx 已提交
6338
  int32_t code = TSDB_CODE_SUCCESS;
6339

6340
  SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo));
6341
  if (pExprs == NULL) {
6342
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6343 6344
  }

H
Haojun Liao 已提交
6345
  bool    isSuperTable = QUERY_IS_STABLE_QUERY(queryType);
6346 6347
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6348
  for (int32_t i = 0; i < numOfOutput; ++i) {
6349
    pExprs[i].base = *pExprMsg[i];
6350 6351 6352 6353

    int16_t type = 0;
    int16_t bytes = 0;

6354
    // parse the arithmetic expression
6355
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6356
      code = buildArithmeticExprFromMsg(&pExprs[i], pMsg);
6357

6358
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6359
        tfree(pExprs);
6360
        return code;
6361 6362
      }

6363
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6364
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6365
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6366 6367 6368
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6369 6370 6371 6372
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
H
Haojun Liao 已提交
6373
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) {
6374
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6375 6376
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

H
Haojun Liao 已提交
6377 6378
      type = pExprs[i].base.param[1].nType;
      bytes = pExprs[i].base.param[1].nLen;
H
Haojun Liao 已提交
6379 6380 6381 6382
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
H
Haojun Liao 已提交
6383
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
6384
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
H
Haojun Liao 已提交
6385
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pTableInfo->numOfTags) {
6386 6387 6388
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      } else {
H
Haojun Liao 已提交
6389
        if (j < PRIMARYKEY_TIMESTAMP_COL_INDEX || j >= pTableInfo->numOfCols) {
6390 6391 6392
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      }
H
Haojun Liao 已提交
6393

dengyihao's avatar
dengyihao 已提交
6394
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6395
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j];
H
Haojun Liao 已提交
6396 6397 6398
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6399
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6400

6401 6402
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6403
      }
D
dapan1121 已提交
6404

6405 6406 6407
      if (pExprs[i].base.flist.numOfFilters > 0) {
        int32_t ret = cloneExprFilterInfo(&pExprs[i].base.flist.filterInfo, pExprMsg[i]->flist.filterInfo,
            pExprMsg[i]->flist.numOfFilters);
D
dapan1121 已提交
6408 6409 6410 6411
        if (ret) {
          return ret;
        }
      }
6412 6413
    }

H
Haojun Liao 已提交
6414
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
H
Haojun Liao 已提交
6415
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
H
Haojun Liao 已提交
6416
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6417 6418 6419 6420
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6421 6422
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].base.resType, &pExprs[i].base.resBytes,
                          &pExprs[i].base.interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6423
      tfree(pExprs);
6424
      return TSDB_CODE_QRY_INVALID_MSG;
6425 6426
    }

6427
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
H
Haojun Liao 已提交
6428
      tagLen += pExprs[i].base.resBytes;
6429
    }
6430

H
Haojun Liao 已提交
6431
    assert(isValidDataType(pExprs[i].base.resType));
6432 6433
  }

H
Haojun Liao 已提交
6434
  // the tag length is affected by other tag columns, so this should be update.
H
Haojun Liao 已提交
6435
  updateOutputBufForTopBotQuery(pTableInfo, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6436

6437
  *pExprInfo = pExprs;
6438 6439 6440
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6441 6442
int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                           SSqlExpr** pExpr, SExprInfo* prevExpr) {
H
Haojun Liao 已提交
6443 6444 6445 6446 6447 6448 6449 6450
  *pExprInfo = NULL;
  int32_t code = TSDB_CODE_SUCCESS;

  SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo));
  if (pExprs == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

H
Haojun Liao 已提交
6451
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6452 6453

  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
6454 6455
    pExprs[i].base = *pExpr[i];
    pExprs[i].base.resType = 0;
H
Haojun Liao 已提交
6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474

    int16_t type = 0;
    int16_t bytes = 0;

    // parse the arithmetic expression
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);

      if (code != TSDB_CODE_SUCCESS) {
        tfree(pExprs);
        return code;
      }

      type  = TSDB_DATA_TYPE_DOUBLE;
      bytes = tDataTypes[type].bytes;
    } else {
      int32_t index = pExprs[i].base.colInfo.colIndex;
      assert(prevExpr[index].base.resColId == pExprs[i].base.colInfo.colId);

H
Haojun Liao 已提交
6475 6476
      type  = prevExpr[index].base.resType;
      bytes = prevExpr[index].base.resBytes;
H
Haojun Liao 已提交
6477 6478
    }

H
Haojun Liao 已提交
6479 6480 6481
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].base.resType, &pExprs[i].base.resBytes,
                          &pExprs[i].base.interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
6482 6483 6484 6485
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6486
    assert(isValidDataType(pExprs[i].base.resType));
H
Haojun Liao 已提交
6487 6488 6489 6490 6491 6492
  }

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6493
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6494 6495 6496 6497 6498
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6499
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6500
  if (pGroupbyExpr == NULL) {
6501
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6502 6503 6504 6505 6506 6507 6508
    return NULL;
  }

  pGroupbyExpr->numOfGroupCols = pQueryMsg->numOfGroupCols;
  pGroupbyExpr->orderType = pQueryMsg->orderType;
  pGroupbyExpr->orderIndex = pQueryMsg->orderByIdx;

6509 6510 6511 6512
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6513

6514 6515 6516
  return pGroupbyExpr;
}

6517 6518 6519 6520
static int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols,
                                  SSingleColumnFilterInfo** pFilterInfo, uint64_t qId) {
  *pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * numOfFilterCols);
  if (pFilterInfo == NULL) {
H
Haojun Liao 已提交
6521 6522
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6523

6524 6525 6526
  for (int32_t i = 0, j = 0; i < numOfCols; ++i) {
    if (pCols[i].flist.numOfFilters > 0) {
      SSingleColumnFilterInfo* pFilter = &((*pFilterInfo)[j]);
6527

6528 6529
      memcpy(&pFilter->info, &pCols[i], sizeof(SColumnInfo));
      pFilter->info = pCols[i];
6530

6531 6532 6533
      pFilter->numOfFilters = pCols[i].flist.numOfFilters;
      pFilter->pFilters = calloc(pFilter->numOfFilters, sizeof(SColumnFilterElem));
      if (pFilter->pFilters == NULL) {
H
Haojun Liao 已提交
6534 6535
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6536

6537 6538 6539
      for (int32_t f = 0; f < pFilter->numOfFilters; ++f) {
        SColumnFilterElem* pSingleColFilter = &pFilter->pFilters[f];
        pSingleColFilter->filterInfo = pCols[i].flist.filterInfo[f];
6540 6541 6542 6543

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
6544
          qError("QInfo:%" PRIu64 " invalid filter info", qId);
6545
          return TSDB_CODE_QRY_INVALID_MSG;
6546 6547
        }

6548 6549
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
6550
          qError("QInfo:%" PRIu64 " invalid filter info", qId);
6551
          return TSDB_CODE_QRY_INVALID_MSG;
6552 6553
        }

6554
        pSingleColFilter->bytes = pCols[i].bytes;
6555 6556 6557 6558 6559 6560 6561 6562 6563
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591
void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) {
  for (int32_t i = 0; i < numOfFilterCols; ++i) {
    if (pFilterInfo[i].numOfFilters > 0) {
      tfree(pFilterInfo[i].pFilters);
    }
  }

  tfree(pFilterInfo);
  return NULL;
}

static int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) {
  for (int32_t i = 0; i < pQueryAttr->numOfCols; ++i) {
    if (pQueryAttr->tableCols[i].flist.numOfFilters > 0) {
      pQueryAttr->numOfFilterCols++;
    }
  }

  if (pQueryAttr->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  doCreateFilterInfo(pQueryAttr->tableCols, pQueryAttr->numOfCols, pQueryAttr->numOfFilterCols,
                     &pQueryAttr->pFilterInfo, qId);

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6592 6593
static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) {
  assert(pQueryAttr->pExpr1 != NULL && pQueryAttr != NULL);
6594

H
Haojun Liao 已提交
6595 6596
  for (int32_t k = 0; k < pQueryAttr->numOfOutput; ++k) {
    SSqlExpr *pSqlExprMsg = &pQueryAttr->pExpr1[k].base;
6597
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6598 6599
      continue;
    }
6600

6601
    // todo opt performance
H
Haojun Liao 已提交
6602
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6603
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6604
      int32_t f = 0;
H
Haojun Liao 已提交
6605
      for (f = 0; f < pQueryAttr->numOfCols; ++f) {
H
Haojun Liao 已提交
6606
        if (pColIndex->colId == pQueryAttr->tableCols[f].colId) {
H
Haojun Liao 已提交
6607
          pColIndex->colIndex = f;
6608 6609 6610
          break;
        }
      }
H
Haojun Liao 已提交
6611

H
Haojun Liao 已提交
6612
      assert(f < pQueryAttr->numOfCols);
6613 6614
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6615 6616
    } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      pColIndex->colIndex = 0;// only one source column, so it must be 0;
H
Haojun Liao 已提交
6617
      assert(pQueryAttr->numOfOutput == 1);
6618
    } else {
6619
      int32_t f = 0;
H
Haojun Liao 已提交
6620 6621
      for (f = 0; f < pQueryAttr->numOfTags; ++f) {
        if (pColIndex->colId == pQueryAttr->tagColList[f].colId) {
H
Haojun Liao 已提交
6622
          pColIndex->colIndex = f;
6623 6624
          break;
        }
6625
      }
6626

H
Haojun Liao 已提交
6627
      assert(f < pQueryAttr->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6628 6629 6630 6631
    }
  }
}

H
Haojun Liao 已提交
6632
void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo) {
H
Haojun Liao 已提交
6633 6634 6635 6636 6637 6638 6639
  const int32_t DEFAULT_RESULT_MSG_SIZE = 1024 * (1024 + 512);

  // the minimum number of rows for projection query
  const int32_t MIN_ROWS_FOR_PRJ_QUERY = 8192;
  const int32_t DEFAULT_MIN_ROWS = 4096;

  const float THRESHOLD_RATIO = 0.85f;
H
Haojun Liao 已提交
6640

H
Haojun Liao 已提交
6641 6642
  if (isProjQuery(pQueryAttr)) {
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQueryAttr->resultRowSize;
H
Haojun Liao 已提交
6643 6644
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6645
    }
H
Haojun Liao 已提交
6646

H
Haojun Liao 已提交
6647
    pResultInfo->capacity  = numOfRes;
6648
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6649
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6650
  }
H
Haojun Liao 已提交
6651 6652 6653

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
  pResultInfo->total = 0;
H
Haojun Liao 已提交
6654 6655
}

D
fix bug  
dapan1121 已提交
6656 6657 6658 6659
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6660
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
H
Haojun Liao 已提交
6661
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId,
D
dapan1121 已提交
6662
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6663 6664 6665
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6666 6667
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6668
    goto _cleanup_qinfo;
6669
  }
6670

D
dapan1121 已提交
6671 6672
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6673 6674
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709
  SQueryAttr* pQueryAttr = &pQInfo->query;
  pQInfo->runtimeEnv.pQueryAttr = pQueryAttr;

  pQueryAttr->tableGroupInfo  = *pTableGroupInfo;
  pQueryAttr->numOfCols       = numOfCols;
  pQueryAttr->numOfOutput     = numOfOutput;
  pQueryAttr->limit.limit     = pQueryMsg->limit;
  pQueryAttr->limit.offset    = pQueryMsg->offset;
  pQueryAttr->order.order     = pQueryMsg->order;
  pQueryAttr->order.orderColId = pQueryMsg->orderColId;
  pQueryAttr->pExpr1          = pExprs;
  pQueryAttr->pExpr2          = pSecExprs;
  pQueryAttr->numOfExpr2      = pQueryMsg->secondStageOutput;
  pQueryAttr->pGroupbyExpr    = pGroupbyExpr;
  memcpy(&pQueryAttr->interval, &pQueryMsg->interval, sizeof(pQueryAttr->interval));
  pQueryAttr->fillType        = pQueryMsg->fillType;
  pQueryAttr->numOfTags       = pQueryMsg->numOfTags;
  pQueryAttr->tagColList      = pTagCols;
  pQueryAttr->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQueryAttr->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
  pQueryAttr->sw              = pQueryMsg->sw;

  pQueryAttr->stableQuery     = pQueryMsg->stableQuery;
  pQueryAttr->topBotQuery     = pQueryMsg->topBotQuery;
  pQueryAttr->groupbyColumn   = pQueryMsg->groupbyColumn;
  pQueryAttr->hasTagResults   = pQueryMsg->hasTagResults;
  pQueryAttr->timeWindowInterpo = pQueryMsg->timeWindowInterpo;
  pQueryAttr->queryBlockDist  = pQueryMsg->queryBlockDist;
  pQueryAttr->stabledev       = pQueryMsg->stabledev;
  pQueryAttr->tsCompQuery     = pQueryMsg->tsCompQuery;
  pQueryAttr->simpleAgg       = pQueryMsg->simpleAgg;
  pQueryAttr->pointInterpQuery = pQueryMsg->pointInterpQuery;
  pQueryAttr->needReverseScan  = pQueryMsg->needReverseScan;
  pQueryAttr->vgId            = vgId;

H
Haojun Liao 已提交
6710 6711
  pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
  if (pQueryAttr->tableCols == NULL) {
6712
    goto _cleanup;
6713
  }
6714

H
Haojun Liao 已提交
6715 6716
  pQueryAttr->srcRowSize = 0;
  pQueryAttr->maxTableColumnWidth = 0;
H
hjxilinx 已提交
6717
  for (int16_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
6718
    pQueryAttr->tableCols[i] = pQueryMsg->tableCols[i];
6719
    pQueryAttr->tableCols[i].flist.filterInfo = tFilterInfoDup(pQueryMsg->tableCols[i].flist.filterInfo, pQueryAttr->tableCols[i].flist.numOfFilters);
6720

H
Haojun Liao 已提交
6721 6722 6723
    pQueryAttr->srcRowSize += pQueryAttr->tableCols[i].bytes;
    if (pQueryAttr->maxTableColumnWidth < pQueryAttr->tableCols[i].bytes) {
      pQueryAttr->maxTableColumnWidth = pQueryAttr->tableCols[i].bytes;
6724
    }
H
hjxilinx 已提交
6725
  }
6726

6727
  // calculate the result row size
6728
  for (int16_t col = 0; col < numOfOutput; ++col) {
H
Haojun Liao 已提交
6729
    assert(pExprs[col].base.resBytes > 0);
H
Haojun Liao 已提交
6730
    pQueryAttr->resultRowSize += pExprs[col].base.resBytes;
6731 6732 6733

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
H
Haojun Liao 已提交
6734
      pQueryAttr->tagLen += pExprs[col].base.resBytes;
6735
    }
D
dapan1121 已提交
6736

6737
    if (pExprs[col].base.flist.filterInfo) {
H
Haojun Liao 已提交
6738
      ++pQueryAttr->havingNum;
D
dapan1121 已提交
6739
    }
6740
  }
6741

H
Haojun Liao 已提交
6742
  doUpdateExprColumnIndex(pQueryAttr);
H
Haojun Liao 已提交
6743
  int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId);
6744
  if (ret != TSDB_CODE_SUCCESS) {
6745
    goto _cleanup;
6746 6747
  }

H
Haojun Liao 已提交
6748 6749 6750
  if (pQueryAttr->fillType != TSDB_FILL_NONE) {
    pQueryAttr->fillVal = malloc(sizeof(int64_t) * pQueryAttr->numOfOutput);
    if (pQueryAttr->fillVal == NULL) {
6751
      goto _cleanup;
6752 6753 6754
    }

    // the first column is the timestamp
H
Haojun Liao 已提交
6755
    memcpy(pQueryAttr->fillVal, (char *)pQueryMsg->fillVal, pQueryAttr->numOfOutput * sizeof(int64_t));
6756 6757
  }

dengyihao's avatar
dengyihao 已提交
6758 6759 6760
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6761
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6762

6763 6764 6765
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6766
  }
H
Haojun Liao 已提交
6767

H
Haojun Liao 已提交
6768
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6769 6770 6771 6772
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6773
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6774
  pQInfo->rspContext = NULL;
6775
  pQInfo->sql = sql;
6776
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6777
  tsem_init(&pQInfo->ready, 0, 0);
6778

H
Haojun Liao 已提交
6779 6780
  pQueryAttr->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, pQueryAttr->stableQuery);
6781

H
Haojun Liao 已提交
6782
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6783
  STimeWindow window = pQueryAttr->window;
H
Haojun Liao 已提交
6784

H
Haojun Liao 已提交
6785
  int32_t index = 0;
H
hjxilinx 已提交
6786
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6787
    SArray* pa = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
6788

H
Haojun Liao 已提交
6789
    size_t s = taosArrayGetSize(pa);
6790
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6791 6792 6793
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6794

H
Haojun Liao 已提交
6795
    taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1);
6796

H
hjxilinx 已提交
6797
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6798
      STableKeyInfo* info = taosArrayGet(pa, j);
6799
      window.skey = info->lastKey;
6800 6801

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
H
Haojun Liao 已提交
6802
      STableQueryInfo* item = createTableQueryInfo(pQueryAttr, info->pTable, pQueryAttr->groupbyColumn, window, buf);
B
Bomin Zhang 已提交
6803 6804 6805
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6806

6807
      item->groupIndex = i;
H
hjxilinx 已提交
6808
      taosArrayPush(p1, &item);
6809 6810

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6811
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6812
      index += 1;
H
hjxilinx 已提交
6813 6814
    }
  }
6815

H
Haojun Liao 已提交
6816
  colIdCheck(pQueryAttr, pQInfo->qId);
6817

6818
  // todo refactor
H
Haojun Liao 已提交
6819
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6820

D
fix bug  
dapan1121 已提交
6821
  qDebug("qmsg:%p QInfo:%" PRIu64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6822 6823
  return pQInfo;

B
Bomin Zhang 已提交
6824
_cleanup_qinfo:
H
Haojun Liao 已提交
6825
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6826

6827 6828 6829 6830
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6831

S
TD-1848  
Shengliang Guan 已提交
6832
  tfree(pTagCols);
B
Bomin Zhang 已提交
6833 6834 6835
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6836 6837
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6838
    }
D
dapan1121 已提交
6839

6840 6841
    if (pExprInfo->base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo->base.flist.filterInfo, pExprInfo->base.flist.numOfFilters);
D
dapan1121 已提交
6842
    }
B
Bomin Zhang 已提交
6843
  }
H
Haojun Liao 已提交
6844

S
TD-1848  
Shengliang Guan 已提交
6845
  tfree(pExprs);
B
Bomin Zhang 已提交
6846

6847
_cleanup:
dengyihao's avatar
dengyihao 已提交
6848
  freeQInfo(pQInfo);
6849 6850 6851
  return NULL;
}

H
Haojun Liao 已提交
6852
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6853 6854 6855 6856
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6857

H
hjxilinx 已提交
6858 6859 6860 6861
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6862
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6863 6864 6865
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6866
int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start,
H
Haojun Liao 已提交
6867
                  int32_t prevResultLen, void* merger) {
H
hjxilinx 已提交
6868
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6869 6870

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6871 6872
  pRuntimeEnv->qinfo = pQInfo;

H
Haojun Liao 已提交
6873
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
6874

6875
  STSBuf *pTsBuf = NULL;
H
Haojun Liao 已提交
6876 6877
  if (pTsBufInfo->tsLen > 0) { // open new file to save the result
    char *tsBlock = start + pTsBufInfo->tsOffset;
H
Haojun Liao 已提交
6878
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pTsBufInfo->tsNumOfBlocks, pTsBufInfo->tsLen, pTsBufInfo->tsOrder,
H
Haojun Liao 已提交
6879
        pQueryAttr->vgId);
6880

6881 6882
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
dengyihao's avatar
dengyihao 已提交
6883
    UNUSED(ret);
H
hjxilinx 已提交
6884
  }
6885

6886
  SArray* prevResult = NULL;
H
Haojun Liao 已提交
6887 6888
  if (prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, prevResultLen);
6889 6890
  }

H
Haojun Liao 已提交
6891
  if (tsdb != NULL) {
H
Haojun Liao 已提交
6892
    pQueryAttr->precision = tsdbGetCfg(tsdb)->precision;
H
Haojun Liao 已提交
6893
  }
6894

H
Haojun Liao 已提交
6895 6896
  if ((QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.skey > pQueryAttr->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.ekey > pQueryAttr->window.skey))) {
H
Haojun Liao 已提交
6897
    qDebug("QInfo:%"PRIu64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQueryAttr->window.skey,
H
Haojun Liao 已提交
6898
           pQueryAttr->window.ekey, pQueryAttr->order.order);
H
Haojun Liao 已提交
6899
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6900
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6901
    // todo free memory
6902 6903
    return TSDB_CODE_SUCCESS;
  }
6904

H
Haojun Liao 已提交
6905
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
6906
    qDebug("QInfo:%"PRIu64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
6907
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6908 6909
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6910 6911

  // filter the qualified
H
Haojun Liao 已提交
6912
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, sourceOptr, param->tableScanOperator, param->pOperator, merger)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6913 6914
    goto _error;
  }
6915

H
hjxilinx 已提交
6916 6917 6918 6919
  return code;

_error:
  // table query ref will be decrease during error handling
6920
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6921 6922 6923
  return code;
}

6924
//TODO refactor
H
Haojun Liao 已提交
6925
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6926
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6927 6928
      return;
    }
H
Haojun Liao 已提交
6929

B
Bomin Zhang 已提交
6930
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
6931
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
6932 6933 6934
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6935

B
Bomin Zhang 已提交
6936 6937 6938
    free(pFilter);
}

H
Haojun Liao 已提交
6939 6940
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6941
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962
    for (int32_t i = 0; i < numOfGroups; ++i) {
      SArray *p = taosArrayGetP(pTableqinfoGroupInfo->pGroupList, i);

      size_t num = taosArrayGetSize(p);
      for(int32_t j = 0; j < num; ++j) {
        STableQueryInfo* item = taosArrayGetP(p, j);
        destroyTableQueryInfoImpl(item);
      }

      taosArrayDestroy(p);
    }
  }

  taosArrayDestroy(pTableqinfoGroupInfo->pGroupList);
  taosHashCleanup(pTableqinfoGroupInfo->map);

  pTableqinfoGroupInfo->pGroupList = NULL;
  pTableqinfoGroupInfo->map = NULL;
  pTableqinfoGroupInfo->numOfTables = 0;
}

H
Haojun Liao 已提交
6963 6964 6965 6966 6967 6968 6969 6970
static void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr) {
  if (pExprInfo == NULL) {
    assert(numOfExpr == 0);
    return NULL;
  }

  for (int32_t i = 0; i < numOfExpr; ++i) {
    if (pExprInfo[i].pExpr != NULL) {
H
Haojun Liao 已提交
6971
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6972
    }
D
dapan1121 已提交
6973

6974 6975
    if (pExprInfo[i].base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo[i].base.flist.filterInfo, pExprInfo[i].base.flist.numOfFilters);
D
dapan1121 已提交
6976
    }
H
Haojun Liao 已提交
6977 6978 6979 6980 6981 6982
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6983
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6984 6985 6986
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6987

H
Haojun Liao 已提交
6988
  qDebug("QInfo:%"PRIu64" start to free QInfo", pQInfo->qId);
6989

H
Haojun Liao 已提交
6990
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6991
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
6992 6993 6994

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);

6995
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6996

H
Haojun Liao 已提交
6997 6998 6999 7000
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
  if (pQueryAttr != NULL) {
    if (pQueryAttr->fillVal != NULL) {
      tfree(pQueryAttr->fillVal);
H
Haojun Liao 已提交
7001
    }
7002

7003
    pQueryAttr->pFilterInfo = doDestroyFilterInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols);
7004

H
Haojun Liao 已提交
7005 7006
    pQueryAttr->pExpr1 = destroyQueryFuncExpr(pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
    pQueryAttr->pExpr2 = destroyQueryFuncExpr(pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
7007
    pQueryAttr->pExpr3 = destroyQueryFuncExpr(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
7008

H
Haojun Liao 已提交
7009
    tfree(pQueryAttr->tagColList);
H
Haojun Liao 已提交
7010

H
Haojun Liao 已提交
7011
    if (pQueryAttr->tableCols != NULL) {
H
Haojun Liao 已提交
7012
      for (int32_t i = 0; i < pQueryAttr->numOfCols; i++) {
H
Haojun Liao 已提交
7013
        SColumnInfo *column = pQueryAttr->tableCols + i;
7014
        freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters);
H
Haojun Liao 已提交
7015
      }
H
Haojun Liao 已提交
7016
      tfree(pQueryAttr->tableCols);
H
Haojun Liao 已提交
7017 7018
    }

H
Haojun Liao 已提交
7019 7020 7021
    if (pQueryAttr->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo);
      tfree(pQueryAttr->pGroupbyExpr);
H
Haojun Liao 已提交
7022
    }
H
hjxilinx 已提交
7023
  }
7024

7025 7026
  tsdbDestroyTableGroup(&pQueryAttr->tableGroupInfo);

H
Haojun Liao 已提交
7027

S
TD-1848  
Shengliang Guan 已提交
7028
  tfree(pQInfo->pBuf);
7029 7030
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
7031
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
7032
  pQInfo->signature = 0;
7033

H
Haojun Liao 已提交
7034
  qDebug("QInfo:%"PRIu64" QInfo is freed", pQInfo->qId);
7035

S
TD-1848  
Shengliang Guan 已提交
7036
  tfree(pQInfo);
H
hjxilinx 已提交
7037 7038
}

H
Haojun Liao 已提交
7039
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
7040
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
7041
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7042
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
7043

H
hjxilinx 已提交
7044
  // load data from file to msg buffer
H
Haojun Liao 已提交
7045
  if (pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
7046 7047
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
7048

H
hjxilinx 已提交
7049
    // make sure file exist
D
fix bug  
dapan1121 已提交
7050 7051
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
7052
      assert(s == pRuntimeEnv->outputBuf->info.rows);
7053

H
Haojun Liao 已提交
7054
      qDebug("QInfo:%"PRIu64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
7055 7056
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
7057
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
7058
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
7059 7060
          assert(0);
        }
H
Haojun Liao 已提交
7061
      } else {
7062
        UNUSED(s);
D
dapan1121 已提交
7063 7064 7065 7066
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
7067
      // dump error info
D
dapan1121 已提交
7068 7069 7070
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
7071
      }
H
Haojun Liao 已提交
7072

D
fix bug  
dapan1121 已提交
7073
      fclose(f);
D
dapan1121 已提交
7074
      *(FILE **)pColInfoData->pData = NULL;
H
hjxilinx 已提交
7075
    }
7076

H
hjxilinx 已提交
7077
    // all data returned, set query over
H
Haojun Liao 已提交
7078 7079
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
7080
    }
H
hjxilinx 已提交
7081
  } else {
H
Haojun Liao 已提交
7082
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
7083
  }
7084

H
Haojun Liao 已提交
7085
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
7086
  qDebug("QInfo:%"PRIu64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
7087
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
7088

H
Haojun Liao 已提交
7089
  if (pQueryAttr->limit.limit > 0 && pQueryAttr->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
7090
    qDebug("QInfo:%"PRIu64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQueryAttr->limit.limit);
H
Haojun Liao 已提交
7091
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
7092
  }
7093

H
hjxilinx 已提交
7094
  return TSDB_CODE_SUCCESS;
7095 7096
}

H
Haojun Liao 已提交
7097
bool doBuildResCheck(SQInfo* pQInfo) {
7098 7099 7100 7101 7102
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
7103
  buildRes = needBuildResAfterQueryComplete(pQInfo);
7104

H
Haojun Liao 已提交
7105 7106
  // clear qhandle owner, it must be in the secure area. other thread may run ahead before current, after it is
  // put into task to be executed.
S
TD-2616  
Shengliang Guan 已提交
7107
  assert(pQInfo->owner == taosGetSelfPthreadId());
7108
  pQInfo->owner = 0;
H
Haojun Liao 已提交
7109

H
Haojun Liao 已提交
7110
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
7111

7112
  // used in retrieve blocking model.
H
Haojun Liao 已提交
7113
  tsem_post(&pQInfo->ready);
7114 7115 7116
  return buildRes;
}

H
Haojun Liao 已提交
7117 7118 7119 7120
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
7121 7122
  }

7123 7124 7125
  if (IS_VAR_DATA_TYPE(type)) {
    // Binary data overflows for sort of unknown reasons. Let trim the overflow data
    if (varDataTLen(val) > bytes) {
H
Haojun Liao 已提交
7126
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
7127 7128 7129 7130 7131
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
7132
  } else {
H
Haojun Liao 已提交
7133
    memcpy(output, val, bytes);
7134 7135 7136
  }
}

H
Haojun Liao 已提交
7137
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
7138 7139 7140 7141
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
7142
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
7143 7144
}

H
Haojun Liao 已提交
7145
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
7146
  int64_t t = getQuerySupportBufSize(numOfTables);
7147
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7148
    return TSDB_CODE_SUCCESS;
7149
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
7150 7151

    while(1) {
7152
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
7153 7154
      int64_t remain = s - t;
      if (remain >= 0) {
7155
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167
          return TSDB_CODE_SUCCESS;
        }
      } else {
        return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER;
      }
    }
  }

  // disable query processing if the value of tsQueryBufferSize is zero.
  return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER;
}

H
Haojun Liao 已提交
7168
void releaseQueryBuf(size_t numOfTables) {
7169
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7170 7171 7172 7173 7174 7175
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
7176
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
7177
}
7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197

void freeQueryAttr(SQueryAttr* pQueryAttr) {
  if (pQueryAttr != NULL) {
    if (pQueryAttr->fillVal != NULL) {
      tfree(pQueryAttr->fillVal);
    }

    for (int32_t i = 0; i < pQueryAttr->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo* pColFilter = &pQueryAttr->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
        tfree(pColFilter->pFilters);
      }
    }

    pQueryAttr->pExpr1 = destroyQueryFuncExpr(pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
    pQueryAttr->pExpr2 = destroyQueryFuncExpr(pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);

    tfree(pQueryAttr->tagColList);
    tfree(pQueryAttr->pFilterInfo);

H
Haojun Liao 已提交
7198
    if (pQueryAttr->tableCols != NULL) {
7199
      for (int32_t i = 0; i < pQueryAttr->numOfCols; i++) {
H
Haojun Liao 已提交
7200
        SColumnInfo* column = pQueryAttr->tableCols + i;
7201
        freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters);
7202
      }
H
Haojun Liao 已提交
7203
      tfree(pQueryAttr->tableCols);
7204 7205 7206 7207 7208 7209 7210 7211 7212
    }

    if (pQueryAttr->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo);
      tfree(pQueryAttr->pGroupbyExpr);
    }
  }
}