qExecutor.c 255.6 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
  int32_t numOfOperator = (int32_t) taosArrayGetSize(pOperator);
H
Haojun Liao 已提交
1700 1701 1702 1703 1704
  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

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

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

H
Haojun Liao 已提交
1888
bool isQueryKilled(SQInfo *pQInfo) {
1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
  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 已提交
1899 1900
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1901 1902 1903 1904 1905 1906
    return true;
  }

  return false;
}

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

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

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

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

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

1960 1961 1962
  return false;
}

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

1971 1972 1973
  return false;
}

H
Haojun Liao 已提交
1974 1975 1976 1977
/**
 * 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 已提交
1978 1979 1980
bool onlyQueryTags(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pQueryAttr->pExpr1[i];
H
Haojun Liao 已提交
1981 1982

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

    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 已提交
1987
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
1988 1989 1990
      return false;
    }
  }
1991

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

1995 1996
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
1997 1998 1999
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 已提交
2000 2001

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

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

2027 2028 2029 2030 2031
  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 已提交
2032 2033 2034
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;
2035

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

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

2046 2047 2048
  return true;
}

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

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

H
Haojun Liao 已提交
2053
static int32_t updateBlockLoadStatus(SQueryAttr *pQuery, int32_t status) {
H
Haojun Liao 已提交
2054 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
  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;
}

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

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

2097 2098 2099 2100
      // 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 已提交
2101 2102 2103 2104
    }
  }
}

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

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

2112 2113
  // 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 已提交
2114
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
2115 2116
    qDebug("QInfo:%"PRIu64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId,
        pQueryAttr->order.order, TSDB_ORDER_ASC);
2117

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

2123 2124
    return;
  }
2125

H
Haojun Liao 已提交
2126 2127 2128 2129
  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 已提交
2130
    }
H
Haojun Liao 已提交
2131

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

H
Haojun Liao 已提交
2136 2137 2138 2139
  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 已提交
2140
    }
2141

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

H
Haojun Liao 已提交
2146 2147 2148 2149 2150
  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);
2151

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

H
Haojun Liao 已提交
2156 2157 2158 2159 2160
      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);
2161

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

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

2169
  } else {  // interval query
2170
    if (stableQuery) {
H
Haojun Liao 已提交
2171 2172 2173 2174
      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);
2175

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

H
Haojun Liao 已提交
2180 2181 2182 2183 2184
        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);
2185

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2254 2255
      continue;
    }
2256

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

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

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

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

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

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

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

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

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

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

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

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

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

  return false;
}

H
Haojun Liao 已提交
2329 2330 2331 2332 2333
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 已提交
2334
         elem.ts, key, elem.tag.i64, pQueryAttr->order.order, pRuntimeEnv->pTsBuf->tsOrder,
H
Haojun Liao 已提交
2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353
         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;
}
2354

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

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

H
Haojun Liao 已提交
2362
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382
    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 已提交
2383 2384

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

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

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

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

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

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

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

  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 已提交
2445
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2446 2447 2448
          }

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

2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
    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 已提交
2467 2468 2469 2470
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

    if (start > 0) {
H
Haojun Liao 已提交
2471
      SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
2472 2473 2474 2475 2476
      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 已提交
2477 2478 2479 2480 2481 2482
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2483 2484 2485
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 已提交
2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
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;
}

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

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

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

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

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

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

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

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

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

      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 已提交
2554 2555 2556
    }
  }

H
Haojun Liao 已提交
2557 2558
  // 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 已提交
2559 2560
  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 ||
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) {
H
Haojun Liao 已提交
2561 2562
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2563

H
Haojun Liao 已提交
2564 2565 2566 2567
  // 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 已提交
2568
    if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2569
      SResultRow* pResult = NULL;
H
Haojun Liao 已提交
2570

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

H
Haojun Liao 已提交
2574
      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2575 2576 2577 2578
      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 已提交
2579
      }
H
Haojun Liao 已提交
2580
    } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
2581 2582
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
H
Haojun Liao 已提交
2583
                               pRuntimeEnv->current->groupIndex);
H
Haojun Liao 已提交
2584
    }
H
Haojun Liao 已提交
2585 2586

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

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

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

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

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

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

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

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

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

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

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

  return TSDB_CODE_SUCCESS;
}

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

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

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

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

2684
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2685 2686 2687 2688 2689
    // 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;
2690

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

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

H
hjxilinx 已提交
2703 2704 2705 2706 2707
  } 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;
2708

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

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

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

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

H
Haojun Liao 已提交
2733 2734 2735 2736 2737 2738
/*
 * 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);
2739

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

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

H
Haojun Liao 已提交
2753
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2754 2755 2756 2757
    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 已提交
2758 2759
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2760
  }
2761 2762
}

2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774
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 已提交
2775
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2776
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2777

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

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

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

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

H
Haojun Liao 已提交
2795 2796 2797 2798 2799 2800 2801 2802 2803
    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 已提交
2804 2805
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resType,
                           pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2806

H
Haojun Liao 已提交
2807 2808
      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 已提交
2809
      } else {
2810
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2811 2812
      }

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

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

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

2828
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2829 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
  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);
  }
}

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

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

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

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

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2936
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2937 2938 2939
    // 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 已提交
2940
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2941 2942 2943 2944
        return;
      }
    }

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

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

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

H
Haojun Liao 已提交
2961 2962
}

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

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

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

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

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

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

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

H
Haojun Liao 已提交
2991 2992 2993 2994
      // 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 已提交
2995

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

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

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

H
Haojun Liao 已提交
3014 3015 3016 3017 3018 3019 3020 3021
/*
 * 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 已提交
3022
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid, int32_t stage) {
H
Haojun Liao 已提交
3023 3024 3025 3026 3027
  SQLFunctionCtx* pCtx           = pInfo->pCtx;
  SSDataBlock* pDataBlock        = pInfo->pRes;
  int32_t* rowCellInfoOffset     = pInfo->rowCellInfoOffset;
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;

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

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

H
Haojun Liao 已提交
3034 3035 3036 3037 3038 3039 3040
    /*
     * 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 已提交
3041 3042 3043
    pCtx[i].resultInfo   = pCellInfo;
    pCtx[i].pOutput      = pData->pData;
    pCtx[i].currentStage = stage;
H
Haojun Liao 已提交
3044
    assert(pCtx[i].pOutput != NULL);
3045

H
Haojun Liao 已提交
3046 3047 3048 3049 3050
    // 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;
    }
3051
  }
3052

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

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

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

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

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

H
Haojun Liao 已提交
3077 3078 3079
  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;
3080

H
Haojun Liao 已提交
3081 3082 3083 3084
    // 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 已提交
3085
    }
H
Haojun Liao 已提交
3086 3087
  }
}
3088

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

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

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

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

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

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

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

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

  setupQueryRangeForReverseScan(pRuntimeEnv);
3129 3130
}

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

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

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

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

      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 已提交
3158
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3159 3160 3161 3162 3163 3164 3165 3166 3167
    }

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

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

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

3177 3178 3179
  return false;
}

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

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

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

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

3199 3200 3201
  return pTableQueryInfo;
}

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

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

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

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

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

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

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

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

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

3247 3248 3249 3250 3251
  /*
   * 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 已提交
3252
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
3253
    if (ret != TSDB_CODE_SUCCESS) {
3254
      return;
3255 3256 3257
    }
  }

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

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

  // 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);

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

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

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

3287 3288 3289
    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;
3290 3291
    }

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

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

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

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

    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 已提交
3317
             pExprInfo->base.param[0].i64, pCtx[0].tag.pz);
H
Haojun Liao 已提交
3318 3319
    } else {
      qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pRuntimeEnv->qinfo,
H
Haojun Liao 已提交
3320
             pExprInfo->base.param[0].i64, pCtx[0].tag.i64);
H
Haojun Liao 已提交
3321 3322 3323 3324 3325
    }
  }
}

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

H
Haojun Liao 已提交
3328 3329 3330 3331 3332 3333
  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 已提交
3334
    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQueryAttr->vgId, &pTableQueryInfo->tag);
H
Haojun Liao 已提交
3335 3336 3337 3338

    // 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 已提交
3339
        qError("QInfo:%"PRIu64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3340
      } else {
H
Haojun Liao 已提交
3341
        qError("QInfo:%"PRIu64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3342 3343 3344 3345 3346 3347 3348 3349
      }

      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 已提交
3350
      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 已提交
3351
    } else {
H
Haojun Liao 已提交
3352
      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 已提交
3353 3354 3355 3356 3357
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3358
      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 已提交
3359
    } else {
H
Haojun Liao 已提交
3360
      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 已提交
3361
    }
H
Haojun Liao 已提交
3362 3363
  }

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

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

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

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

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

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

}
3400

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

H
Haojun Liao 已提交
3404
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3405 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
  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 已提交
3431

3432 3433 3434
/*
 * There are two cases to handle:
 *
H
Haojun Liao 已提交
3435 3436
 * 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.
3437 3438 3439 3440
 * 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 已提交
3441
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3442
  SQueryAttr           *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3443
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
3444
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3445

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

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

H
Haojun Liao 已提交
3453 3454 3455 3456 3457 3458
  /**
   * 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 已提交
3459
  STimeWindow w = TSWINDOW_INITIALIZER;
3460

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

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

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

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

/**
H
Haojun Liao 已提交
3477
 * copyToOutputBuf support copy data in ascending/descending order
3478 3479 3480 3481 3482 3483 3484
 * 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 已提交
3485

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

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

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3495
  qDebug("QInfo:%"PRIu64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515
  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 已提交
3516 3517

    int16_t offset = 0;
H
Haojun Liao 已提交
3518 3519 3520 3521 3522
    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 已提交
3523
      char *in  = getPosInResultPage(pQueryAttr, page, pRow->offset, offset);
H
Haojun Liao 已提交
3524
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3525 3526

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
3633
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3634 3635 3636 3637 3638 3639
  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 已提交
3640
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3641
  tfree(p);
H
Haojun Liao 已提交
3642 3643
  return pOutput->info.rows;
}
3644

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

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

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

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

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

H
Haojun Liao 已提交
3670
  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 已提交
3671
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3672 3673
}

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

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

3749
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
H
Haojun Liao 已提交
3750
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3751 3752
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
H
Haojun Liao 已提交
3753
//  assert(pQueryAttr->limit.offset == 0);
3754
//  STimeWindow tw = *win;
H
Haojun Liao 已提交
3755
//  getNextTimeWindow(pQueryAttr, &tw);
3756
//
H
Haojun Liao 已提交
3757 3758
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
3759 3760 3761 3762 3763 3764 3765 3766
//
//    // 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 已提交
3767
//        getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
3768 3769 3770
//    assert(startPos >= 0);
//
//    // set the abort info
H
Haojun Liao 已提交
3771
//    pQueryAttr->pos = startPos;
3772 3773 3774
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
H
Haojun Liao 已提交
3775
//    pQueryAttr->window.skey = pTableQueryInfo->win.skey;
3776 3777 3778 3779 3780 3781 3782 3783
//    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 已提交
3784 3785
//    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 已提交
3786
//           pQueryAttr->current->lastKey);
3787 3788 3789
//
//    return key;
//  } else {  // do nothing
H
Haojun Liao 已提交
3790
//    pQueryAttr->window.skey      = tw.skey;
3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
//    pWindowResInfo->prevSKey = tw.skey;
//    pTableQueryInfo->lastKey = tw.skey;
//
//    return tw.skey;
//  }
//
//  return true;
//}

//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
H
Haojun Liao 已提交
3801 3802
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3803
//    assert(*start <= pRuntimeEnv->current->lastKey);
3804
//  } else {
H
Haojun Liao 已提交
3805
//    assert(*start >= pRuntimeEnv->current->lastKey);
3806 3807 3808
//  }
//
//  // if queried with value filter, do NOT forward query start position
H
Haojun Liao 已提交
3809
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
3810 3811 3812 3813
//    return true;
//  }
//
//  /*
H
Haojun Liao 已提交
3814 3815 3816
//   * 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
3817 3818 3819 3820
//   */
//  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
//
//  STimeWindow w = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3821
//  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
3822 3823
//
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
3824
//  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3825 3826 3827 3828 3829
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
//    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3830
//    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
3831
//      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3832
//        getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey, &w);
3833 3834 3835
//        pWindowResInfo->prevSKey = w.skey;
//      }
//    } else {
H
Haojun Liao 已提交
3836
//      getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w);
3837 3838 3839 3840
//      pWindowResInfo->prevSKey = w.skey;
//    }
//
//    // the first time window
H
Haojun Liao 已提交
3841
//    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
3842
//
H
Haojun Liao 已提交
3843
//    while (pQueryAttr->limit.offset > 0) {
3844 3845 3846
//      STimeWindow tw = win;
//
//      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
3847
//        pQueryAttr->limit.offset -= 1;
3848 3849 3850 3851 3852 3853 3854 3855 3856
//        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 已提交
3857
//      if (pQueryAttr->limit.offset == 0) {
3858 3859 3860 3861 3862
//        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//        return true;
//      }
//
//      // current window does not ended in current data block, try next data block
H
Haojun Liao 已提交
3863
//      getNextTimeWindow(pQueryAttr, &tw);
3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877
//
//      /*
//       * 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 已提交
3878
//          pQueryAttr->limit.offset -= 1;
3879 3880
//        }
//
H
Haojun Liao 已提交
3881
//        if (pQueryAttr->limit.offset == 0) {
3882 3883 3884 3885 3886
//          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//          return true;
//        } else {
//          tw = win;
//          int32_t startPos =
H
Haojun Liao 已提交
3887
//              getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
3888 3889 3890
//          assert(startPos >= 0);
//
//          // set the abort info
H
Haojun Liao 已提交
3891
//          pQueryAttr->pos = startPos;
3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
//          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;
//}
3909

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3991 3992 3993
  return pFillCol;
}

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

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

4001 4002
  pRuntimeEnv->prevResult = prevResult;

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

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

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

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

H
Haojun Liao 已提交
4019 4020 4021 4022 4023 4024 4025 4026 4027 4028
  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 已提交
4029
      pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), 1);
H
Haojun Liao 已提交
4030 4031 4032
      break;
    }
    case OP_TableScan: {
H
Haojun Liao 已提交
4033
      pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr));
H
Haojun Liao 已提交
4034 4035
      break;
    }
H
Haojun Liao 已提交
4036
    default: { // do nothing
H
Haojun Liao 已提交
4037 4038 4039
      break;
    }
  }
H
Haojun Liao 已提交
4040 4041 4042 4043 4044 4045

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

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

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

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

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

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

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

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

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

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

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

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

  return tidInfo;
}

H
Haojun Liao 已提交
4111 4112 4113 4114
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 已提交
4115 4116
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4117 4118 4119 4120 4121 4122 4123 4124
  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 已提交
4125 4126 4127 4128
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);
4129

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
4228 4229
    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 已提交
4230 4231
  }

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

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

H
Haojun Liao 已提交
4239 4240
    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 已提交
4241

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
4280 4281 4282 4283 4284 4285
  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 已提交
4286

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

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

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

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

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

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

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

  return pOperator;
}

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

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

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

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

H
Haojun Liao 已提交
4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362
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 已提交
4363
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4364 4365 4366 4367 4368
  pOperator->exec         = doBlockInfoScan;

  return pOperator;
}

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

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

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

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

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

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

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

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

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

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

4405 4406 4407 4408 4409 4410
    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 已提交
4411 4412 4413
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4414 4415 4416
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4417 4418
}

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

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

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

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

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

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

  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 已提交
4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470
  {
    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 已提交
4471 4472 4473
  return pOrderColumns;
}

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

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

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

    bool found = false;
H
Haojun Liao 已提交
4488
    for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4489 4490 4491 4492 4493 4494
      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 已提交
4495
        index->colIndex = j;
H
Haojun Liao 已提交
4496 4497 4498
        index->colId = pExpr->resColId;
        found = true;
        break;
H
Haojun Liao 已提交
4499 4500
      }
    }
H
Haojun Liao 已提交
4501 4502

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

  return pOrderColumns;
}
H
Haojun Liao 已提交
4507

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

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

H
Haojun Liao 已提交
4518 4519 4520 4521 4522 4523
static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) {
  SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param;
  taosArrayDestroy(pInfo->orderColumnList);
  tfree(pInfo->prevRow);
}

H
Haojun Liao 已提交
4524
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream,
H
Haojun Liao 已提交
4525
                                                 SExprInfo* pExpr, int32_t numOfOutput, void* param) {
H
Haojun Liao 已提交
4526 4527
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

4528 4529 4530
  pInfo->resultRowFactor =
      (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery,
                                              false));
H
Haojun Liao 已提交
4531

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

H
Haojun Liao 已提交
4534
  pInfo->pMerge = param;
H
Haojun Liao 已提交
4535
  pInfo->bufCapacity = 4096;
4536 4537

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

H
Haojun Liao 已提交
4540
  pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4541
  pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4542

H
Haojun Liao 已提交
4543 4544 4545
  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
4546
    len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4547 4548
  }

H
Haojun Liao 已提交
4549
  int32_t numOfCols = (pInfo->orderColumnList != NULL)? taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4550
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4551
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4552 4553

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

H
Haojun Liao 已提交
4556 4557
    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
H
Haojun Liao 已提交
4558 4559
  }

H
Haojun Liao 已提交
4560
  numOfCols = (pInfo->groupColumnList != NULL)? taosArrayGetSize(pInfo->groupColumnList):0;
H
Haojun Liao 已提交
4561
  pInfo->currentGroupColData = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4562
  offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4563 4564

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4565
    pInfo->currentGroupColData[i] = (char*)pInfo->currentGroupColData + offset;
H
Haojun Liao 已提交
4566 4567 4568 4569 4570

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

H
Haojun Liao 已提交
4571 4572 4573
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  pInfo->seed = rand();
H
Haojun Liao 已提交
4574
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MERGE_STAGE);
H
Haojun Liao 已提交
4575 4576

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

  pOperator->exec         = doGlobalAggregate;
4588
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4589 4590 4591
  return pOperator;
}

H
Haojun Liao 已提交
4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605
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) {
4606
      len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4607 4608 4609 4610
    }

    int32_t numOfCols = (pInfo->orderColumnList != NULL)? taosArrayGetSize(pInfo->orderColumnList):0;
    pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4611
    int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4612 4613 4614 4615 4616

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

      SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
4617
      offset += pExpr[index->colIndex].base.colBytes;
H
Haojun Liao 已提交
4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628
    }
  }

  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 已提交
4629
  pOperator->exec         = doMultiwayMergeSort;
4630
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4631 4632 4633
  return pOperator;
}

H
Haojun Liao 已提交
4634
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4635 4636 4637
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4638
// this is a blocking operator
H
Haojun Liao 已提交
4639
static SSDataBlock* doAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4640
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4641
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4642 4643
    return NULL;
  }
H
Haojun Liao 已提交
4644

H
Haojun Liao 已提交
4645
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4646 4647
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4648
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4649

H
Haojun Liao 已提交
4650 4651
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
4652

H
Haojun Liao 已提交
4653
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4654

H
Haojun Liao 已提交
4655
  while(1) {
H
Haojun Liao 已提交
4656
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4657 4658 4659 4660
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4661 4662 4663
    if (pRuntimeEnv->current != NULL) {
      setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
4664

H
Haojun Liao 已提交
4665
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4666
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4667 4668 4669
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4670
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4671
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4672
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4673 4674
  }

H
Haojun Liao 已提交
4675
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4676
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4677

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

H
Haojun Liao 已提交
4681
  return pInfo->pRes;
H
Haojun Liao 已提交
4682 4683
}

H
Haojun Liao 已提交
4684
static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4685
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4686
  if (pOperator->status == OP_EXEC_DONE) {
4687 4688
    return NULL;
  }
H
Haojun Liao 已提交
4689

H
Haojun Liao 已提交
4690
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4691 4692
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4693
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4694

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

H
Haojun Liao 已提交
4698 4699
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4700 4701
    }

H
Haojun Liao 已提交
4702
    return pInfo->pRes;
4703
  }
H
Haojun Liao 已提交
4704

H
Haojun Liao 已提交
4705 4706
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
4707 4708 4709 4710

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
4711
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
4712 4713 4714 4715
    if (pBlock == NULL) {
      break;
    }

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

H
Haojun Liao 已提交
4718
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4719
      STableScanInfo* pScanInfo = upstream->info;
4720 4721 4722 4723
      order = getTableScanOrder(pScanInfo);
    }

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

H
Haojun Liao 已提交
4726
    TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
H
Haojun Liao 已提交
4727
    setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pRuntimeEnv->current->groupIndex, key);
H
Haojun Liao 已提交
4728
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
4729
  }
H
Haojun Liao 已提交
4730

H
Haojun Liao 已提交
4731 4732
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4733

H
Haojun Liao 已提交
4734
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4735
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4736

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

H
Haojun Liao 已提交
4739 4740 4741
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4742 4743
  }

H
Haojun Liao 已提交
4744
  return pInfo->pRes;
4745 4746
}

H
Haojun Liao 已提交
4747
static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
4748 4749
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4750 4751
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4752
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4753

H
Haojun Liao 已提交
4754
  SSDataBlock* pRes = pInfo->pRes;
H
Haojun Liao 已提交
4755
  int32_t order = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4756 4757

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

H
Haojun Liao 已提交
4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787
  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 已提交
4788
  while(1) {
H
Haojun Liao 已提交
4789 4790 4791 4792
    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 已提交
4793
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4794 4795 4796
      assert(*newgroup == false);

      *newgroup = prevVal;
H
Haojun Liao 已提交
4797
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4798
      break;
H
Haojun Liao 已提交
4799 4800
    }

H
Haojun Liao 已提交
4801 4802 4803 4804 4805 4806 4807
    // 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 已提交
4808
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
4809 4810

    // todo dynamic set tags
H
Haojun Liao 已提交
4811 4812 4813
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
H
Haojun Liao 已提交
4814

H
Haojun Liao 已提交
4815
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4816
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4817
    updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);
4818

H
Haojun Liao 已提交
4819
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4820 4821 4822 4823

    if (pTableQueryInfo != NULL) { // TODO refactor
      updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
    }
H
Haojun Liao 已提交
4824

H
Haojun Liao 已提交
4825 4826
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4827 4828 4829 4830
      break;
    }
  }

H
Haojun Liao 已提交
4831
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4832
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4833 4834
}

H
Haojun Liao 已提交
4835
static SSDataBlock* doLimit(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4836
  SOperatorInfo* pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4837
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4838
    return NULL;
H
Haojun Liao 已提交
4839 4840
  }

H
Haojun Liao 已提交
4841
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4842
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4843

H
Haojun Liao 已提交
4844
  SSDataBlock* pBlock = NULL;
H
Haojun Liao 已提交
4845
  while (1) {
H
Haojun Liao 已提交
4846
    pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4847
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4848
      setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4849
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4850 4851 4852
      return NULL;
    }

H
Haojun Liao 已提交
4853
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4854
      break;
4855
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4856
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4857
    } else {
sangshuduo's avatar
sangshuduo 已提交
4858
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4859 4860 4861
      pBlock->info.rows = remain;

      for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
H
Haojun Liao 已提交
4862
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
H
Haojun Liao 已提交
4863 4864

        int16_t bytes = pColInfoData->info.bytes;
H
Haojun Liao 已提交
4865
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4866 4867
      }

H
Haojun Liao 已提交
4868
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4869
      break;
H
Haojun Liao 已提交
4870 4871
    }
  }
H
Haojun Liao 已提交
4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883

  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 已提交
4884 4885
}

D
dapan1121 已提交
4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898

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 已提交
4899

D
dapan1121 已提交
4900 4901 4902 4903 4904 4905 4906
  if (fp(filterElem, input, input, p->info.type)) {
    return true;
  }

  return false;
}

4907
static SSDataBlock* doFilter(void* param, bool* newgroup) {
D
dapan1121 已提交
4908 4909 4910 4911 4912
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

4913
  SConditionOperatorInfo* pCondInfo = pOperator->info;
D
dapan1121 已提交
4914 4915 4916
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

  while (1) {
H
Haojun Liao 已提交
4917
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
D
dapan1121 已提交
4918
    if (pBlock == NULL) {
4919
      break;
D
dapan1121 已提交
4920
    }
H
Haojun Liao 已提交
4921

4922 4923 4924
    doSetFilterColumnInfo(pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock);
    assert(pRuntimeEnv->pTsBuf == NULL);
    filterRowsInDataBlock(pRuntimeEnv, pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock, true);
D
dapan1121 已提交
4925

4926 4927 4928
    if (pBlock->info.rows > 0) {
      return pBlock;
    }
D
dapan1121 已提交
4929 4930
  }

4931 4932 4933 4934
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  pOperator->status = OP_EXEC_DONE;
  return NULL;
}
D
dapan1121 已提交
4935

H
Haojun Liao 已提交
4936
static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4937
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4938
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4939 4940 4941
    return NULL;
  }

H
Haojun Liao 已提交
4942
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4943

H
Haojun Liao 已提交
4944
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4945
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4946 4947
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4948
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4949
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4950 4951 4952 4953
    }

    return pIntervalInfo->pRes;
  }
H
Haojun Liao 已提交
4954

H
Haojun Liao 已提交
4955 4956 4957
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
H
Haojun Liao 已提交
4958

H
Haojun Liao 已提交
4959
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4960 4961

  while(1) {
H
Haojun Liao 已提交
4962
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4963 4964 4965 4966 4967
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4968
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
H
Haojun Liao 已提交
4969
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4970 4971
  }

4972
  // restore the value
H
Haojun Liao 已提交
4973 4974
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
4975

H
Haojun Liao 已提交
4976
  pOperator->status = OP_RES_TO_RETURN;
4977
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4978
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4979
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4980

H
Haojun Liao 已提交
4981
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4982
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4983

H
Haojun Liao 已提交
4984
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4985
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4986 4987
  }

H
Haojun Liao 已提交
4988
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4989 4990
}

H
Haojun Liao 已提交
4991
static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4992
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4993
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4994 4995 4996
    return NULL;
  }

H
Haojun Liao 已提交
4997
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4998
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4999

H
Haojun Liao 已提交
5000
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5001
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5002
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5003
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5004 5005 5006 5007 5008
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
5009 5010
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
5011

H
Haojun Liao 已提交
5012
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
5013 5014

  while(1) {
H
Haojun Liao 已提交
5015
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5016
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5017
      break;
H
Haojun Liao 已提交
5018 5019
    }

H
Haojun Liao 已提交
5020
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5021
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
5022

H
Haojun Liao 已提交
5023
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5024
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
5025
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
5026

H
Haojun Liao 已提交
5027
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
5028
  }
H
Haojun Liao 已提交
5029

H
Haojun Liao 已提交
5030
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5031
  pQueryAttr->order.order = order;   // TODO : restore the order
5032
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
5033
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
5034

H
Haojun Liao 已提交
5035
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5036
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5037
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5038 5039 5040 5041
  }

  return pIntervalInfo->pRes;
}
H
Haojun Liao 已提交
5042

H
Haojun Liao 已提交
5043
static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062
  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 已提交
5063 5064 5065
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
5066 5067 5068 5069

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5070
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
5071 5072 5073 5074 5075
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5076
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQueryAttr->order.order);
5077 5078 5079 5080
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

  // restore the value
H
Haojun Liao 已提交
5081 5082
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098

  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 已提交
5099
static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5100
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5101
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5102 5103 5104
    return NULL;
  }

H
Haojun Liao 已提交
5105
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5106

H
Haojun Liao 已提交
5107
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5108
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5109
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5110 5111

    if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5112
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5113
    }
H
Haojun Liao 已提交
5114

H
Haojun Liao 已提交
5115
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5116 5117 5118 5119 5120
  }

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5121
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5122 5123 5124 5125 5126
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5127
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQueryAttr->order.order);
H
Haojun Liao 已提交
5128
    setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5129
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
5130
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQueryAttr->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
5131 5132
    }

H
Haojun Liao 已提交
5133
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5134 5135
  }

H
Haojun Liao 已提交
5136
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5137
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5138
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5139

H
Haojun Liao 已提交
5140
  if (!pRuntimeEnv->pQueryAttr->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5141 5142 5143
    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);
5144 5145
  }

H
Haojun Liao 已提交
5146
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5147
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5148

H
Haojun Liao 已提交
5149
  if (pInfo->binfo.pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5150
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5151 5152
  }

H
Haojun Liao 已提交
5153
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5154 5155
}

H
Haojun Liao 已提交
5156
static SSDataBlock* doFill(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5157
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5158
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5159 5160 5161
    return NULL;
  }

H
Haojun Liao 已提交
5162
  SFillOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5163
  SQueryRuntimeEnv  *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5164

H
Haojun Liao 已提交
5165
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
H
Haojun Liao 已提交
5166
    *newgroup = false;
sangshuduo's avatar
sangshuduo 已提交
5167
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5168 5169 5170
    return pInfo->pRes;
  }

H
Haojun Liao 已提交
5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185
  // 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 已提交
5186
  while(1) {
H
Haojun Liao 已提交
5187 5188 5189 5190 5191 5192 5193 5194
    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 已提交
5195

H
Haojun Liao 已提交
5196 5197
      // fill the previous group data block
      // before handle a new data block, close the fill operation for previous group data block
H
Haojun Liao 已提交
5198
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
H
Haojun Liao 已提交
5199
    } else {
H
Haojun Liao 已提交
5200 5201 5202 5203 5204 5205 5206 5207 5208
      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 已提交
5209

H
Haojun Liao 已提交
5210 5211
        int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
                                                                            : */pBlock->info.window.ekey;
H
Haojun Liao 已提交
5212

H
Haojun Liao 已提交
5213 5214 5215
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
H
Haojun Liao 已提交
5216 5217
    }

H
Haojun Liao 已提交
5218
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238
    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 已提交
5239 5240
  }
}
H
Haojun Liao 已提交
5241

H
Haojun Liao 已提交
5242
// todo set the attribute of query scan count
H
Haojun Liao 已提交
5243 5244 5245
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 已提交
5246 5247 5248 5249 5250 5251 5252 5253
    if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) {
      return 2;
    }
  }

  return 1;
}

H
Haojun Liao 已提交
5254 5255 5256 5257 5258
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5259
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5260
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5261 5262
  }

H
Haojun Liao 已提交
5263
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5264
  tfree(pOperator->info);
H
Haojun Liao 已提交
5265 5266 5267
  tfree(pOperator);
}

H
Haojun Liao 已提交
5268
SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5269 5270
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5271 5272
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
H
Haojun Liao 已提交
5273 5274

  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
H
Haojun Liao 已提交
5275
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5276

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

H
Haojun Liao 已提交
5279
  pInfo->seed = rand();
H
Haojun Liao 已提交
5280
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5281

H
Haojun Liao 已提交
5282
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5283
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5284
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5285
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5286
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5287
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5288
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5289 5290 5291
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5292

H
Haojun Liao 已提交
5293 5294
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5295 5296 5297
  return pOperator;
}

H
Haojun Liao 已提交
5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314
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 已提交
5315
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5316 5317 5318 5319
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5320
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5321
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5322
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5323 5324 5325 5326 5327 5328 5329
}

static void destroyArithOperatorInfo(void* param, int32_t numOfOutput) {
  SArithOperatorInfo* pInfo = (SArithOperatorInfo*) param;
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}

H
Haojun Liao 已提交
5330 5331 5332 5333 5334
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

5335 5336 5337
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
  SConditionOperatorInfo* pInfo = (SConditionOperatorInfo*) param;
  doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
D
dapan1121 已提交
5338 5339
}

H
Haojun Liao 已提交
5340
SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
5341 5342
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5343
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5344

H
Haojun Liao 已提交
5345
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) tableGroup);
H
Haojun Liao 已提交
5346
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
sangshuduo's avatar
sangshuduo 已提交
5347
  initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)tableGroup, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5348

5349
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5350 5351
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5352
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5353
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5354
  pOperator->info         = pInfo;
5355
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5356 5357 5358
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5359

H
Haojun Liao 已提交
5360 5361 5362
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5363
  return pOperator;
H
Haojun Liao 已提交
5364 5365
}

H
Haojun Liao 已提交
5366
SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5367 5368
  SArithOperatorInfo* pInfo = calloc(1, sizeof(SArithOperatorInfo));

H
Haojun Liao 已提交
5369
  pInfo->seed = rand();
H
Haojun Liao 已提交
5370
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5371

H
Haojun Liao 已提交
5372
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5373
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5374 5375 5376
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5377
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5378 5379

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5380 5381
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5382
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5383
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5384
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5385
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5386 5387 5388
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5389

H
Haojun Liao 已提交
5390 5391 5392
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5393 5394 5395
  return pOperator;
}

5396 5397 5398
SOperatorInfo* createConditionOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
                                           int32_t numOfOutput) {
  SConditionOperatorInfo* pInfo = calloc(1, sizeof(SConditionOperatorInfo));
D
dapan1121 已提交
5399

5400 5401
  {
    SColumnInfo* pCols = calloc(numOfOutput, sizeof(SColumnInfo));
D
dapan1121 已提交
5402

5403 5404 5405 5406 5407
    int32_t numOfFilter = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
      if (pExpr[i].base.flist.numOfFilters > 0) {
        numOfFilter += 1;
      }
D
dapan1121 已提交
5408

5409 5410 5411
      pCols[i].type = pExpr[i].base.resType;
      pCols[i].bytes = pExpr[i].base.resBytes;
      pCols[i].colId = pExpr[i].base.resColId;
H
Haojun Liao 已提交
5412

5413 5414 5415
      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 已提交
5416 5417
    }

5418 5419 5420
    assert(numOfFilter > 0);
    doCreateFilterInfo(pCols, numOfOutput, numOfFilter, &pInfo->pFilterInfo, 0);
    pInfo->numOfFilterCols = numOfFilter;
D
dapan1121 已提交
5421

5422 5423
    for(int32_t i = 0; i < numOfOutput; ++i) {
      tfree(pCols[i].flist.filterInfo);
D
dapan1121 已提交
5424 5425
    }

5426
    tfree(pCols);
D
dapan1121 已提交
5427 5428 5429 5430
  }

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

5431 5432
  pOperator->name         = "ConditionOperator";
  pOperator->operatorType = OP_Condition;
D
dapan1121 已提交
5433 5434 5435 5436 5437
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
5438
  pOperator->exec         = doFilter;
D
dapan1121 已提交
5439 5440
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5441
  pOperator->cleanup      = destroyConditionOperatorInfo;
D
dapan1121 已提交
5442 5443 5444 5445

  return pOperator;
}

H
Haojun Liao 已提交
5446
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5447
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
H
Haojun Liao 已提交
5448
  pInfo->limit = pRuntimeEnv->pQueryAttr->limit.limit;
H
Haojun Liao 已提交
5449 5450 5451

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5452 5453
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5454
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5455
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5456
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5457
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5458 5459
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5460 5461 5462 5463

  return pOperator;
}

H
Haojun Liao 已提交
5464
SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5465
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5466

H
Haojun Liao 已提交
5467
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5468
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5469
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5470 5471 5472

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5473
  pOperator->name         = "TimeIntervalAggOperator";
5474
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5475
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5476
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5477
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5478 5479 5480 5481
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5482
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5483 5484
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5485 5486 5487
  return pOperator;
}

5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512
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 已提交
5513
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5514
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5515

H
Haojun Liao 已提交
5516
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5517
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5518
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5519 5520

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5521 5522
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5523
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5524
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5525
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5526 5527
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5528 5529
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5530

H
Haojun Liao 已提交
5531 5532 5533
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5534 5535 5536
  return pOperator;
}

H
Haojun Liao 已提交
5537
SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5538
  SGroupbyOperatorInfo* pInfo = calloc(1, sizeof(SGroupbyOperatorInfo));
H
Haojun Liao 已提交
5539
  pInfo->colIndex = -1;  // group by column index
H
Haojun Liao 已提交
5540

H
Haojun Liao 已提交
5541
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5542
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5543
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5544 5545

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5546
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5547
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5548 5549
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5550
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5551 5552 5553 5554
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5555
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5556 5557
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5558 5559
  return pOperator;
}
H
Haojun Liao 已提交
5560

H
Haojun Liao 已提交
5561
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5562
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5563
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5564 5565 5566
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);

  {
H
Haojun Liao 已提交
5567 5568
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQueryAttr->fillVal);
H
Haojun Liao 已提交
5569 5570
    STimeWindow w = TSWINDOW_INITIALIZER;

H
Haojun Liao 已提交
5571 5572 5573
    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 已提交
5574

H
Haojun Liao 已提交
5575 5576 5577 5578
    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 已提交
5579
  }
H
Haojun Liao 已提交
5580 5581 5582

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5583
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5584
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5585 5586 5587
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5588
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5589 5590 5591 5592
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5593

H
Haojun Liao 已提交
5594 5595 5596
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5597 5598 5599
  return pOperator;
}

H
Haojun Liao 已提交
5600
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) {
H
Haojun Liao 已提交
5601 5602
  SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo));

H
Haojun Liao 已提交
5603 5604 5605
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;

  pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr);
H
Haojun Liao 已提交
5606 5607
  pInfo->slimit          = pQueryAttr->slimit;
  pInfo->limit           = pQueryAttr->limit;
H
Haojun Liao 已提交
5608 5609 5610

  pInfo->currentGroupOffset = pQueryAttr->slimit.offset;
  pInfo->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
5611 5612 5613 5614 5615 5616 5617 5618 5619

  // 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 已提交
5620
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
5621 5622 5623 5624 5625 5626 5627

  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 已提交
5628 5629 5630 5631 5632 5633 5634 5635

  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 已提交
5636
  pOperator->exec         = doSLimit;
H
Haojun Liao 已提交
5637 5638
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5639
  pOperator->cleanup      = destroySlimitOperatorInfo;
H
Haojun Liao 已提交
5640 5641 5642 5643
  return pOperator;
}


H
Haojun Liao 已提交
5644
static SSDataBlock* doTagScan(void* param, bool* newgroup) {
5645
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5646
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5647 5648
    return NULL;
  }
5649

H
Haojun Liao 已提交
5650
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5651

H
Haojun Liao 已提交
5652
  int32_t maxNumOfTables = (int32_t)pRuntimeEnv->resultInfo.capacity;
5653

H
Haojun Liao 已提交
5654 5655
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
H
Haojun Liao 已提交
5656
  *newgroup = false;
5657 5658

  int32_t count = 0;
H
Haojun Liao 已提交
5659 5660 5661 5662
  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 已提交
5663 5664
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    assert(pQueryAttr->numOfOutput == 1);
5665 5666

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
H
Haojun Liao 已提交
5667
    int32_t rsize = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
5668

5669 5670
    count = 0;

H
Haojun Liao 已提交
5671 5672
    int16_t bytes = pExprInfo->base.resBytes;
    int16_t type  = pExprInfo->base.resType;
5673

H
Haojun Liao 已提交
5674 5675 5676 5677
    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;
5678 5679 5680 5681
        break;
      }
    }

H
Haojun Liao 已提交
5682 5683 5684 5685
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5686 5687
      STableQueryInfo *item = taosArrayGetP(pa, i);

H
Haojun Liao 已提交
5688
      char *output = pColInfo->pData + count * rsize;
5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
      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 已提交
5703 5704
      *(int32_t *)output = pQueryAttr->vgId;
      output += sizeof(pQueryAttr->vgId);
5705

H
Haojun Liao 已提交
5706
      char* data = NULL;
5707
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5708
        data = tsdbGetTableName(item->pTable);
5709
      } else {
H
Haojun Liao 已提交
5710
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5711 5712
      }

H
Haojun Liao 已提交
5713
      doSetTagValueToResultBuf(output, data, type, bytes);
5714 5715 5716
      count += 1;
    }

H
Haojun Liao 已提交
5717
    qDebug("QInfo:%"PRIu64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5718 5719 5720
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5721
    count = 1;
H
Haojun Liao 已提交
5722 5723

    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5724
    qDebug("QInfo:%"PRIu64" create count(tbname) query, res:%d rows:1", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5725
  } else {  // return only the tags|table name etc.
H
Haojun Liao 已提交
5726
    SExprInfo* pExprInfo = pOperator->pExpr;  // todo use the column list instead of exprinfo
5727

H
Haojun Liao 已提交
5728 5729 5730
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741

      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 已提交
5742
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5743 5744
        type  = pExprInfo[j].base.resType;
        bytes = pExprInfo[j].base.resBytes;
5745 5746 5747 5748 5749 5750 5751

        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 已提交
5752
        dst  = pColInfo->pData + count * pExprInfo[j].base.resBytes;
5753 5754
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5755

5756 5757 5758
      count += 1;
    }

H
Haojun Liao 已提交
5759 5760 5761 5762
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

H
Haojun Liao 已提交
5763
    qDebug("QInfo:%"PRIu64" create tag values results completed, rows:%d", GET_QID(pRuntimeEnv), count);
5764 5765
  }

H
Haojun Liao 已提交
5766
  pRes->info.rows = count;
H
Haojun Liao 已提交
5767
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5768 5769
}

H
Haojun Liao 已提交
5770
SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput) {
5771
  STagScanInfo* pInfo = calloc(1, sizeof(STagScanInfo));
H
Haojun Liao 已提交
5772
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
5773

H
Haojun Liao 已提交
5774 5775 5776 5777 5778 5779
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

  pInfo->totalTables = pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
  pInfo->currentIndex = 0;

5780
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5781
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5782
  pOperator->operatorType = OP_TagScan;
5783
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5784
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5785 5786
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5787 5788
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5789
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5790
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5791

5792 5793
  return pOperator;
}
H
Haojun Liao 已提交
5794

H
Haojun Liao 已提交
5795
static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
5796
  int32_t j = 0;
5797

H
Haojun Liao 已提交
5798 5799
  if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
    if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5800
      return TSDB_TBNAME_COLUMN_INDEX;
H
Haojun Liao 已提交
5801
    } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
Y
yihaoDeng 已提交
5802
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5803
    }
Y
yihaoDeng 已提交
5804
    
H
Haojun Liao 已提交
5805

H
Haojun Liao 已提交
5806 5807
    while(j < pTableInfo->numOfTags) {
      if (pExpr->colInfo.colId == pTagCols[j].colId) {
5808 5809
        return j;
      }
5810

5811 5812
      j += 1;
    }
5813

H
Haojun Liao 已提交
5814
  } else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5815
    return TSDB_UD_COLUMN_INDEX;
5816
  } else {
H
Haojun Liao 已提交
5817 5818
    while (j < pTableInfo->numOfCols) {
      if (pExpr->colInfo.colId == pTableInfo->colList[j].colId) {
5819 5820
        return j;
      }
5821

5822
      j += 1;
5823 5824
    }
  }
5825 5826

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5827 5828
}

H
Haojun Liao 已提交
5829 5830
bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols);
5831
  return j != INT32_MIN;
5832 5833
}

5834
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5835 5836
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5837
    return false;
5838 5839
  }

5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850
  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 已提交
5851
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5852
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5853
    return false;
5854 5855
  }

H
hjxilinx 已提交
5856
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5857
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5858
    return false;
5859 5860
  }

5861 5862
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5863
    return false;
5864 5865
  }

5866 5867 5868
  return true;
}

H
Haojun Liao 已提交
5869 5870 5871 5872 5873
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);
5874
    return false;
5875 5876
  }

H
Haojun Liao 已提交
5877 5878 5879 5880 5881 5882 5883
  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)) {
5884
        continue;
5885
      }
5886

5887
      return false;
5888 5889
    }
  }
5890

H
Haojun Liao 已提交
5891 5892
  for(int32_t i = 0; i < numOfOutput; ++i) {
    if (!validateExprColumnInfo(pTableInfo, pExpr[i], pTagCols)) {
5893 5894 5895 5896
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5897
  return true;
5898 5899
}

5900
static char *createTableIdList(SQueryTableMsg *pQueryMsg, char *pMsg, SArray **pTableIdList) {
H
hjxilinx 已提交
5901
  assert(pQueryMsg->numOfTables > 0);
5902

weixin_48148422's avatar
weixin_48148422 已提交
5903
  *pTableIdList = taosArrayInit(pQueryMsg->numOfTables, sizeof(STableIdInfo));
5904

weixin_48148422's avatar
weixin_48148422 已提交
5905 5906
  for (int32_t j = 0; j < pQueryMsg->numOfTables; ++j) {
    STableIdInfo* pTableIdInfo = (STableIdInfo *)pMsg;
5907

5908
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5909 5910
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5911

H
hjxilinx 已提交
5912 5913 5914
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5915

H
hjxilinx 已提交
5916 5917
  return pMsg;
}
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 5946 5947 5948 5949
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;
}

5950
/**
H
hjxilinx 已提交
5951
 * pQueryMsg->head has been converted before this function is called.
5952
 *
H
hjxilinx 已提交
5953
 * @param pQueryMsg
5954 5955 5956 5957
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5958
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5959 5960
  int32_t code = TSDB_CODE_SUCCESS;

5961 5962 5963 5964
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5965 5966 5967
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);
  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5968 5969 5970
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5971 5972
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5973
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5974

5975 5976
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5977
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5978
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5979 5980

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5981
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5982
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5983
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
H
Haojun Liao 已提交
5984 5985 5986 5987
  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);
5988
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5989
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5990
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5991
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5992
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5993 5994
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
H
Haojun Liao 已提交
5995 5996
  pQueryMsg->tableScanOperator = htonl(pQueryMsg->tableScanOperator);
  pQueryMsg->numOfOperator = htonl(pQueryMsg->numOfOperator);
5997

5998
  // query msg safety check
5999
  if (!validateQueryMsg(pQueryMsg)) {
6000 6001
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
6002 6003
  }

H
Haojun Liao 已提交
6004
  char *pMsg = (char *)(pQueryMsg->tableCols) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
H
hjxilinx 已提交
6005
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
H
Haojun Liao 已提交
6006
    SColumnInfo *pColInfo = &pQueryMsg->tableCols[col];
6007

H
hjxilinx 已提交
6008
    pColInfo->colId = htons(pColInfo->colId);
6009
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
6010
    pColInfo->bytes = htons(pColInfo->bytes);
6011
    pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters);
6012

6013 6014 6015 6016 6017
    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;
    }
6018

6019
    int32_t numOfFilters = pColInfo->flist.numOfFilters;
6020
    if (numOfFilters > 0) {
6021 6022
      pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo));
      if (pColInfo->flist.filterInfo == NULL) {
H
Haojun Liao 已提交
6023 6024 6025
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
6026 6027
    }

6028 6029 6030
    code = deserializeColFilterInfo(pColInfo->flist.filterInfo, numOfFilters, &pMsg);
    if (code != TSDB_CODE_SUCCESS) {
      goto _cleanup;
6031 6032 6033
    }
  }

H
Haojun Liao 已提交
6034
  param->tableScanOperator = pQueryMsg->tableScanOperator;
H
Haojun Liao 已提交
6035 6036
  param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExpr == NULL) {
H
Haojun Liao 已提交
6037 6038 6039 6040
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

H
Haojun Liao 已提交
6041
  SSqlExpr *pExprMsg = (SSqlExpr *)pMsg;
6042

6043
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
6044
    param->pExpr[i] = pExprMsg;
6045

6046
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
6047
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6048
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6049
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6050 6051 6052 6053
    pExprMsg->colType       = htons(pExprMsg->colType);

    pExprMsg->resType       = htons(pExprMsg->resType);
    pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6054

H
Haojun Liao 已提交
6055 6056 6057
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
6058
    pExprMsg->flist.numOfFilters  = htons(pExprMsg->flist.numOfFilters);
H
Haojun Liao 已提交
6059
    pMsg += sizeof(SSqlExpr);
6060 6061

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6062 6063
      pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
      pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
6064

H
Haojun Liao 已提交
6065 6066 6067
      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.
6068
      } else {
H
Haojun Liao 已提交
6069
        pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
6070 6071 6072
      }
    }

H
Haojun Liao 已提交
6073 6074
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
6075
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
6076 6077
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
6078 6079 6080
      }
    }

6081 6082 6083 6084 6085
    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 已提交
6086
    pExprMsg = (SSqlExpr *)pMsg;
6087
  }
6088

H
Haojun Liao 已提交
6089
  if (pQueryMsg->secondStageOutput) {
H
Haojun Liao 已提交
6090 6091
    pExprMsg = (SSqlExpr *)pMsg;
    param->pSecExpr = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
6092

H
Haojun Liao 已提交
6093
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
H
Haojun Liao 已提交
6094
      param->pSecExpr[i] = pExprMsg;
H
Haojun Liao 已提交
6095 6096 6097

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6098
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6099 6100
      pExprMsg->resType       = htons(pExprMsg->resType);
      pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6101
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6102
      pExprMsg->colType       = htons(pExprMsg->colType);
H
Haojun Liao 已提交
6103

H
Haojun Liao 已提交
6104 6105 6106
      pExprMsg->functionId = htons(pExprMsg->functionId);
      pExprMsg->numOfParams = htons(pExprMsg->numOfParams);

H
Haojun Liao 已提交
6107
      pMsg += sizeof(SSqlExpr);
H
Haojun Liao 已提交
6108 6109

      for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6110 6111
        pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
        pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
H
Haojun Liao 已提交
6112

H
Haojun Liao 已提交
6113 6114 6115
        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 已提交
6116
        } else {
H
Haojun Liao 已提交
6117
          pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
H
Haojun Liao 已提交
6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128
        }
      }

      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 已提交
6129
      pExprMsg = (SSqlExpr *)pMsg;
H
Haojun Liao 已提交
6130 6131 6132
    }
  }

6133
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
6134

H
hjxilinx 已提交
6135
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
6136 6137
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
6138 6139 6140
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6141 6142

    for (int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
6143 6144
      param->pGroupColIndex[i].colId = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colId);
6145

6146 6147
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
6148

6149 6150
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
6151

6152 6153
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
6154
    }
6155

H
hjxilinx 已提交
6156 6157
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
6158 6159
  }

6160 6161
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
6162
    pQueryMsg->fillVal = (uint64_t)(pMsg);
6163 6164

    int64_t *v = (int64_t *)pMsg;
6165
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
6166 6167
      v[i] = htobe64(v[i]);
    }
6168

6169
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
6170
  }
6171

6172
  if (pQueryMsg->numOfTags > 0) {
6173 6174
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
6175 6176 6177 6178
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6179 6180
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6181

6182 6183 6184
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
6185
      pTagCol->flist.numOfFilters = 0;
6186

6187
      param->pTagColumnInfo[i] = *pTagCol;
6188
      pMsg += sizeof(SColumnInfo);
6189
    }
H
hjxilinx 已提交
6190
  }
6191

6192 6193
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6194 6195
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6196 6197 6198
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6199 6200

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6201 6202
    pMsg += pQueryMsg->tagCondLen;
  }
6203

6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214
  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 已提交
6215
  if (pQueryMsg->tbnameCondLen > 0) {
6216 6217
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6218 6219 6220 6221
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6222
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6223
    pMsg += pQueryMsg->tbnameCondLen;
6224 6225
  }

D
dapan1121 已提交
6226
  //skip ts buf
H
Haojun Liao 已提交
6227 6228
  if ((pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen;
D
dapan1121 已提交
6229 6230
  }

H
Haojun Liao 已提交
6231 6232 6233 6234 6235 6236 6237 6238
  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);
  }

6239
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6240

H
Haojun Liao 已提交
6241
  SQueriedTableInfo info = { .numOfTags = pQueryMsg->numOfTags, .numOfCols = pQueryMsg->numOfCols, .colList = pQueryMsg->tableCols};
H
Haojun Liao 已提交
6242
  if (!validateQueryTableCols(&info, param->pExpr, pQueryMsg->numOfOutput, param->pTagColumnInfo, pQueryMsg)) {
6243 6244
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6245
  }
6246

6247
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6248 6249
         "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,
6250
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6251
         pQueryMsg->fillType, pQueryMsg->tsBuf.tsLen, pQueryMsg->tsBuf.tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6252

6253
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6254
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6255 6256

_cleanup:
6257
  freeParam(param);
6258
  return code;
6259 6260
}

H
Haojun Liao 已提交
6261 6262 6263 6264
  int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
    if (filterNum <= 0) {
      return TSDB_CODE_SUCCESS;
    }
D
dapan1121 已提交
6265

H
Haojun Liao 已提交
6266 6267 6268 6269
    *dst = calloc(filterNum, sizeof(*src));
    if (*dst == NULL) {
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
D
dapan1121 已提交
6270

H
Haojun Liao 已提交
6271
    memcpy(*dst, src, sizeof(*src) * filterNum);
D
dapan1121 已提交
6272

H
Haojun Liao 已提交
6273 6274 6275
    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 已提交
6276

H
Haojun Liao 已提交
6277 6278 6279 6280 6281 6282
        if (pz == NULL) {
          if (i == 0) {
            free(*dst);
          } else {
            freeColumnFilterInfo(*dst, i);
          }
D
dapan1121 已提交
6283

H
Haojun Liao 已提交
6284 6285
          return TSDB_CODE_QRY_OUT_OF_MEMORY;
        }
D
dapan1121 已提交
6286

H
Haojun Liao 已提交
6287
        memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6288

H
Haojun Liao 已提交
6289 6290 6291
        (*dst)[i].pz = (int64_t)pz;
      }
    }
D
dapan1121 已提交
6292

H
Haojun Liao 已提交
6293 6294 6295
    return TSDB_CODE_SUCCESS;
  }

6296
int32_t buildArithmeticExprFromMsg(SExprInfo *pExprInfo, void *pQueryMsg) {
H
Haojun Liao 已提交
6297
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6298 6299

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6300
  TRY(TSDB_MAX_TAG_CONDITIONS) {
6301
    pExprNode = exprTreeFromBinary(pExprInfo->base.param[0].pz, pExprInfo->base.param[0].nLen);
weixin_48148422's avatar
weixin_48148422 已提交
6302 6303
  } CATCH( code ) {
    CLEANUP_EXECUTE();
6304
    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 已提交
6305 6306 6307
    return code;
  } END_TRY

H
hjxilinx 已提交
6308
  if (pExprNode == NULL) {
6309
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pExprInfo->base.param[0].pz);
6310
    return TSDB_CODE_QRY_APP_ERROR;
6311
  }
6312

6313
  pExprInfo->pExpr = pExprNode;
6314 6315 6316
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6317 6318

static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6319 6320 6321 6322
  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 已提交
6323 6324
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
      if (j < 0 || j >= pTableInfo->numOfCols) {
H
Haojun Liao 已提交
6325 6326
        return TSDB_CODE_QRY_INVALID_MSG;
      } else {
H
Haojun Liao 已提交
6327 6328 6329
        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 已提交
6330 6331 6332 6333 6334 6335 6336 6337
        assert(ret == TSDB_CODE_SUCCESS);
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6338
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6339 6340
int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo,
                        SSqlExpr** pExprMsg, SColumnInfo* pTagCols, int32_t queryType, void* pMsg) {
6341
  *pExprInfo = NULL;
H
hjxilinx 已提交
6342
  int32_t code = TSDB_CODE_SUCCESS;
6343

6344
  SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo));
6345
  if (pExprs == NULL) {
6346
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6347 6348
  }

H
Haojun Liao 已提交
6349
  bool    isSuperTable = QUERY_IS_STABLE_QUERY(queryType);
6350 6351
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6352
  for (int32_t i = 0; i < numOfOutput; ++i) {
6353
    pExprs[i].base = *pExprMsg[i];
H
Haojun Liao 已提交
6354 6355 6356 6357 6358
    memset(pExprs[i].base.param, 0, sizeof(tVariant) * tListLen(pExprs[i].base.param));

    for (int32_t j = 0; j < pExprMsg[i]->numOfParams; ++j) {
      tVariantAssign(&pExprs[i].base.param[j], &pExprMsg[i]->param[j]);
    }
6359 6360 6361 6362

    int16_t type = 0;
    int16_t bytes = 0;

6363
    // parse the arithmetic expression
6364
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6365
      code = buildArithmeticExprFromMsg(&pExprs[i], pMsg);
6366

6367
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6368
        tfree(pExprs);
6369
        return code;
6370 6371
      }

6372
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6373
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6374
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6375 6376 6377
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6378 6379 6380 6381
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
H
Haojun Liao 已提交
6382
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) {
6383
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6384 6385
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

H
Haojun Liao 已提交
6386 6387
      type = pExprs[i].base.param[1].nType;
      bytes = pExprs[i].base.param[1].nLen;
H
Haojun Liao 已提交
6388 6389 6390 6391
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
H
Haojun Liao 已提交
6392
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
6393
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
H
Haojun Liao 已提交
6394
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pTableInfo->numOfTags) {
6395 6396 6397
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      } else {
H
Haojun Liao 已提交
6398
        if (j < PRIMARYKEY_TIMESTAMP_COL_INDEX || j >= pTableInfo->numOfCols) {
6399 6400 6401
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      }
H
Haojun Liao 已提交
6402

dengyihao's avatar
dengyihao 已提交
6403
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6404
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j];
H
Haojun Liao 已提交
6405 6406 6407
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6408
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6409

6410 6411
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6412
      }
D
dapan1121 已提交
6413

6414 6415 6416
      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 已提交
6417 6418 6419 6420
        if (ret) {
          return ret;
        }
      }
6421 6422
    }

H
Haojun Liao 已提交
6423
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
H
Haojun Liao 已提交
6424
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
H
Haojun Liao 已提交
6425
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6426 6427 6428 6429
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6430 6431
    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 已提交
6432
      tfree(pExprs);
6433
      return TSDB_CODE_QRY_INVALID_MSG;
6434 6435
    }

6436
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
H
Haojun Liao 已提交
6437
      tagLen += pExprs[i].base.resBytes;
6438
    }
6439

H
Haojun Liao 已提交
6440
    assert(isValidDataType(pExprs[i].base.resType));
6441 6442
  }

H
Haojun Liao 已提交
6443
  // the tag length is affected by other tag columns, so this should be update.
H
Haojun Liao 已提交
6444
  updateOutputBufForTopBotQuery(pTableInfo, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6445

6446
  *pExprInfo = pExprs;
6447 6448 6449
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6450 6451
int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                           SSqlExpr** pExpr, SExprInfo* prevExpr) {
H
Haojun Liao 已提交
6452 6453 6454 6455 6456 6457 6458 6459
  *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 已提交
6460
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6461 6462

  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
6463 6464
    pExprs[i].base = *pExpr[i];
    pExprs[i].base.resType = 0;
H
Haojun Liao 已提交
6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483

    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 已提交
6484 6485
      type  = prevExpr[index].base.resType;
      bytes = prevExpr[index].base.resBytes;
H
Haojun Liao 已提交
6486 6487
    }

H
Haojun Liao 已提交
6488 6489 6490
    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 已提交
6491 6492 6493 6494
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6495
    assert(isValidDataType(pExprs[i].base.resType));
H
Haojun Liao 已提交
6496 6497 6498 6499 6500 6501
  }

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6502
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6503 6504 6505 6506 6507
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6508
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6509
  if (pGroupbyExpr == NULL) {
6510
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6511 6512 6513 6514 6515 6516 6517
    return NULL;
  }

  pGroupbyExpr->numOfGroupCols = pQueryMsg->numOfGroupCols;
  pGroupbyExpr->orderType = pQueryMsg->orderType;
  pGroupbyExpr->orderIndex = pQueryMsg->orderByIdx;

6518 6519 6520 6521
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6522

6523 6524 6525
  return pGroupbyExpr;
}

6526 6527 6528 6529
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 已提交
6530 6531
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6532

6533 6534 6535
  for (int32_t i = 0, j = 0; i < numOfCols; ++i) {
    if (pCols[i].flist.numOfFilters > 0) {
      SSingleColumnFilterInfo* pFilter = &((*pFilterInfo)[j]);
6536

6537 6538
      memcpy(&pFilter->info, &pCols[i], sizeof(SColumnInfo));
      pFilter->info = pCols[i];
6539

6540 6541 6542
      pFilter->numOfFilters = pCols[i].flist.numOfFilters;
      pFilter->pFilters = calloc(pFilter->numOfFilters, sizeof(SColumnFilterElem));
      if (pFilter->pFilters == NULL) {
H
Haojun Liao 已提交
6543 6544
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6545

6546 6547 6548
      for (int32_t f = 0; f < pFilter->numOfFilters; ++f) {
        SColumnFilterElem* pSingleColFilter = &pFilter->pFilters[f];
        pSingleColFilter->filterInfo = pCols[i].flist.filterInfo[f];
6549 6550 6551 6552

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
6553
          qError("QInfo:%" PRIu64 " invalid filter info", qId);
6554
          return TSDB_CODE_QRY_INVALID_MSG;
6555 6556
        }

6557 6558
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
6559
          qError("QInfo:%" PRIu64 " invalid filter info", qId);
6560
          return TSDB_CODE_QRY_INVALID_MSG;
6561 6562
        }

6563
        pSingleColFilter->bytes = pCols[i].bytes;
6564 6565 6566 6567 6568 6569 6570 6571 6572
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600
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 已提交
6601 6602
static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) {
  assert(pQueryAttr->pExpr1 != NULL && pQueryAttr != NULL);
6603

H
Haojun Liao 已提交
6604 6605
  for (int32_t k = 0; k < pQueryAttr->numOfOutput; ++k) {
    SSqlExpr *pSqlExprMsg = &pQueryAttr->pExpr1[k].base;
6606
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6607 6608
      continue;
    }
6609

6610
    // todo opt performance
H
Haojun Liao 已提交
6611
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6612
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6613
      int32_t f = 0;
H
Haojun Liao 已提交
6614
      for (f = 0; f < pQueryAttr->numOfCols; ++f) {
H
Haojun Liao 已提交
6615
        if (pColIndex->colId == pQueryAttr->tableCols[f].colId) {
H
Haojun Liao 已提交
6616
          pColIndex->colIndex = f;
6617 6618 6619
          break;
        }
      }
H
Haojun Liao 已提交
6620

H
Haojun Liao 已提交
6621
      assert(f < pQueryAttr->numOfCols);
6622 6623
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6624 6625
    } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      pColIndex->colIndex = 0;// only one source column, so it must be 0;
H
Haojun Liao 已提交
6626
      assert(pQueryAttr->numOfOutput == 1);
6627
    } else {
6628
      int32_t f = 0;
H
Haojun Liao 已提交
6629 6630
      for (f = 0; f < pQueryAttr->numOfTags; ++f) {
        if (pColIndex->colId == pQueryAttr->tagColList[f].colId) {
H
Haojun Liao 已提交
6631
          pColIndex->colIndex = f;
6632 6633
          break;
        }
6634
      }
6635

H
Haojun Liao 已提交
6636
      assert(f < pQueryAttr->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6637 6638 6639 6640
    }
  }
}

H
Haojun Liao 已提交
6641
void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo) {
H
Haojun Liao 已提交
6642 6643 6644 6645 6646 6647 6648
  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 已提交
6649

H
Haojun Liao 已提交
6650 6651
  if (isProjQuery(pQueryAttr)) {
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQueryAttr->resultRowSize;
H
Haojun Liao 已提交
6652 6653
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6654
    }
H
Haojun Liao 已提交
6655

H
Haojun Liao 已提交
6656
    pResultInfo->capacity  = numOfRes;
6657
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6658
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6659
  }
H
Haojun Liao 已提交
6660 6661 6662

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
  pResultInfo->total = 0;
H
Haojun Liao 已提交
6663 6664
}

D
fix bug  
dapan1121 已提交
6665 6666 6667 6668
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6669
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
H
Haojun Liao 已提交
6670
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId,
D
dapan1121 已提交
6671
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6672 6673 6674
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6675 6676
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6677
    goto _cleanup_qinfo;
6678
  }
6679

D
dapan1121 已提交
6680 6681
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6682 6683
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
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 6710 6711 6712 6713 6714 6715 6716 6717 6718
  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 已提交
6719 6720
  pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
  if (pQueryAttr->tableCols == NULL) {
6721
    goto _cleanup;
6722
  }
6723

H
Haojun Liao 已提交
6724 6725
  pQueryAttr->srcRowSize = 0;
  pQueryAttr->maxTableColumnWidth = 0;
H
hjxilinx 已提交
6726
  for (int16_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
6727
    pQueryAttr->tableCols[i] = pQueryMsg->tableCols[i];
6728
    pQueryAttr->tableCols[i].flist.filterInfo = tFilterInfoDup(pQueryMsg->tableCols[i].flist.filterInfo, pQueryAttr->tableCols[i].flist.numOfFilters);
6729

H
Haojun Liao 已提交
6730 6731 6732
    pQueryAttr->srcRowSize += pQueryAttr->tableCols[i].bytes;
    if (pQueryAttr->maxTableColumnWidth < pQueryAttr->tableCols[i].bytes) {
      pQueryAttr->maxTableColumnWidth = pQueryAttr->tableCols[i].bytes;
6733
    }
H
hjxilinx 已提交
6734
  }
6735

6736
  // calculate the result row size
6737
  for (int16_t col = 0; col < numOfOutput; ++col) {
H
Haojun Liao 已提交
6738
    assert(pExprs[col].base.resBytes > 0);
H
Haojun Liao 已提交
6739
    pQueryAttr->resultRowSize += pExprs[col].base.resBytes;
6740 6741 6742

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
H
Haojun Liao 已提交
6743
      pQueryAttr->tagLen += pExprs[col].base.resBytes;
6744
    }
D
dapan1121 已提交
6745

6746
    if (pExprs[col].base.flist.filterInfo) {
H
Haojun Liao 已提交
6747
      ++pQueryAttr->havingNum;
D
dapan1121 已提交
6748
    }
6749
  }
6750

H
Haojun Liao 已提交
6751
  doUpdateExprColumnIndex(pQueryAttr);
H
Haojun Liao 已提交
6752
  int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId);
6753
  if (ret != TSDB_CODE_SUCCESS) {
6754
    goto _cleanup;
6755 6756
  }

H
Haojun Liao 已提交
6757 6758 6759
  if (pQueryAttr->fillType != TSDB_FILL_NONE) {
    pQueryAttr->fillVal = malloc(sizeof(int64_t) * pQueryAttr->numOfOutput);
    if (pQueryAttr->fillVal == NULL) {
6760
      goto _cleanup;
6761 6762 6763
    }

    // the first column is the timestamp
H
Haojun Liao 已提交
6764
    memcpy(pQueryAttr->fillVal, (char *)pQueryMsg->fillVal, pQueryAttr->numOfOutput * sizeof(int64_t));
6765 6766
  }

dengyihao's avatar
dengyihao 已提交
6767 6768 6769
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6770
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6771

6772 6773 6774
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6775
  }
H
Haojun Liao 已提交
6776

H
Haojun Liao 已提交
6777
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6778 6779 6780 6781
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6782
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6783
  pQInfo->rspContext = NULL;
6784
  pQInfo->sql = sql;
6785
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6786
  tsem_init(&pQInfo->ready, 0, 0);
6787

H
Haojun Liao 已提交
6788 6789
  pQueryAttr->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, pQueryAttr->stableQuery);
6790

H
Haojun Liao 已提交
6791
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6792
  STimeWindow window = pQueryAttr->window;
H
Haojun Liao 已提交
6793

H
Haojun Liao 已提交
6794
  int32_t index = 0;
H
hjxilinx 已提交
6795
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6796
    SArray* pa = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
6797

H
Haojun Liao 已提交
6798
    size_t s = taosArrayGetSize(pa);
6799
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6800 6801 6802
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6803

H
Haojun Liao 已提交
6804
    taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1);
6805

H
hjxilinx 已提交
6806
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6807
      STableKeyInfo* info = taosArrayGet(pa, j);
6808
      window.skey = info->lastKey;
6809 6810

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
H
Haojun Liao 已提交
6811
      STableQueryInfo* item = createTableQueryInfo(pQueryAttr, info->pTable, pQueryAttr->groupbyColumn, window, buf);
B
Bomin Zhang 已提交
6812 6813 6814
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6815

6816
      item->groupIndex = i;
H
hjxilinx 已提交
6817
      taosArrayPush(p1, &item);
6818 6819

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6820
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6821
      index += 1;
H
hjxilinx 已提交
6822 6823
    }
  }
6824

H
Haojun Liao 已提交
6825
  colIdCheck(pQueryAttr, pQInfo->qId);
6826

6827
  // todo refactor
H
Haojun Liao 已提交
6828
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6829

D
fix bug  
dapan1121 已提交
6830
  qDebug("qmsg:%p QInfo:%" PRIu64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6831 6832
  return pQInfo;

B
Bomin Zhang 已提交
6833
_cleanup_qinfo:
H
Haojun Liao 已提交
6834
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6835

6836 6837 6838 6839
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6840

S
TD-1848  
Shengliang Guan 已提交
6841
  tfree(pTagCols);
B
Bomin Zhang 已提交
6842 6843 6844
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6845 6846
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6847
    }
D
dapan1121 已提交
6848

6849 6850
    if (pExprInfo->base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo->base.flist.filterInfo, pExprInfo->base.flist.numOfFilters);
D
dapan1121 已提交
6851
    }
B
Bomin Zhang 已提交
6852
  }
H
Haojun Liao 已提交
6853

S
TD-1848  
Shengliang Guan 已提交
6854
  tfree(pExprs);
B
Bomin Zhang 已提交
6855

6856
_cleanup:
dengyihao's avatar
dengyihao 已提交
6857
  freeQInfo(pQInfo);
6858 6859 6860
  return NULL;
}

H
Haojun Liao 已提交
6861
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6862 6863 6864 6865
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6866

H
hjxilinx 已提交
6867 6868 6869 6870
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6871
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6872 6873 6874
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6875
int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start,
H
Haojun Liao 已提交
6876
                  int32_t prevResultLen, void* merger) {
H
hjxilinx 已提交
6877
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6878 6879

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6880 6881
  pRuntimeEnv->qinfo = pQInfo;

H
Haojun Liao 已提交
6882
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
6883

6884
  STSBuf *pTsBuf = NULL;
H
Haojun Liao 已提交
6885 6886
  if (pTsBufInfo->tsLen > 0) { // open new file to save the result
    char *tsBlock = start + pTsBufInfo->tsOffset;
H
Haojun Liao 已提交
6887
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pTsBufInfo->tsNumOfBlocks, pTsBufInfo->tsLen, pTsBufInfo->tsOrder,
H
Haojun Liao 已提交
6888
        pQueryAttr->vgId);
6889

6890 6891
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
dengyihao's avatar
dengyihao 已提交
6892
    UNUSED(ret);
H
hjxilinx 已提交
6893
  }
6894

6895
  SArray* prevResult = NULL;
H
Haojun Liao 已提交
6896 6897
  if (prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, prevResultLen);
6898 6899
  }

H
Haojun Liao 已提交
6900
  if (tsdb != NULL) {
H
Haojun Liao 已提交
6901
    pQueryAttr->precision = tsdbGetCfg(tsdb)->precision;
H
Haojun Liao 已提交
6902
  }
6903

H
Haojun Liao 已提交
6904 6905
  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 已提交
6906
    qDebug("QInfo:%"PRIu64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQueryAttr->window.skey,
H
Haojun Liao 已提交
6907
           pQueryAttr->window.ekey, pQueryAttr->order.order);
H
Haojun Liao 已提交
6908
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6909
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6910
    // todo free memory
6911 6912
    return TSDB_CODE_SUCCESS;
  }
6913

H
Haojun Liao 已提交
6914
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
6915
    qDebug("QInfo:%"PRIu64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
6916
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6917 6918
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6919 6920

  // filter the qualified
H
Haojun Liao 已提交
6921
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, sourceOptr, param->tableScanOperator, param->pOperator, merger)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6922 6923
    goto _error;
  }
6924

H
hjxilinx 已提交
6925 6926 6927 6928
  return code;

_error:
  // table query ref will be decrease during error handling
6929
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6930 6931 6932
  return code;
}

6933
//TODO refactor
H
Haojun Liao 已提交
6934
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6935
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6936 6937
      return;
    }
H
Haojun Liao 已提交
6938

B
Bomin Zhang 已提交
6939
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
6940
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
6941 6942 6943
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6944

B
Bomin Zhang 已提交
6945 6946 6947
    free(pFilter);
}

H
Haojun Liao 已提交
6948 6949
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6950
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971
    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 已提交
6972 6973 6974 6975 6976 6977 6978 6979
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 已提交
6980
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6981
    }
D
dapan1121 已提交
6982

6983 6984
    if (pExprInfo[i].base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo[i].base.flist.filterInfo, pExprInfo[i].base.flist.numOfFilters);
D
dapan1121 已提交
6985
    }
H
Haojun Liao 已提交
6986 6987 6988 6989

    for(int32_t j = 0; j < pExprInfo[i].base.numOfParams; ++j) {
      tVariantDestroy(&pExprInfo[i].base.param[j]);
    }
H
Haojun Liao 已提交
6990 6991 6992 6993 6994 6995
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6996
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6997 6998 6999
  if (!isValidQInfo(pQInfo)) {
    return;
  }
7000

H
Haojun Liao 已提交
7001
  qDebug("QInfo:%"PRIu64" start to free QInfo", pQInfo->qId);
7002

H
Haojun Liao 已提交
7003
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7004
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
7005 7006

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
7007
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
7008

H
Haojun Liao 已提交
7009
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
7010
  freeQueryAttr(pQueryAttr);
7011

7012 7013
  tsdbDestroyTableGroup(&pQueryAttr->tableGroupInfo);

S
TD-1848  
Shengliang Guan 已提交
7014
  tfree(pQInfo->pBuf);
7015 7016
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
7017
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
7018
  pQInfo->signature = 0;
7019

H
Haojun Liao 已提交
7020
  qDebug("QInfo:%"PRIu64" QInfo is freed", pQInfo->qId);
7021

S
TD-1848  
Shengliang Guan 已提交
7022
  tfree(pQInfo);
H
hjxilinx 已提交
7023 7024
}

H
Haojun Liao 已提交
7025
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
7026
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
7027
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7028
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
7029

H
hjxilinx 已提交
7030
  // load data from file to msg buffer
H
Haojun Liao 已提交
7031
  if (pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
7032 7033
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
7034

H
hjxilinx 已提交
7035
    // make sure file exist
D
fix bug  
dapan1121 已提交
7036 7037
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
7038
      assert(s == pRuntimeEnv->outputBuf->info.rows);
7039

H
Haojun Liao 已提交
7040
      qDebug("QInfo:%"PRIu64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
7041 7042
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
7043
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
7044
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
7045 7046
          assert(0);
        }
H
Haojun Liao 已提交
7047
      } else {
7048
        UNUSED(s);
D
dapan1121 已提交
7049 7050 7051 7052
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
7053
      // dump error info
D
dapan1121 已提交
7054 7055 7056
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
7057
      }
H
Haojun Liao 已提交
7058

D
fix bug  
dapan1121 已提交
7059
      fclose(f);
D
dapan1121 已提交
7060
      *(FILE **)pColInfoData->pData = NULL;
H
hjxilinx 已提交
7061
    }
7062

H
hjxilinx 已提交
7063
    // all data returned, set query over
H
Haojun Liao 已提交
7064 7065
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
7066
    }
H
hjxilinx 已提交
7067
  } else {
H
Haojun Liao 已提交
7068
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
7069
  }
7070

H
Haojun Liao 已提交
7071
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
7072
  qDebug("QInfo:%"PRIu64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
7073
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
7074

H
Haojun Liao 已提交
7075
  if (pQueryAttr->limit.limit > 0 && pQueryAttr->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
7076
    qDebug("QInfo:%"PRIu64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQueryAttr->limit.limit);
H
Haojun Liao 已提交
7077
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
7078
  }
7079

H
hjxilinx 已提交
7080
  return TSDB_CODE_SUCCESS;
7081 7082
}

H
Haojun Liao 已提交
7083
bool doBuildResCheck(SQInfo* pQInfo) {
7084 7085 7086 7087 7088
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
7089
  buildRes = needBuildResAfterQueryComplete(pQInfo);
7090

H
Haojun Liao 已提交
7091 7092
  // 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 已提交
7093
  assert(pQInfo->owner == taosGetSelfPthreadId());
7094
  pQInfo->owner = 0;
H
Haojun Liao 已提交
7095

H
Haojun Liao 已提交
7096
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
7097

7098
  // used in retrieve blocking model.
H
Haojun Liao 已提交
7099
  tsem_post(&pQInfo->ready);
7100 7101 7102
  return buildRes;
}

H
Haojun Liao 已提交
7103 7104 7105 7106
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
7107 7108
  }

7109 7110 7111
  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 已提交
7112
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
7113 7114 7115 7116 7117
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
7118
  } else {
H
Haojun Liao 已提交
7119
    memcpy(output, val, bytes);
7120 7121 7122
  }
}

H
Haojun Liao 已提交
7123
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
7124 7125 7126 7127
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
7128
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
7129 7130
}

H
Haojun Liao 已提交
7131
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
7132
  int64_t t = getQuerySupportBufSize(numOfTables);
7133
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7134
    return TSDB_CODE_SUCCESS;
7135
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
7136 7137

    while(1) {
7138
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
7139 7140
      int64_t remain = s - t;
      if (remain >= 0) {
7141
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153
          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 已提交
7154
void releaseQueryBuf(size_t numOfTables) {
7155
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7156 7157 7158 7159 7160 7161
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
7162
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
7163
}
7164 7165 7166 7167 7168 7169 7170

void freeQueryAttr(SQueryAttr* pQueryAttr) {
  if (pQueryAttr != NULL) {
    if (pQueryAttr->fillVal != NULL) {
      tfree(pQueryAttr->fillVal);
    }

H
Haojun Liao 已提交
7171
    pQueryAttr->pFilterInfo = doDestroyFilterInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols);
7172 7173 7174

    pQueryAttr->pExpr1 = destroyQueryFuncExpr(pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
    pQueryAttr->pExpr2 = destroyQueryFuncExpr(pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
H
Haojun Liao 已提交
7175
    pQueryAttr->pExpr3 = destroyQueryFuncExpr(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
7176 7177 7178 7179

    tfree(pQueryAttr->tagColList);
    tfree(pQueryAttr->pFilterInfo);

H
Haojun Liao 已提交
7180
    if (pQueryAttr->tableCols != NULL) {
7181
      for (int32_t i = 0; i < pQueryAttr->numOfCols; i++) {
H
Haojun Liao 已提交
7182
        SColumnInfo* column = pQueryAttr->tableCols + i;
7183
        freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters);
7184
      }
H
Haojun Liao 已提交
7185
      tfree(pQueryAttr->tableCols);
7186 7187 7188 7189 7190 7191 7192 7193 7194
    }

    if (pQueryAttr->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo);
      tfree(pQueryAttr->pGroupbyExpr);
    }
  }
}