qExecutor.c 317.3 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"
29

H
Haojun Liao 已提交
30
#define MAX_ROWS_PER_RESBUF_PAGE  ((1u<<12) - 1)
31 32 33 34 35 36

/**
 * check if the primary column is load by default, otherwise, the program will
 * forced to load primary column explicitly.
 */

37
#define IS_MASTER_SCAN(runtime)        ((runtime)->scanFlag == MASTER_SCAN)
H
hjxilinx 已提交
38
#define IS_REVERSE_SCAN(runtime)       ((runtime)->scanFlag == REVERSE_SCAN)
39
#define SET_MASTER_SCAN_FLAG(runtime)  ((runtime)->scanFlag = MASTER_SCAN)
H
hjxilinx 已提交
40
#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN)
41

H
Haojun Liao 已提交
42
#define GET_QINFO_ADDR(x) ((SQInfo *)((char *)(x)-offsetof(SQInfo, runtimeEnv)))
43

44
#define GET_COL_DATA_POS(query, index, step) ((query)->pos + (index) * (step))
45
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
46

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

S
TD-1057  
Shengliang Guan 已提交
49
#define TIME_WINDOW_COPY(_dst, _src)  do {\
H
Haojun Liao 已提交
50 51
   (_dst).skey = (_src).skey;\
   (_dst).ekey = (_src).ekey;\
H
Haojun Liao 已提交
52
} while (0)
S
TD-1057  
Shengliang Guan 已提交
53

54
enum {
55 56
  TS_JOIN_TS_EQUAL       = 0,
  TS_JOIN_TS_NOT_EQUALS  = 1,
57 58 59
  TS_JOIN_TAG_NOT_EQUALS = 2,
};

60
typedef struct {
61 62 63 64 65
  int32_t     status;       // query status
  TSKEY       lastKey;      // the lastKey value before query executed
  STimeWindow w;            // whole query time window
  int32_t     windowIndex;  // index of active time window result for interval query
  STSCursor   cur;
66 67
} SQueryStatusInfo;

Y
yihaoDeng 已提交
68 69 70 71 72 73 74
typedef struct {
  SArray  *dataBlockInfos; 
  int64_t firstSeekTimeUs; 
  int64_t numOfRowsInMemTable;
  char    *result;
} STableBlockDist;

H
Haojun Liao 已提交
75
#if 0
H
Haojun Liao 已提交
76
static UNUSED_FUNC void *u_malloc (size_t __size) {
H
Haojun Liao 已提交
77
  uint32_t v = rand();
H
Haojun Liao 已提交
78 79

  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
80 81
    return NULL;
  } else {
H
Haojun Liao 已提交
82
    return malloc(__size);
H
Haojun Liao 已提交
83
  }
H
Haojun Liao 已提交
84 85
}

H
Haojun Liao 已提交
86 87
static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) {
  uint32_t v = rand();
H
Haojun Liao 已提交
88
  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
89 90 91 92 93 94
    return NULL;
  } else {
    return calloc(num, __size);
  }
}

H
Haojun Liao 已提交
95 96 97 98 99 100 101 102 103
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 已提交
104
#define calloc  u_calloc
H
Haojun Liao 已提交
105
#define malloc  u_malloc
H
Haojun Liao 已提交
106
#define realloc u_realloc
H
Haojun Liao 已提交
107
#endif
H
Haojun Liao 已提交
108

109
#define CLEAR_QUERY_STATUS(q, st)   ((q)->status &= (~(st)))
H
Haojun Liao 已提交
110
#define GET_NUM_OF_TABLEGROUP(q)    taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
111
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)
H
Haojun Liao 已提交
112

H
Haojun Liao 已提交
113
static void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv);
114

H
Haojun Liao 已提交
115
int32_t getMaximumIdleDurationSec() {
116 117
  return tsShellActivityTimer * 2;
}
118

119 120
static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) {
  int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
121 122 123
  if (pQuery->interval.intervalUnit != 'n' && pQuery->interval.intervalUnit != 'y') {
    tw->skey += pQuery->interval.sliding * factor;
    tw->ekey = tw->skey + pQuery->interval.interval - 1;
124 125 126
    return;
  }

127
  int64_t key = tw->skey / 1000, interval = pQuery->interval.interval;
128 129 130
  if (pQuery->precision == TSDB_TIME_PRECISION_MICRO) {
    key /= 1000;
  }
131
  if (pQuery->interval.intervalUnit == 'y') {
132 133
    interval *= 12;
  }
134 135 136 137 138

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

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

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

  if (pQuery->precision == TSDB_TIME_PRECISION_MICRO) {
    tw->skey *= 1000L;
    tw->ekey *= 1000L;
  }
  tw->ekey -= 1;
}

156
static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult);
H
Haojun Liao 已提交
157 158
static void setResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfCols);

H
Haojun Liao 已提交
159
static void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult);
160
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId);
161

162
static void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY *tsCol, SDataBlockInfo* pBlockInfo,
H
Haojun Liao 已提交
163
                          SDataStatis *pStatis, SExprInfo* pExprInfo);
H
Haojun Liao 已提交
164
static void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex);
165

H
Haojun Liao 已提交
166
  static void initCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pSQLCtx);
H
Haojun Liao 已提交
167
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
168
static void resetDefaultResInfoOutputBuf(SQueryRuntimeEnv *pRuntimeEnv);
169 170
static bool hasMainOutput(SQuery *pQuery);

H
Haojun Liao 已提交
171
static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
172
static void releaseQueryBuf(size_t numOfTables);
173
static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order);
H
Haojun Liao 已提交
174
static void doRowwiseTimeWindowInterpolation(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type);
H
Haojun Liao 已提交
175
static STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win);
176
static STableIdInfo createTableIdInfo(SQuery* pQuery);
177

H
Haojun Liao 已提交
178 179
static SOperatorInfo* createBiDirectionTableScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime);
static SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime);
H
Haojun Liao 已提交
180 181
static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream);

H
Haojun Liao 已提交
182
static int32_t getNumOfScanTimes(SQuery* pQuery);
H
Haojun Liao 已提交
183
static char *getArithemicInputSrc(void *param, const char *name, int32_t colId);
H
Haojun Liao 已提交
184 185 186 187 188 189 190
static bool isFixedOutputQuery(SQuery* pQuery);

static SOperatorInfo* createAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createArithOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createLimitOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createOffsetOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createHashIntervalAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
H
Haojun Liao 已提交
191 192
static SOperatorInfo* createFillOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createHashGroupbyAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
H
Haojun Liao 已提交
193
static SOperatorInfo* createStableIntervalOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
H
Haojun Liao 已提交
194

H
Haojun Liao 已提交
195
static int32_t doCopyToSData_rv(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock);
H
Haojun Liao 已提交
196

H
Haojun Liao 已提交
197 198
static char *getGroupbyColumnData(SQuery *pQuery, int16_t *type, int16_t *bytes, SArray* pDataBlock);
static int32_t getGroupbyColumnData_rv(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock);
H
Haojun Liao 已提交
199

H
Haojun Liao 已提交
200 201 202
static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo, char *pData, int16_t type, int16_t bytes, int32_t groupIndex);
static int32_t setGroupResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                          SQLFunctionCtx * pCtx, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex);
H
Haojun Liao 已提交
203 204 205
static void destroyOperatorInfo(SOperatorInfo* pOperator);
void initCtxOutputBuf_rv(SQLFunctionCtx* pCtx, int32_t size);
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win);
H
Haojun Liao 已提交
206 207 208

// setup the output buffer
static SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput) {
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 217 218
    idata.info.type = pExpr[i].type;
    idata.info.bytes = pExpr[i].bytes;
    idata.info.colId = pExpr[i].base.resColId;
    idata.pData = calloc(4096, idata.info.bytes * 4096);
H
Haojun Liao 已提交
219 220
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
221 222

  return res;
H
Haojun Liao 已提交
223 224
}

H
Haojun Liao 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
static void* destroyOutputBuf(SSDataBlock* pBlock) {
  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;
}

242
bool doFilterData(SQuery *pQuery, int32_t elemPos) {
243 244
  for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
    SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
245

S
TD-1057  
Shengliang Guan 已提交
246
    char *pElem = (char*)pFilterInfo->pData + pFilterInfo->info.bytes * elemPos;
247

248 249
    bool qualified = false;
    for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
250
      SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
251

H
Haojun Liao 已提交
252 253
      bool isnull = isNull(pElem, pFilterInfo->info.type);
      if (isnull) {
254
        if (pFilterElem->fp == isNullOperator) {
H
Haojun Liao 已提交
255 256 257 258 259 260
          qualified = true;
          break;
        } else {
          continue;
        }
      } else {
261
        if (pFilterElem->fp == notNullOperator) {
H
Haojun Liao 已提交
262 263
          qualified = true;
          break;
264
        } else if (pFilterElem->fp == isNullOperator) {
H
Haojun Liao 已提交
265 266 267 268
          continue;
        }
      }

269
      if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo->info.type)) {
270 271 272 273
        qualified = true;
        break;
      }
    }
274

275 276 277 278
    if (!qualified) {
      return false;
    }
  }
279

280 281 282 283 284 285
  return true;
}

int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);
286

287
  int64_t maxOutput = 0;
288
  for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
289
    int32_t functionId = pQuery->pExpr1[j].base.functionId;
290

291 292 293 294 295 296 297 298
    /*
     * ts, tag, tagprj function can not decide the output number of current query
     * the number of output result is decided by main output
     */
    if (hasMainFunction &&
        (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ)) {
      continue;
    }
299

H
Haojun Liao 已提交
300
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
301 302 303 304
    if (pResInfo != NULL && maxOutput < pResInfo->numOfRes) {
      maxOutput = pResInfo->numOfRes;
    }
  }
305

306
  assert(maxOutput >= 0);
307 308 309
  return maxOutput;
}

H
Haojun Liao 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
int64_t getNumOfResult_rv(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);

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

    /*
     * ts, tag, tagprj function can not decide the output number of current query
     * the number of output result is decided by main output
     */
    if (hasMainFunction &&
        (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ)) {
      continue;
    }

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

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

337 338 339
/*
 * the value of number of result needs to be update due to offset value upated.
 */
H
Haojun Liao 已提交
340 341 342
void updateNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfRes) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

343
  for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
344
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
345

H
Haojun Liao 已提交
346 347 348 349 350
    int16_t functionId = pRuntimeEnv->pCtx[j].functionId;
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ ||
        functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
351

H
Haojun Liao 已提交
352
    assert(pResInfo->numOfRes > numOfRes);
353 354 355 356
    pResInfo->numOfRes = numOfRes;
  }
}

357
bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) {
358 359 360
  if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) {
    return false;
  }
361

362
  for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) {
363
    SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i);
Y
TD-1230  
yihaoDeng 已提交
364
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
365
      //make sure the normal column locates at the second position if tbname exists in group by clause
366
      if (pGroupbyExpr->numOfGroupCols > 1) {
367
        assert(pColIndex->colIndex > 0);
368
      }
369

370 371 372
      return true;
    }
  }
373

374 375 376
  return false;
}

377 378 379 380 381 382 383 384 385 386 387
bool isStabledev(SQuery* pQuery) {
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functId = pQuery->pExpr1[i].base.functionId;
    if (functId == TSDB_FUNC_STDDEV_DST) {
      return true;
    }
  }

  return false;
}

388 389
int16_t getGroupbyColumnType(SQuery *pQuery, SSqlGroupbyExpr *pGroupbyExpr) {
  assert(pGroupbyExpr != NULL);
390

391 392
  int32_t colId = -2;
  int16_t type = TSDB_DATA_TYPE_NULL;
393

394
  for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) {
395
    SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i);
Y
TD-1230  
yihaoDeng 已提交
396
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
397 398 399 400
      colId = pColIndex->colId;
      break;
    }
  }
401

402
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
403 404
    if (colId == pQuery->colList[i].colId) {
      type = pQuery->colList[i].type;
405 406 407
      break;
    }
  }
408

409 410 411
  return type;
}

H
Haojun Liao 已提交
412
static bool isSelectivityWithTagsQuery(SQuery *pQuery) {
413 414
  bool    hasTags = false;
  int32_t numOfSelectivity = 0;
415

416
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
417
    int32_t functId = pQuery->pExpr1[i].base.functionId;
418 419 420 421
    if (functId == TSDB_FUNC_TAG_DUMMY || functId == TSDB_FUNC_TS_DUMMY) {
      hasTags = true;
      continue;
    }
422

H
Haojun Liao 已提交
423
    if ((aAggs[functId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
424 425 426
      numOfSelectivity++;
    }
  }
427

428 429 430
  if (numOfSelectivity > 0 && hasTags) {
    return true;
  }
431

432 433 434
  return false;
}

H
Haojun Liao 已提交
435
static bool isProjQuery(SQuery *pQuery) {
436
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
437
    int32_t functId = pQuery->pExpr1[i].base.functionId;
438 439 440 441 442 443 444 445
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

H
Haojun Liao 已提交
446
static bool isTsCompQuery(SQuery *pQuery) { return pQuery->pExpr1[0].base.functionId == TSDB_FUNC_TS_COMP; }
447

H
Haojun Liao 已提交
448
static bool limitOperator(SQuery* pQuery, void* qinfo) {
449 450
  if ((pQuery->limit.limit > 0) && (pQuery->rec.total + pQuery->rec.rows > pQuery->limit.limit)) {
    pQuery->rec.rows = pQuery->limit.limit - pQuery->rec.total;
451

452
    qDebug("QInfo:%p discard remain data due to result limitation, limit:%"PRId64", current return:%" PRId64 ", total:%"PRId64,
H
Haojun Liao 已提交
453
           qinfo, pQuery->limit.limit, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows);
454
    assert(pQuery->rec.rows >= 0);
455 456 457
    setQueryStatus(pQuery, QUERY_COMPLETED);
    return true;
  }
458

459 460 461 462
  return false;
}

static bool isTopBottomQuery(SQuery *pQuery) {
463
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
464
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
465 466 467
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
468

469 470 471 472
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      return true;
    }
  }
473

474 475 476
  return false;
}

477 478 479
static bool timeWindowInterpoRequired(SQuery *pQuery) {
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
480
    if (functionId == TSDB_FUNC_TWA || functionId == TSDB_FUNC_INTERP) {
481 482 483 484 485 486 487
      return true;
    }
  }

  return false;
}

H
Haojun Liao 已提交
488
static bool hasTagValOutput(SQuery* pQuery) {
H
Haojun Liao 已提交
489
  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
H
Haojun Liao 已提交
490 491 492 493
  if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP) {
    return true;
  } else {  // set tag value, by which the results are aggregated.
    for (int32_t idx = 0; idx < pQuery->numOfOutput; ++idx) {
H
Haojun Liao 已提交
494
      SExprInfo *pLocalExprInfo = &pQuery->pExpr1[idx];
H
Haojun Liao 已提交
495 496 497 498 499 500 501 502 503 504 505

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

  return false;
}

H
Haojun Liao 已提交
506 507 508 509 510 511 512 513 514 515 516 517
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;
}

518 519 520 521 522 523 524 525
/**
 * @param pQuery
 * @param col
 * @param pDataBlockInfo
 * @param pStatis
 * @param pColStatis
 * @return
 */
H
Haojun Liao 已提交
526
static bool hasNullValue(SColIndex* pColIndex, SDataStatis *pStatis, SDataStatis **pColStatis) {
H
Haojun Liao 已提交
527
  if (pStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
H
Haojun Liao 已提交
528 529
    *pColStatis = &pStatis[pColIndex->colIndex];
    assert((*pColStatis)->colId == pColIndex->colId);
H
hjxilinx 已提交
530 531
  } else {
    *pColStatis = NULL;
532
  }
533

H
Haojun Liao 已提交
534
  if (TSDB_COL_IS_TAG(pColIndex->flag) || TSDB_COL_IS_UD_COL(pColIndex->flag) || pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
535 536 537
    return false;
  }

538 539 540
  if ((*pColStatis) != NULL && (*pColStatis)->numOfNull == 0) {
    return false;
  }
541

542 543 544
  return true;
}

H
Haojun Liao 已提交
545
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
546
                                             int16_t bytes, bool masterscan, uint64_t uid) {
547
  bool existed = false;
H
Haojun Liao 已提交
548
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567

  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.
  if (QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQuery)) {
    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;
        }
      }
    }
568
  } else {
569 570
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
571
    }
572
  }
573

574
  if (!existed) {
H
Haojun Liao 已提交
575
    // TODO refactor
H
Haojun Liao 已提交
576
    // more than the capacity, reallocate the resources
H
Haojun Liao 已提交
577
    if (pResultRowInfo->size >= pResultRowInfo->capacity) {
H
Haojun Liao 已提交
578
      int64_t newCapacity = 0;
H
Haojun Liao 已提交
579 580
      if (pResultRowInfo->capacity > 10000) {
        newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25);
581
      } else {
H
Haojun Liao 已提交
582
        newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5);
583 584
      }

H
Haojun Liao 已提交
585
      char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES));
586 587
      if (t == NULL) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
588
      }
589

H
Haojun Liao 已提交
590
      pResultRowInfo->pResult = (SResultRow **)t;
591

H
Haojun Liao 已提交
592 593
      int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity;
      memset(&pResultRowInfo->pResult[pResultRowInfo->capacity], 0, POINTER_BYTES * inc);
594

H
Haojun Liao 已提交
595
      pResultRowInfo->capacity = (int32_t)newCapacity;
596
    }
597

598 599 600 601 602 603 604 605 606 607 608 609 610
    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;
611
    }
H
Haojun Liao 已提交
612

613
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
614
    pResultRowInfo->curIndex = pResultRowInfo->size++;
615
  }
616

617
  // too many time window in query
H
Haojun Liao 已提交
618
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
619 620 621
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
622
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
623 624 625
}

// get the correct time window according to the handled timestamp
H
Haojun Liao 已提交
626
static STimeWindow getActiveTimeWindow(SResultRowInfo *pWindowResInfo, int64_t ts, SQuery *pQuery) {
627
  STimeWindow w = {0};
628

629
 if (pWindowResInfo->curIndex == -1) {  // the first window, from the previous stored value
H
Haojun Liao 已提交
630 631 632 633 634 635 636 637 638
   if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
     if (QUERY_IS_ASC_QUERY(pQuery)) {
       getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, &w);
     } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
       getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, &w);
     }

     pWindowResInfo->prevSKey = w.skey;
   } else {
639
    w.skey = pWindowResInfo->prevSKey;
H
Haojun Liao 已提交
640 641
   }

642
    if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
643
      w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
644
    } else {
645
      w.ekey = w.skey + pQuery->interval.interval - 1;
646
    }
647
  } else {
648
    int32_t slot = curTimeWindowIndex(pWindowResInfo);
649
    SResultRow* pWindowRes = getResultRow(pWindowResInfo, slot);
650
    w = pWindowRes->win;
651
  }
652

653
  if (w.skey > ts || w.ekey < ts) {
654 655 656
    if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
      w.skey = taosTimeTruncate(ts, &pQuery->interval, pQuery->precision);
      w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
657 658
    } else {
      int64_t st = w.skey;
659

660
      if (st > ts) {
661
        st -= ((st - ts + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
662
      }
663

664
      int64_t et = st + pQuery->interval.interval - 1;
665
      if (et < ts) {
666
        st += ((ts - et + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
667
      }
668

669
      w.skey = st;
670
      w.ekey = w.skey + pQuery->interval.interval - 1;
671
    }
672
  }
673

674 675 676 677 678 679 680
  /*
   * 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.
   */
  if (w.ekey > pQuery->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) {
    w.ekey = pQuery->window.ekey;
  }
681

682 683 684
  return w;
}

H
Haojun Liao 已提交
685
static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf *pResultBuf, int32_t tid,
686
                                     int32_t numOfRowsPerPage) {
687
  if (pWindowRes->pageId != -1) {
688 689
    return 0;
  }
690

691
  tFilePage *pData = NULL;
692

693 694
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
695
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
696

H
Haojun Liao 已提交
697
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
698
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
699
  } else {
H
Haojun Liao 已提交
700 701 702
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
703

704
    if (pData->num >= numOfRowsPerPage) {
H
Haojun Liao 已提交
705 706
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
707
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
708
      if (pData != NULL) {
709
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
710 711 712
      }
    }
  }
713

714 715 716
  if (pData == NULL) {
    return -1;
  }
717

718
  // set the number of rows in current disk page
719 720 721
  if (pWindowRes->pageId == -1) {  // not allocated yet, allocate new buffer
    pWindowRes->pageId = pageId;
    pWindowRes->rowId = (int32_t)(pData->num++);
H
Haojun Liao 已提交
722

723
    assert(pWindowRes->pageId >= 0);
724
  }
725

726 727 728
  return 0;
}

729
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
H
Haojun Liao 已提交
730
                                       bool masterscan, SResultRow **pResult, int64_t groupId) {
731 732
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
733

734
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
735
  if (pResultRow == NULL) {
736 737
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
738
  }
739

740
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
741
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
742
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->numOfRowsPerPage);
H
Haojun Liao 已提交
743
    if (ret != TSDB_CODE_SUCCESS) {
744 745 746
      return -1;
    }
  }
747

748
  // set time window for current result
H
Haojun Liao 已提交
749
  pResultRow->win = (*win);
750
  *pResult = pResultRow;
H
Haojun Liao 已提交
751
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow);
752

753 754 755
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
756
static bool getResultRowStatus(SResultRowInfo *pWindowResInfo, int32_t slot) {
757
  assert(slot >= 0 && slot < pWindowResInfo->size);
758
  return pWindowResInfo->pResult[slot]->closed;
759 760
}

761 762 763 764 765 766 767 768 769 770 771 772 773 774
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP   = 2,
} SResultTsInterpType;

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 已提交
775
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
776 777 778 779 780 781 782 783
  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 已提交
784
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
785 786
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
787

H
Haojun Liao 已提交
788 789 790 791
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
792

H
Haojun Liao 已提交
793 794 795 796 797 798 799 800 801 802 803 804
      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;
      }
805 806
    }
  }
807

H
Haojun Liao 已提交
808
  assert(forwardStep > 0);
809 810 811
  return forwardStep;
}

812
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
813
  int64_t skey = TSKEY_INITIAL_VAL;
814 815 816
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
817
    if (pResult->closed) {
818
      break;
H
Haojun Liao 已提交
819 820
    }

821
    // new closed result rows
822 823 824 825 826 827 828 829 830 831
    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 已提交
832
    } else {
833 834 835 836 837
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
838 839 840
    }
  }

841
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
842
  if (skey == TSKEY_INITIAL_VAL) {
843
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
844 845
  } else {

846 847 848 849 850
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
851
    }
852

D
fix bug  
dapan1121 已提交
853
    if (i == pResultRowInfo->size - 1) {
854
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
855 856 857 858
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

859
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
860
  }
861
}
862

863
static void updateResultRowIndex(SResultRowInfo* pResultRowInfo, STableQueryInfo* pTableQueryInfo, bool ascQuery, bool timeWindowInterpo) {
864
  if ((pTableQueryInfo->lastKey > pTableQueryInfo->win.ekey && ascQuery) || (pTableQueryInfo->lastKey < pTableQueryInfo->win.ekey && (!ascQuery))) {
865 866 867
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
868
    int32_t step = ascQuery? 1:-1;
869
    doUpdateResultRowIndex(pResultRowInfo, pTableQueryInfo->lastKey - step, ascQuery, timeWindowInterpo);
870
  }
871 872 873
}

static int32_t getNumOfRowsInTimeWindow(SQuery *pQuery, SDataBlockInfo *pDataBlockInfo, TSKEY *pPrimaryColumn,
H
hjxilinx 已提交
874
                                        int32_t startPos, TSKEY ekey, __block_search_fn_t searchFn, bool updateLastKey) {
875
  assert(startPos >= 0 && startPos < pDataBlockInfo->rows);
876

H
Haojun Liao 已提交
877
  int32_t num   = -1;
878
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
879
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
880

H
hjxilinx 已提交
881
  STableQueryInfo* item = pQuery->current;
882

883 884
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (ekey < pDataBlockInfo->window.ekey) {
885
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
886 887
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
888 889
      }
    } else {
890
      num = pDataBlockInfo->rows - startPos;
891
      if (updateLastKey) {
H
hjxilinx 已提交
892
        item->lastKey = pDataBlockInfo->window.ekey + step;
893 894 895 896
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
897
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
898 899
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
900 901 902 903
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
904
        item->lastKey = pDataBlockInfo->window.skey + step;
905 906 907
      }
    }
  }
908

H
Haojun Liao 已提交
909
  assert(num > 0);
910 911 912
  return num;
}

H
Haojun Liao 已提交
913
static char *getDataBlock(SQuery* pQuery, SArithmeticSupport *sas, int32_t col, int32_t size, SArray *pDataBlock);
H
Haojun Liao 已提交
914 915 916 917

static void doBlockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pWin, int32_t offset,
                                      int32_t forwardStep, TSKEY *tsCol, int32_t numOfTotal, SArray *pDataBlock) {
  SQuery *        pQuery = pRuntimeEnv->pQuery;
918
  SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
919

H
Haojun Liao 已提交
920 921
  bool hasPrev = pCtx[0].preAggVals.isSet;

922 923
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
924
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
925

H
Haojun Liao 已提交
926
    char *dataBlock = getDataBlock(pQuery, &pRuntimeEnv->sasArray[k], k, numOfTotal, pDataBlock);
H
Haojun Liao 已提交
927 928 929 930 931 932 933 934 935

    int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1);
    if (dataBlock != NULL) {
      pCtx[k].pInput = (char *)dataBlock + pos * pCtx[k].inputBytes;
    }

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

H
Haojun Liao 已提交
937
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
938

939 940 941 942 943
    // 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 已提交
944

945 946
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
947
    }
948 949 950

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
951 952 953
  }
}

H
Haojun Liao 已提交
954 955
static void doRowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pWin, int32_t offset) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
956
  SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
957

958
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
959
    pCtx[k].startTs = pWin->skey;
960

961 962 963
    int32_t functionId = pQuery->pExpr1[k].base.functionId;
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunctionF(&pCtx[k], offset);
964 965 966 967
    }
  }
}

H
Haojun Liao 已提交
968
static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
969
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
970
  getNextTimeWindow(pQuery, pNext);
971

H
Haojun Liao 已提交
972
  // next time window is not in current block
H
Haojun Liao 已提交
973 974
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
975 976
    return -1;
  }
977

H
Haojun Liao 已提交
978 979
  TSKEY startKey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
980
    startKey = pNext->skey;
H
Haojun Liao 已提交
981 982
    if (startKey < pQuery->window.skey) {
      startKey = pQuery->window.skey;
983
    }
H
Haojun Liao 已提交
984
  } else {
H
Haojun Liao 已提交
985
    startKey = pNext->ekey;
H
Haojun Liao 已提交
986 987
    if (startKey > pQuery->window.skey) {
      startKey = pQuery->window.skey;
988
    }
H
Haojun Liao 已提交
989
  }
990

H
Haojun Liao 已提交
991
  int32_t startPos = 0;
H
Haojun Liao 已提交
992

H
Haojun Liao 已提交
993
  // tumbling time window query, a special case of sliding time window query
994
  if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) {
H
Haojun Liao 已提交
995 996 997
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
998
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
999
      startPos = 0;
H
Haojun Liao 已提交
1000
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
1001 1002 1003 1004
      startPos = pDataBlockInfo->rows - 1;
    } else {
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order);
    }
H
Haojun Liao 已提交
1005
  }
1006

H
Haojun Liao 已提交
1007 1008 1009 1010
  /*
   * 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 已提交
1011 1012 1013
  if (primaryKeys == NULL) {
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
1014
    } else {
H
Haojun Liao 已提交
1015
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
1016
    }
H
Haojun Liao 已提交
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
  } else {
    if (QUERY_IS_ASC_QUERY(pQuery) && primaryKeys[startPos] > pNext->ekey) {
      TSKEY next = primaryKeys[startPos];
      if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
      } else {
        pNext->ekey += ((next - pNext->ekey + pQuery->interval.sliding - 1)/pQuery->interval.sliding) * pQuery->interval.sliding;
        pNext->skey = pNext->ekey - pQuery->interval.interval + 1;
      }
    } else if ((!QUERY_IS_ASC_QUERY(pQuery)) && primaryKeys[startPos] < pNext->skey) {
      TSKEY next = primaryKeys[startPos];
      if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
      } else {
        pNext->skey -= ((pNext->skey - next + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
        pNext->ekey = pNext->skey + pQuery->interval.interval - 1;
      }
1036
    }
1037
  }
1038

H
Haojun Liao 已提交
1039
  return startPos;
1040 1041
}

H
Haojun Liao 已提交
1042
static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
  TSKEY ekey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    ekey = pWindow->ekey;
    if (ekey > pQuery->window.ekey) {
      ekey = pQuery->window.ekey;
    }
  } else {
    ekey = pWindow->skey;
    if (ekey < pQuery->window.ekey) {
      ekey = pQuery->window.ekey;
    }
  }
1055

1056 1057 1058
  return ekey;
}

H
hjxilinx 已提交
1059 1060
//todo binary search
static void* getDataBlockImpl(SArray* pDataBlock, int32_t colId) {
S
TD-1057  
Shengliang Guan 已提交
1061
  int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock);
1062

H
hjxilinx 已提交
1063 1064 1065 1066 1067 1068
  for (int32_t i = 0; i < numOfCols; ++i) {
    SColumnInfoData *p = taosArrayGet(pDataBlock, i);
    if (colId == p->info.colId) {
      return p->pData;
    }
  }
1069

H
hjxilinx 已提交
1070 1071 1072
  return NULL;
}

H
Haojun Liao 已提交
1073

H
Haojun Liao 已提交
1074
// todo refactor
H
Haojun Liao 已提交
1075
static char *getDataBlock(SQuery* pQuery, SArithmeticSupport *sas, int32_t col, int32_t size, SArray *pDataBlock) {
dengyihao's avatar
dengyihao 已提交
1076 1077 1078
  if (pDataBlock == NULL) {
    return NULL;
  }
1079

H
Haojun Liao 已提交
1080
  char *dataBlock = NULL;
H
Haojun Liao 已提交
1081
  int32_t functionId = pQuery->pExpr1[col].base.functionId;
1082
  if (functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
1083
    sas->pArithExpr = &pQuery->pExpr1[col];
1084 1085 1086
    sas->offset     = (QUERY_IS_ASC_QUERY(pQuery))? pQuery->pos : pQuery->pos - (size - 1);
    sas->colList    = pQuery->colList;
    sas->numOfCols  = pQuery->numOfCols;
H
Haojun Liao 已提交
1087

1088
    // here the pQuery->colList and sas->colList are identical
S
TD-1057  
Shengliang Guan 已提交
1089
    int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock);
1090
    for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
1091
      SColumnInfo *pColMsg = &pQuery->colList[i];
1092

1093 1094 1095 1096 1097 1098 1099 1100
      dataBlock = NULL;
      for (int32_t k = 0; k < numOfCols; ++k) {  //todo refactor
        SColumnInfoData *p = taosArrayGet(pDataBlock, k);
        if (pColMsg->colId == p->info.colId) {
          dataBlock = p->pData;
          break;
        }
      }
1101

1102
      assert(dataBlock != NULL);
1103
      sas->data[i] = dataBlock;  // start from the offset
1104
    }
1105

1106
  } else {  // other type of query function
H
Haojun Liao 已提交
1107
    SColIndex *pCol = &pQuery->pExpr1[col].base.colInfo;
H
Haojun Liao 已提交
1108
    if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) {
H
Haojun Liao 已提交
1109
      SColIndex* pColIndex = &pQuery->pExpr1[col].base.colInfo;
H
Haojun Liao 已提交
1110 1111 1112 1113
      SColumnInfoData *p = taosArrayGet(pDataBlock, pColIndex->colIndex);
      assert(p->info.colId == pColIndex->colId);

      dataBlock = p->pData;
H
Haojun Liao 已提交
1114 1115
    } else {
      dataBlock = NULL;
1116 1117
    }
  }
1118

1119 1120 1121
  return dataBlock;
}

H
Haojun Liao 已提交
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
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;
    }
  }
}

1134
// window start key interpolation
1135 1136
static bool setTimeWindowInterpolationStartTs(SQueryRuntimeEnv* pRuntimeEnv, int32_t pos, int32_t numOfRows,
    SArray* pDataBlock, TSKEY* tsCols, STimeWindow* win, int16_t type) {
1137 1138
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
1139
  TSKEY curTs  = tsCols[pos];
1140 1141
  TSKEY lastTs = *(TSKEY *) pRuntimeEnv->prevRow[0];

H
Haojun Liao 已提交
1142 1143 1144 1145
  // 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
  TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->skey:win->ekey;
  if (key == curTs) {
H
Haojun Liao 已提交
1146
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
1147
    return true;
H
Haojun Liao 已提交
1148
  }
1149

H
Haojun Liao 已提交
1150
  if (lastTs == INT64_MIN && ((pos == 0 && QUERY_IS_ASC_QUERY(pQuery)) || (pos == (numOfRows - 1) && !QUERY_IS_ASC_QUERY(pQuery)))) {
H
Haojun Liao 已提交
1151
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1152
    return true;
1153 1154
  }

H
Haojun Liao 已提交
1155 1156 1157
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
  TSKEY   prevTs = ((pos == 0 && QUERY_IS_ASC_QUERY(pQuery)) || (pos == (numOfRows - 1) && !QUERY_IS_ASC_QUERY(pQuery)))?
      lastTs:tsCols[pos - step];
1158

H
Haojun Liao 已提交
1159 1160 1161
  doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, pos - step, curTs, pos, key, RESULT_ROW_START_INTERP);
  return true;
}
1162

H
Haojun Liao 已提交
1163 1164 1165
static bool setTimeWindowInterpolationEndTs(SQueryRuntimeEnv* pRuntimeEnv, int32_t endRowIndex, SArray* pDataBlock, TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
  TSKEY   actualEndKey = tsCols[endRowIndex];
1166

H
Haojun Liao 已提交
1167
  TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->ekey:win->skey;
1168

H
Haojun Liao 已提交
1169 1170
  // not ended in current data block, do not invoke interpolation
  if ((key > blockEkey && QUERY_IS_ASC_QUERY(pQuery)) || (key < blockEkey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
1171
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1172 1173
    return false;
  }
1174

H
Haojun Liao 已提交
1175 1176
  // there is actual end point of current time window, no interpolation need
  if (key == actualEndKey) {
H
Haojun Liao 已提交
1177
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP);
1178 1179
    return true;
  }
H
Haojun Liao 已提交
1180 1181 1182 1183 1184 1185 1186 1187

  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
  int32_t nextRowIndex = endRowIndex + step;
  assert(nextRowIndex >= 0);

  TSKEY nextKey = tsCols[nextRowIndex];
  doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, actualEndKey, endRowIndex, nextKey, nextRowIndex, key, RESULT_ROW_END_INTERP);
  return true;
1188 1189
}

1190 1191
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
    int32_t rowIndex) {
1192 1193 1194 1195 1196 1197 1198
  if (pDataBlock == NULL) {
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  for (int32_t k = 0; k < pQuery->numOfCols; ++k) {
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, k);
H
Haojun Liao 已提交
1199
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
1200 1201 1202
  }
}

H
Haojun Liao 已提交
1203
static TSKEY getStartTsKey(SQuery* pQuery, SDataBlockInfo* pDataBlockInfo, const TSKEY* tsCols, int32_t step) {
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
  TSKEY ts = TSKEY_INITIAL_VAL;

  if (tsCols == NULL) {
    ts = QUERY_IS_ASC_QUERY(pQuery) ? pDataBlockInfo->window.skey : pDataBlockInfo->window.ekey;
  } else {
    int32_t offset = GET_COL_DATA_POS(pQuery, 0, step);
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
1216 1217
static void doWindowBorderInterpolation(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray *pDataBlock,
    SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep) {
H
Haojun Liao 已提交
1218 1219
  SQuery* pQuery = pRuntimeEnv->pQuery;
  if (!pQuery->timeWindowInterpo) {
H
Haojun Liao 已提交
1220 1221 1222 1223 1224
    return;
  }

  assert(pDataBlock != NULL);

1225 1226
  int32_t fillType = pQuery->fillType;

H
Haojun Liao 已提交
1227 1228 1229 1230 1231 1232 1233 1234
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

  SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, 0);

  TSKEY  *tsCols = (TSKEY *)(pColInfo->pData);
  bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
  if (!done) {
    int32_t startRowIndex = startPos;
1235
    bool    interp = setTimeWindowInterpolationStartTs(pRuntimeEnv, startRowIndex, pDataBlockInfo->rows, pDataBlock, tsCols, win, fillType);
H
Haojun Liao 已提交
1236 1237 1238 1239 1240 1241 1242
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    }
  } else {
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
  }

1243 1244 1245 1246 1247 1248
  // point interpolation does not require the end key time window interpolation.
  if (isPointInterpoQuery(pQuery)) {
    return;
  }

  // interpolation query does not generate the time window end interpolation
H
Haojun Liao 已提交
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
  done = resultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
  if (!done) {
    int32_t endRowIndex = startPos + (forwardStep - 1) * step;

    TSKEY endKey = QUERY_IS_ASC_QUERY(pQuery)? pDataBlockInfo->window.ekey:pDataBlockInfo->window.skey;
    bool  interp = setTimeWindowInterpolationEndTs(pRuntimeEnv, endRowIndex, pDataBlock, tsCols, endKey, win);
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
    }
  } else {
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP);
  }
}

H
Haojun Liao 已提交
1263

H
Haojun Liao 已提交
1264
static void setInputSDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock, int32_t order) {
H
Haojun Liao 已提交
1265 1266 1267
  if (pCtx[0].pInput == NULL && pSDataBlock->pDataBlock != NULL) {
    for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
      pCtx[i].size = pSDataBlock->info.rows;
H
Haojun Liao 已提交
1268
      pCtx[i].order = order;
H
Haojun Liao 已提交
1269

H
Haojun Liao 已提交
1270
      SColIndex *pCol = &pOperator->pExpr[i].base.colInfo;
H
Haojun Liao 已提交
1271
      if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) {
H
Haojun Liao 已提交
1272
        SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo;
H
Haojun Liao 已提交
1273 1274 1275
        SColumnInfoData *p = taosArrayGet(pSDataBlock->pDataBlock, pColIndex->colIndex);
        assert(p->info.colId == pColIndex->colId);

H
Haojun Liao 已提交
1276 1277
        SQLFunctionCtx* pCtx1 = &pCtx[i];
        pCtx1->pInput = p->pData;
H
Haojun Liao 已提交
1278

H
Haojun Liao 已提交
1279
        uint32_t status = aAggs[pCtx1->functionId].status;
H
Haojun Liao 已提交
1280 1281
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
          SColumnInfoData *tsInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1282
          pCtx1->ptsList = tsInfo->pData;
H
Haojun Liao 已提交
1283
        }
H
Haojun Liao 已提交
1284 1285
      }
    }
H
Haojun Liao 已提交
1286 1287 1288
  } else {
    for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
      pCtx[i].size = pSDataBlock->info.rows;
H
Haojun Liao 已提交
1289
      pCtx[i].order = order;
H
Haojun Liao 已提交
1290
    }
H
Haojun Liao 已提交
1291 1292 1293
  }
}

H
Haojun Liao 已提交
1294 1295
static void aggApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1296

H
Haojun Liao 已提交
1297 1298
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
    setBlockStatisInfo(&pCtx[k], pSDataBlock, &pOperator->pExpr[k].base.colInfo);
H
Haojun Liao 已提交
1299 1300

    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1301 1302 1303 1304 1305 1306 1307
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      pCtx[k].startTs = pQuery->window.skey;
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

H
Haojun Liao 已提交
1308 1309 1310
static void setArithParams(SArithmeticSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
  sas->numOfCols = (int32_t) pSDataBlock->info.numOfCols;
  sas->pArithExpr = pExprInfo;
H
Haojun Liao 已提交
1311

H
Haojun Liao 已提交
1312 1313 1314 1315
  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;
H
Haojun Liao 已提交
1316 1317
  }

H
Haojun Liao 已提交
1318
  sas->data = calloc(sas->numOfCols, POINTER_BYTES);
H
Haojun Liao 已提交
1319 1320

  // set the input column data
H
Haojun Liao 已提交
1321
  for (int32_t f = 0; f < pSDataBlock->info.numOfCols; ++f) {
H
Haojun Liao 已提交
1322
    SColumnInfoData *pColumnInfoData = taosArrayGet(pSDataBlock->pDataBlock, f);
H
Haojun Liao 已提交
1323
    sas->data[f] = pColumnInfoData->pData;
H
Haojun Liao 已提交
1324
  }
H
Haojun Liao 已提交
1325
}
H
Haojun Liao 已提交
1326

H
Haojun Liao 已提交
1327 1328
static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, SExprInfo *pExprInfo, int32_t numOfOutput) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1329

H
Haojun Liao 已提交
1330 1331 1332 1333 1334 1335 1336 1337 1338
  for (int32_t k = 0; k < numOfOutput; ++k) {
    int32_t functionId = pExprInfo[k].base.functionId;
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      pCtx[k].startTs = pQuery->window.skey;
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

H
Haojun Liao 已提交
1339
static void hashIntervalAgg(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) {
H
Haojun Liao 已提交
1340 1341 1342
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
H
Haojun Liao 已提交
1343
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1344

H
Haojun Liao 已提交
1345 1346 1347 1348
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
    tsCols = pColDataInfo->pData;
H
Haojun Liao 已提交
1349
    assert(tsCols[0] == pSDataBlock->info.window.skey && tsCols[pSDataBlock->info.rows-1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1350 1351 1352 1353 1354 1355
  }

  TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info, tsCols, step);

  STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQuery);
  bool masterScan = (pRuntimeEnv->scanFlag == MASTER_SCAN)? true:false;
H
Haojun Liao 已提交
1356 1357

  SResultRow *pResult = NULL;
H
Haojun Liao 已提交
1358
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, 0);
H
Haojun Liao 已提交
1359 1360 1361 1362 1363 1364 1365 1366
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
    //      goto _end;
  }

  int32_t forwardStep = 0;
  int32_t startPos = pQuery->pos;

  TSKEY ekey = reviseWindowEkey(pQuery, &win);
H
Haojun Liao 已提交
1367
  forwardStep = getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, pQuery->pos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1368 1369

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1370
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1371 1372
  if (prevIndex != -1 && prevIndex < curIndex && pQuery->timeWindowInterpo) {
    for (int32_t j = prevIndex; j < curIndex; ++j) {  // previous time window may be all closed already.
H
Haojun Liao 已提交
1373
      SResultRow *pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1374 1375 1376
      if (pRes->closed) {
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) && resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
        continue;
H
Haojun Liao 已提交
1377
      }
H
Haojun Liao 已提交
1378 1379

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1380
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, 0);
H
Haojun Liao 已提交
1381 1382
      assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));

H
Haojun Liao 已提交
1383 1384
      int32_t p = QUERY_IS_ASC_QUERY(pQuery) ? 0 : pSDataBlock->info.rows - 1;
      doRowwiseTimeWindowInterpolation(pRuntimeEnv, pSDataBlock->pDataBlock, *(TSKEY *)pRuntimeEnv->prevRow[0], -1, tsCols[0], p,
H
Haojun Liao 已提交
1385 1386 1387 1388
                                       w.ekey, RESULT_ROW_END_INTERP);
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
      setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);

H
Haojun Liao 已提交
1389
      doBlockwiseApplyFunctions(pRuntimeEnv, &w, startPos, 0, tsCols, pSDataBlock->info.rows, pSDataBlock->pDataBlock);
H
Haojun Liao 已提交
1390 1391
    }

H
Haojun Liao 已提交
1392
    // restore current time window
H
Haojun Liao 已提交
1393
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, 0);
H
Haojun Liao 已提交
1394 1395 1396 1397
    assert(ret == TSDB_CODE_SUCCESS);
  }

  // window start key interpolation
H
Haojun Liao 已提交
1398 1399
  doWindowBorderInterpolation(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, pResult, &win, pQuery->pos, forwardStep);
  doBlockwiseApplyFunctions(pRuntimeEnv, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, pSDataBlock->pDataBlock);
H
Haojun Liao 已提交
1400 1401 1402 1403

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1404
    startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1405 1406
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1407 1408
    }

H
Haojun Liao 已提交
1409
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1410
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, 0);
H
Haojun Liao 已提交
1411 1412
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
      break;
H
Haojun Liao 已提交
1413 1414
    }

H
Haojun Liao 已提交
1415
    ekey = reviseWindowEkey(pQuery, &nextWin);
H
Haojun Liao 已提交
1416
    forwardStep = getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1417 1418

    // window start(end) key interpolation
H
Haojun Liao 已提交
1419 1420
    doWindowBorderInterpolation(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, pResult, &nextWin, startPos, forwardStep);
    doBlockwiseApplyFunctions(pRuntimeEnv, &nextWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, pSDataBlock->pDataBlock);
H
Haojun Liao 已提交
1421 1422 1423
  }
}

H
Haojun Liao 已提交
1424 1425
static void hashGroupbyAgg(SQueryRuntimeEnv *pRuntimeEnv, SOperatorInfo* pOperator, SResultRowInfo *pResultRowInfo, SQLFunctionCtx *pCtx,
                           SSDataBlock *pSDataBlock, int32_t colIndex) {
H
Haojun Liao 已提交
1426 1427 1428 1429
  SQuery *pQuery = pRuntimeEnv->pQuery;

  STableQueryInfo* item = pQuery->current;

H
Haojun Liao 已提交
1430 1431 1432
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, colIndex);
  int16_t bytes = pColInfoData->info.bytes;
  int16_t type  = pColInfoData->info.type;
H
Haojun Liao 已提交
1433

H
Haojun Liao 已提交
1434
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
H
Haojun Liao 已提交
1435 1436
    int32_t offset = GET_COL_DATA_POS(pQuery, j, 1);

H
Haojun Liao 已提交
1437
    char *val = pColInfoData->pData + bytes * offset;
H
Haojun Liao 已提交
1438 1439 1440 1441
    if (isNull(val, type)) {  // ignore the null value
      continue;
    }

H
Haojun Liao 已提交
1442 1443
    // TODO compare with the previous value to speedup the query processing
    int32_t ret = setGroupResultOutputBuf_rv(pRuntimeEnv, pResultRowInfo, pCtx, pOperator->numOfOutput, val, type, bytes, item->groupIndex);
H
Haojun Liao 已提交
1444 1445 1446 1447
    if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
    }

H
Haojun Liao 已提交
1448 1449
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
      int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1450 1451 1452 1453 1454 1455 1456
      if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
        aAggs[functionId].xFunctionF(&pCtx[k], offset);
      }
    }
  }
}

1457
/**
H
Haojun Liao 已提交
1458
 * todo set the last value for pQueryTableInfo as in rowwiseapplyfunctions
1459 1460
 * @param pRuntimeEnv
 * @param forwardStep
1461
 * @param tsCols
1462 1463 1464 1465 1466
 * @param pFields
 * @param isDiskFileBlock
 * @return                  the incremental number of output value, so it maybe 0 for fixed number of query,
 *                          such as count/min/max etc.
 */
H
Haojun Liao 已提交
1467
static void blockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pStatis, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
1468
                                    SResultRowInfo *pWindowResInfo, __block_search_fn_t searchFn, SArray *pDataBlock) {
1469
  SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
1470
  bool            masterScan = IS_MASTER_SCAN(pRuntimeEnv);
1471

1472 1473 1474
  SQuery *pQuery  = pRuntimeEnv->pQuery;
  int64_t groupId = pQuery->current->groupIndex;

1475
  TSKEY  *tsCols = NULL;
1476
  if (pDataBlock != NULL) {
1477
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, 0);
1478
    tsCols = (TSKEY *)(pColInfo->pData);
1479
  }
1480

1481
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
1482
    char *dataBlock = getDataBlock(pQuery, &pRuntimeEnv->sasArray[k], k, pDataBlockInfo->rows, pDataBlock);
H
Haojun Liao 已提交
1483
    setExecParams(pQuery, &pCtx[k], dataBlock, tsCols, pDataBlockInfo, pStatis, &pQuery->pExpr1[k]);
1484
  }
1485

1486
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
H
Haojun Liao 已提交
1487
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
1488 1489
    int32_t prevIndex = curTimeWindowIndex(pWindowResInfo);

1490
    TSKEY ts = getStartTsKey(pQuery, pDataBlockInfo, tsCols, step);
H
Haojun Liao 已提交
1491
    STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery);
1492

1493
    SResultRow* pResult = NULL;
1494 1495 1496
    int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId);
    if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
      goto _end;
1497
    }
1498

H
Haojun Liao 已提交
1499 1500 1501
    int32_t forwardStep = 0;
    int32_t startPos = pQuery->pos;

1502 1503
    TSKEY ekey = reviseWindowEkey(pQuery, &win);
    forwardStep = getNumOfRowsInTimeWindow(pQuery, pDataBlockInfo, tsCols, pQuery->pos, ekey, searchFn, true);
H
Haojun Liao 已提交
1504

1505 1506
    // prev time window not interpolation yet.
    int32_t curIndex = curTimeWindowIndex(pWindowResInfo);
H
Haojun Liao 已提交
1507
    if (prevIndex != -1 && prevIndex < curIndex && pQuery->timeWindowInterpo) {
1508
      for(int32_t j = prevIndex; j < curIndex; ++j) { // previous time window may be all closed already.
1509
        SResultRow *pRes = pWindowResInfo->pResult[j];
1510 1511 1512 1513
        if (pRes->closed) {
          assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) && resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
          continue;
        }
H
Haojun Liao 已提交
1514

1515 1516 1517
        STimeWindow w = pRes->win;
        ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &w, masterScan, &pResult, groupId);
        assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1518

1519 1520 1521 1522
        int32_t p = QUERY_IS_ASC_QUERY(pQuery)? 0:pDataBlockInfo->rows-1;
        doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, *(TSKEY*) pRuntimeEnv->prevRow[0], -1,  tsCols[0], p, w.ekey, RESULT_ROW_END_INTERP);
        setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
        setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1523

H
Haojun Liao 已提交
1524
        doBlockwiseApplyFunctions(pRuntimeEnv, &w, startPos, 0, tsCols, pDataBlockInfo->rows, pDataBlock);
H
Haojun Liao 已提交
1525 1526
      }

1527 1528 1529
      // restore current time window
      ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId);
      assert (ret == TSDB_CODE_SUCCESS);
1530
    }
1531

1532 1533
    // window start key interpolation
    doWindowBorderInterpolation(pRuntimeEnv, pDataBlockInfo, pDataBlock, pResult, &win, pQuery->pos, forwardStep);
H
Haojun Liao 已提交
1534
    doBlockwiseApplyFunctions(pRuntimeEnv, &win, startPos, forwardStep, tsCols, pDataBlockInfo->rows, pDataBlock);
1535

1536
    STimeWindow nextWin = win;
1537
    while (1) {
H
Haojun Liao 已提交
1538
      int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1539
      startPos = getNextQualifiedWindow(pQuery, &nextWin, pDataBlockInfo, tsCols, searchFn, prevEndPos);
1540 1541 1542
      if (startPos < 0) {
        break;
      }
1543

1544
      // null data, failed to allocate more memory buffer
1545 1546
      int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &nextWin, masterScan, &pResult, groupId);
      if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
1547 1548
        break;
      }
1549

1550
      ekey = reviseWindowEkey(pQuery, &nextWin);
H
Haojun Liao 已提交
1551
      forwardStep = getNumOfRowsInTimeWindow(pQuery, pDataBlockInfo, tsCols, startPos, ekey, searchFn, true);
1552

1553
      // window start(end) key interpolation
H
Haojun Liao 已提交
1554
      doWindowBorderInterpolation(pRuntimeEnv, pDataBlockInfo, pDataBlock, pResult, &nextWin, startPos, forwardStep);
H
Haojun Liao 已提交
1555
      doBlockwiseApplyFunctions(pRuntimeEnv, &nextWin, startPos, forwardStep, tsCols, pDataBlockInfo->rows, pDataBlock);
1556
    }
1557

1558 1559 1560 1561 1562 1563
  } else {
    /*
     * the sqlfunctionCtx parameters should be set done before all functions are invoked,
     * since the selectivity + tag_prj query needs all parameters been set done.
     * tag_prj function are changed to be TSDB_FUNC_TAG_DUMMY
     */
1564
    for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
1565
      int32_t functionId = pQuery->pExpr1[k].base.functionId;
1566
      if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
1567
        pCtx[k].startTs = pQuery->window.skey;
1568 1569 1570 1571
        aAggs[functionId].xFunction(&pCtx[k]);
      }
    }
  }
1572

1573
  _end:
H
Haojun Liao 已提交
1574
  if (pQuery->timeWindowInterpo) {
1575 1576
    int32_t rowIndex = QUERY_IS_ASC_QUERY(pQuery)? pDataBlockInfo->rows-1:0;
    saveDataBlockLastRow(pRuntimeEnv, pDataBlockInfo, pDataBlock, rowIndex);
1577
  }
1578 1579
}

H
Haojun Liao 已提交
1580
static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo, char *pData, int16_t type, int16_t bytes, int32_t groupIndex) {
1581
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
1582

H
Haojun Liao 已提交
1583
  // not assign result buffer yet, add new result buffer, TODO remove it
1584 1585 1586 1587 1588 1589 1590
  char* d = pData;
  int16_t len = bytes;
  if (type == TSDB_DATA_TYPE_BINARY||type == TSDB_DATA_TYPE_NCHAR) {
    d = varDataVal(pData);
    len = varDataLen(pData);
  } else if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) {
    SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
H
Haojun Liao 已提交
1591
    qError("QInfo:%p group by not supported on double/float columns, abort", pQInfo);
1592
    return -1;
1593 1594
  }

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

  int64_t v = -1;
H
Haojun Liao 已提交
1599
  GET_TYPED_DATA(v, int64_t, type, pData);
1600
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
1601 1602 1603 1604 1605 1606
    if (pResultRow->key == NULL) {
      pResultRow->key = malloc(varDataTLen(pData));
      varDataCopy(pResultRow->key, pData);
    } else {
      assert(memcmp(pResultRow->key, pData, varDataTLen(pData)) == 0);
    }
1607
  } else {
H
Haojun Liao 已提交
1608 1609
    pResultRow->win.skey = v;
    pResultRow->win.ekey = v;
1610
  }
1611

H
Haojun Liao 已提交
1612
  if (pResultRow->pageId == -1) {
1613
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->numOfRowsPerPage);
1614 1615 1616 1617
    if (ret != 0) {
      return -1;
    }
  }
1618

H
Haojun Liao 已提交
1619
  setResultOutputBuf(pRuntimeEnv, pResultRow);
H
Haojun Liao 已提交
1620
  initCtxOutputBuf(pRuntimeEnv, pRuntimeEnv->pCtx);
1621 1622
  return TSDB_CODE_SUCCESS;
}
H
Haojun Liao 已提交
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
static int32_t setGroupResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo,
    SQLFunctionCtx * pCtx, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex) {
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;

  // 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);
  } else if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) {
    SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
    qError("QInfo:%p group by not supported on double/float columns, abort", pQInfo);
    return -1;
  }

  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, d, len, true, groupIndex);
  assert (pResultRow != NULL);

  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;
  }

  if (pResultRow->pageId == -1) {
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->numOfRowsPerPage);
    if (ret != 0) {
      return -1;
    }
  }

  setResultOutputBuf_rv(pRuntimeEnv, pResultRow, pCtx, numOfCols);
  initCtxOutputBuf_rv(pCtx, numOfCols);
  return TSDB_CODE_SUCCESS;
}
1667

1668
static char *getGroupbyColumnData(SQuery *pQuery, int16_t *type, int16_t *bytes, SArray* pDataBlock) {
1669
  SSqlGroupbyExpr *pGroupbyExpr = pQuery->pGroupbyExpr;
1670

1671
  for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) {
1672
    SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, k);
Y
TD-1230  
yihaoDeng 已提交
1673
    if (TSDB_COL_IS_TAG(pColIndex->flag)) {
1674 1675
      continue;
    }
1676

1677
    int16_t colIndex = -1;
1678
    int32_t colId = pColIndex->colId;
1679

1680
    for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
1681
      if (pQuery->colList[i].colId == colId) {
1682 1683 1684 1685
        colIndex = i;
        break;
      }
    }
1686

1687
    assert(colIndex >= 0 && colIndex < pQuery->numOfCols);
1688

1689 1690
    *type = pQuery->colList[colIndex].type;
    *bytes = pQuery->colList[colIndex].bytes;
H
Haojun Liao 已提交
1691

1692
    /*
1693 1694 1695
     *  the colIndex is acquired from the first tables of all qualified tables in this vnode during query prepare
     * stage, the remain tables may not have the required column in cache actually. So, the validation of required
     * column in cache with the corresponding schema is reinforced.
1696
     */
S
TD-1057  
Shengliang Guan 已提交
1697
    int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock);
1698

1699 1700 1701 1702 1703 1704
    for (int32_t i = 0; i < numOfCols; ++i) {
      SColumnInfoData *p = taosArrayGet(pDataBlock, i);
      if (pColIndex->colId == p->info.colId) {
        return p->pData;
      }
    }
1705
  }
1706

1707
  return NULL;
1708 1709
}

H
Haojun Liao 已提交
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
static int32_t getGroupbyColumnData_rv(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
  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);
}

1730 1731
static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, int32_t offset) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
1732

H
Haojun Liao 已提交
1733
  STSElem         elem = tsBufGetElem(pRuntimeEnv->pTsBuf);
1734
  SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
1735

1736
  // compare tag first
H
Haojun Liao 已提交
1737
  if (tVariantCompare(&pCtx[0].tag, elem.tag) != 0) {
1738 1739
    return TS_JOIN_TAG_NOT_EQUALS;
  }
1740

1741
  TSKEY key = *(TSKEY *)((char*)pCtx[0].pInput + TSDB_KEYSIZE * offset);
1742 1743

#if defined(_DEBUG_VIEW)
1744
  printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n",
1745
         elem.ts, key, elem.tag.i64, pQuery->order.order, pRuntimeEnv->pTsBuf->tsOrder,
H
Haojun Liao 已提交
1746
         pRuntimeEnv->pTsBuf->cur.order, pRuntimeEnv->pTsBuf->cur.tsIndex);
1747
#endif
1748

1749 1750 1751 1752
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (key < elem.ts) {
      return TS_JOIN_TS_NOT_EQUALS;
    } else if (key > elem.ts) {
D
fix bug  
dapan1121 已提交
1753
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN);
1754 1755 1756 1757 1758
    }
  } else {
    if (key > elem.ts) {
      return TS_JOIN_TS_NOT_EQUALS;
    } else if (key < elem.ts) {
D
fix bug  
dapan1121 已提交
1759
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_INCONSISTAN);
1760 1761
    }
  }
1762

1763 1764 1765 1766
  return TS_JOIN_TS_EQUAL;
}

static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1767
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
hjxilinx 已提交
1768
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1769 1770 1771 1772 1773

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

1775 1776 1777
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1778

1779
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
hjxilinx 已提交
1780 1781
    return QUERY_IS_ASC_QUERY(pQuery);
  }
1782

H
Haojun Liao 已提交
1783
  // denote the order type
1784
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
1785
    return pCtx->param[0].i64 == pQuery->order.order;
1786 1787
  }

1788
  // in the supplementary scan, only the following functions need to be executed
H
Haojun Liao 已提交
1789
  if (IS_REVERSE_SCAN(pRuntimeEnv)) {
1790 1791
    return false;
  }
1792

1793 1794 1795
  return true;
}

1796 1797 1798 1799
void doRowwiseTimeWindowInterpolation(SQueryRuntimeEnv *pRuntimeEnv, SArray *pDataBlock, TSKEY prevTs,
                                      int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey,
                                      int32_t type) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1800 1801
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
    int32_t functionId = pQuery->pExpr1[k].base.functionId;
1802
    if (functionId != TSDB_FUNC_TWA && functionId != TSDB_FUNC_INTERP) {
H
Haojun Liao 已提交
1803 1804 1805 1806
      pRuntimeEnv->pCtx[k].start.key = INT64_MIN;
      continue;
    }

1807 1808 1809
    SColIndex *      pColIndex = &pQuery->pExpr1[k].base.colInfo;
    int16_t          index = pColIndex->colIndex;
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index);
H
Haojun Liao 已提交
1810 1811 1812 1813 1814

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

    if (prevRowIndex == -1) {
1815
      GET_TYPED_DATA(v1, double, pColInfo->info.type, (char *)pRuntimeEnv->prevRow[index]);
H
Haojun Liao 已提交
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
    } 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);

    SPoint point1 = (SPoint){.key = prevTs, .val = &v1};
    SPoint point2 = (SPoint){.key = curTs, .val = &v2};
    SPoint point  = (SPoint){.key = windowKey, .val = &v};

1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
    if (functionId == TSDB_FUNC_TWA) {
      taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE);

      if (type == RESULT_ROW_START_INTERP) {
        pRuntimeEnv->pCtx[k].start.key = point.key;
        pRuntimeEnv->pCtx[k].start.val = v;
      } else {
        pRuntimeEnv->pCtx[k].end.key = point.key;
        pRuntimeEnv->pCtx[k].end.val = v;
      }
H
Haojun Liao 已提交
1836
    } else {
1837 1838 1839 1840 1841 1842 1843
      if (type == RESULT_ROW_START_INTERP) {
        pRuntimeEnv->pCtx[k].start.key = prevTs;
        pRuntimeEnv->pCtx[k].start.val = v1;

        pRuntimeEnv->pCtx[k].end.key = curTs;
        pRuntimeEnv->pCtx[k].end.val = v2;
      }
H
Haojun Liao 已提交
1844 1845 1846 1847
    }
  }
}

H
Haojun Liao 已提交
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
static void setTimeWindowSKeyInterp(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY ts, int32_t offset, SResultRow* pResult, STimeWindow* win) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

  bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
  if (!done) {
    TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->skey:win->ekey;
    if (key == ts) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    } else if (prevTs != INT64_MIN && ((QUERY_IS_ASC_QUERY(pQuery) && prevTs < key) || (!QUERY_IS_ASC_QUERY(pQuery) && prevTs > key))) {
      doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, key, RESULT_ROW_START_INTERP);
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    } else {
      setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
    }

    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_END_INTERP);
    for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
      pRuntimeEnv->pCtx[k].size = 1;
    }
  } else {
    setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
  }
}

static void setTimeWindowEKeyInterp(SQueryRuntimeEnv* pRuntimeEnv, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY ts, int32_t offset, SResultRow* pResult, STimeWindow* win) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

  TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->ekey:win->skey;
  doRowwiseTimeWindowInterpolation(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, key, RESULT_ROW_END_INTERP);
  setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);

  setNotInterpoWindowKey(pRuntimeEnv->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    pRuntimeEnv->pCtx[i].size = 0;
  }
}

1885
static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pStatis, SDataBlockInfo *pDataBlockInfo,
1886
                                  SResultRowInfo *pWindowResInfo, SArray *pDataBlock) {
1887
  SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
1888
  bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);
1889

1890
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
1891
  STableQueryInfo* item = pQuery->current;
H
Haojun Liao 已提交
1892

1893 1894
  int64_t groupId = item->groupIndex;

H
Haojun Liao 已提交
1895 1896 1897
  SColumnInfoData* pColumnInfoData = (SColumnInfoData *)taosArrayGet(pDataBlock, 0);

  TSKEY  *tsCols = (pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP)? (TSKEY*) pColumnInfoData->pData:NULL;
H
Haojun Liao 已提交
1898
  bool    groupbyColumnValue = pQuery->groupbyColumn;
1899

1900 1901
  int16_t type = 0;
  int16_t bytes = 0;
1902

1903
  char *groupbyColumnData = NULL;
H
Haojun Liao 已提交
1904
  if (groupbyColumnValue) {
1905
    groupbyColumnData = getGroupbyColumnData(pQuery, &type, &bytes, pDataBlock);
1906
  }
1907

H
Haojun Liao 已提交
1908
  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
1909
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
1910
    char *dataBlock = getDataBlock(pQuery, &pRuntimeEnv->sasArray[k], k, pDataBlockInfo->rows, pDataBlock);
H
Haojun Liao 已提交
1911
    setExecParams(pQuery, &pCtx[k], dataBlock, tsCols, pDataBlockInfo, pStatis, &pQuery->pExpr1[k]);
H
Haojun Liao 已提交
1912
    pCtx[k].size = 1;
1913
  }
1914

1915 1916
  // set the input column data
  for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
1917
    SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
H
hjxilinx 已提交
1918 1919
    pFilterInfo->pData = getDataBlockImpl(pDataBlock, pFilterInfo->info.colId);
    assert(pFilterInfo->pData != NULL);
1920
  }
1921

1922
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
1923

1924 1925
  // from top to bottom in desc
  // from bottom to top in asc order
H
Haojun Liao 已提交
1926
  if (pRuntimeEnv->pTsBuf != NULL) {
1927
    qDebug("QInfo:%p process data rows, numOfRows:%d, query order:%d, ts comp order:%d", pQInfo, pDataBlockInfo->rows,
H
Haojun Liao 已提交
1928
           pQuery->order.order, pRuntimeEnv->pTsBuf->cur.order);
1929
  }
1930

H
hjxilinx 已提交
1931
  int32_t offset = -1;
H
Haojun Liao 已提交
1932
  TSKEY   prevTs = *(TSKEY*) pRuntimeEnv->prevRow[0];
H
Haojun Liao 已提交
1933
  int32_t prevRowIndex = -1;
1934

1935
  for (int32_t j = 0; j < pDataBlockInfo->rows; ++j) {
H
hjxilinx 已提交
1936
    offset = GET_COL_DATA_POS(pQuery, j, step);
1937

H
Haojun Liao 已提交
1938
    if (pRuntimeEnv->pTsBuf != NULL) {
1939 1940
      int32_t ret = doTSJoinFilter(pRuntimeEnv, offset);
      if (ret == TS_JOIN_TAG_NOT_EQUALS) {
1941
        break;
1942
      } else if (ret == TS_JOIN_TS_NOT_EQUALS) {
1943 1944
        continue;
      } else {
1945
        assert(ret == TS_JOIN_TS_EQUAL);
1946 1947
      }
    }
1948

1949
    if (pQuery->numOfFilterCols > 0 && (!doFilterData(pQuery, offset))) {
1950 1951
      continue;
    }
1952

1953
    // interval window query, decide the time window according to the primary timestamp
H
Haojun Liao 已提交
1954
    if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
1955
      int32_t prevWindowIndex = curTimeWindowIndex(pWindowResInfo);
1956
      int64_t ts = tsCols[offset];
H
Haojun Liao 已提交
1957

1958
      STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery);
1959

1960
      SResultRow* pResult = NULL;
1961 1962 1963
      int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId);
      if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {  // null data, too many state code
        goto _end;
1964
      }
H
Haojun Liao 已提交
1965

1966
      // window start key interpolation
H
Haojun Liao 已提交
1967
      if (pQuery->timeWindowInterpo) {
H
Haojun Liao 已提交
1968 1969 1970 1971 1972
        // check for the time window end time interpolation
        int32_t curIndex = curTimeWindowIndex(pWindowResInfo);
        if (prevWindowIndex != -1 && prevWindowIndex < curIndex) {
          for (int32_t k = prevWindowIndex; k < curIndex; ++k) {
            SResultRow *pRes = pWindowResInfo->pResult[k];
1973 1974 1975 1976
            if (pRes->closed) {
              assert(resultRowInterpolated(pResult, RESULT_ROW_START_INTERP) && resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
              continue;
            }
H
Haojun Liao 已提交
1977

1978
            ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &pRes->win, masterScan, &pResult, groupId);
H
Haojun Liao 已提交
1979
            assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1980

H
Haojun Liao 已提交
1981
            setTimeWindowEKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &pRes->win);
1982
            doRowwiseApplyFunctions(pRuntimeEnv, &pRes->win, offset);
H
Haojun Liao 已提交
1983 1984 1985
          }

          // restore current time window
1986
          ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId);
H
Haojun Liao 已提交
1987 1988
          if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
            continue;
1989 1990
          }
        }
1991

H
Haojun Liao 已提交
1992
        setTimeWindowSKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &win);
1993
      }
H
Haojun Liao 已提交
1994

1995
      doRowwiseApplyFunctions(pRuntimeEnv, &win, offset);
1996
      int32_t index = pWindowResInfo->curIndex;
1997

1998 1999
      STimeWindow nextWin = win;
      while (1) {
H
Haojun Liao 已提交
2000
        getNextTimeWindow(pQuery, &nextWin);
2001
        if ((nextWin.skey > pQuery->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
H
Haojun Liao 已提交
2002
            (nextWin.ekey < pQuery->window.ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
2003 2004
          break;
        }
2005

2006 2007 2008
        if (ts < nextWin.skey || ts > nextWin.ekey) {
          break;
        }
2009

2010
        // null data, failed to allocate more memory buffer
2011 2012
        int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &nextWin, masterScan, &pResult, groupId);
        if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
2013 2014
          break;
        }
2015

2016 2017
        setTimeWindowSKeyInterp(pRuntimeEnv, pDataBlock, prevTs, prevRowIndex, ts, offset, pResult, &nextWin);
        doRowwiseApplyFunctions(pRuntimeEnv, &nextWin, offset);
2018
      }
2019

2020
      // restore the index, add the result row will move the index
2021 2022 2023
      pWindowResInfo->curIndex = index;
    } else {  // other queries
      // decide which group this rows belongs to according to current state value
2024
      char* val = NULL;
H
Haojun Liao 已提交
2025
      if (groupbyColumnValue) {
2026
        val = groupbyColumnData + bytes * offset;
2027 2028 2029
        if (isNull(val, type)) {  // ignore the null value
          continue;
        }
2030

H
Haojun Liao 已提交
2031
        int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, val, type, bytes, item->groupIndex);
2032
        if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
2033
          longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
2034 2035
        }
      }
2036

H
Haojun Liao 已提交
2037
      if (pQuery->stabledev) {
2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
        for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
          int32_t functionId = pQuery->pExpr1[k].base.functionId;
          if (functionId != TSDB_FUNC_STDDEV_DST) {
            continue;
          }

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

          // todo opt perf
          int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult);
          for (int32_t i = 0; i < numOfGroup; ++i) {
            SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, i);
            if (memcmp(p->tags, val, bytes) == 0) {
              int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
              for (int32_t f = 0; f < numOfCols; ++f) {
                SStddevInterResult *pres = taosArrayGet(p->pResult, f);
                if (pres->colId == pQuery->pExpr1[k].base.colInfo.colId) {
                  pRuntimeEnv->pCtx[k].param[0].arr = pres->pResult;
                  break;
                }
              }
            }
          }
        }
      }

2065
      for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
2066
        int32_t functionId = pQuery->pExpr1[k].base.functionId;
2067 2068 2069 2070 2071
        if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
          aAggs[functionId].xFunctionF(&pCtx[k], offset);
        }
      }
    }
2072

H
Haojun Liao 已提交
2073 2074
    prevTs = tsCols[offset];
    prevRowIndex = offset;
2075

H
Haojun Liao 已提交
2076
    if (pRuntimeEnv->pTsBuf != NULL) {
2077
      // if timestamp filter list is empty, quit current query
H
Haojun Liao 已提交
2078
      if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) {
H
hjxilinx 已提交
2079
        setQueryStatus(pQuery, QUERY_COMPLETED);
2080 2081 2082 2083
        break;
      }
    }
  }
H
Haojun Liao 已提交
2084

2085
  _end:
2086
  assert(offset >= 0 && tsCols != NULL);
D
fix bug  
dapan1121 已提交
2087
  if (prevTs != INT64_MIN && prevTs != *(int64_t*)pRuntimeEnv->prevRow[0]) {
2088
    assert(prevRowIndex >= 0);
2089
    item->lastKey = prevTs + step;
H
Haojun Liao 已提交
2090 2091
  }

2092
  // In case of all rows in current block are not qualified
H
Haojun Liao 已提交
2093
  if (pQuery->timeWindowInterpo && prevRowIndex != -1) {
2094
    saveDataBlockLastRow(pRuntimeEnv, pDataBlockInfo, pDataBlock, prevRowIndex);
H
Haojun Liao 已提交
2095
  }
H
Haojun Liao 已提交
2096

H
Haojun Liao 已提交
2097 2098
  if (pRuntimeEnv->pTsBuf != NULL) {
    item->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
2099
  }
2100 2101 2102
}

static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pDataBlockInfo,
H
hjxilinx 已提交
2103
                                          SDataStatis *pStatis, __block_search_fn_t searchFn, SArray *pDataBlock) {
H
hjxilinx 已提交
2104
  SQuery *pQuery = pRuntimeEnv->pQuery;
2105

2106
  STableQueryInfo* pTableQueryInfo = pQuery->current;
H
Haojun Liao 已提交
2107
  SResultRowInfo*  pResultRowInfo = &pRuntimeEnv->resultRowInfo;
2108

H
Haojun Liao 已提交
2109
  if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pQuery->groupbyColumn) {
2110
    rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, pDataBlock);
2111
  } else {
2112
    blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, searchFn, pDataBlock);
2113
  }
2114

2115 2116 2117 2118
  // update the lastkey of current table for projection/aggregation query
  TSKEY lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pDataBlockInfo->window.ekey : pDataBlockInfo->window.skey;
  pTableQueryInfo->lastKey = lastKey + GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

2119
  // interval query with limit applied
2120
  int32_t numOfRes = 0;
H
Haojun Liao 已提交
2121
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || pQuery->groupbyColumn) {
2122
    numOfRes = pResultRowInfo->size;
H
Haojun Liao 已提交
2123
    updateResultRowIndex(pResultRowInfo, pTableQueryInfo, QUERY_IS_ASC_QUERY(pQuery), pQuery->timeWindowInterpo);
H
Haojun Liao 已提交
2124
  } else { // projection query
2125
    numOfRes = (int32_t) getNumOfResult(pRuntimeEnv);
2126

2127
    // update the number of output result
H
Haojun Liao 已提交
2128
    if (numOfRes > 0 && pQuery->checkResultBuf == 1) {
2129 2130
      assert(numOfRes >= pQuery->rec.rows);
      pQuery->rec.rows = numOfRes;
2131

2132 2133 2134
      if (numOfRes >= pQuery->rec.threshold) {
        setQueryStatus(pQuery, QUERY_RESBUF_FULL);
      }
2135

2136 2137 2138
      if ((pQuery->limit.limit >= 0) && (pQuery->limit.limit + pQuery->limit.offset) <= numOfRes) {
        setQueryStatus(pQuery, QUERY_COMPLETED);
      }
2139

2140 2141
      if (((pTableQueryInfo->lastKey > pTableQueryInfo->win.ekey) && QUERY_IS_ASC_QUERY(pQuery)) ||
          ((pTableQueryInfo->lastKey < pTableQueryInfo->win.ekey) && (!QUERY_IS_ASC_QUERY(pQuery)))) {
2142 2143
        setQueryStatus(pQuery, QUERY_COMPLETED);
      }
H
Haojun Liao 已提交
2144
    }
2145
  }
2146

2147
  return numOfRes;
2148 2149
}

H
Haojun Liao 已提交
2150

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

H
Haojun Liao 已提交
2154 2155 2156 2157
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
2158 2159 2160 2161 2162 2163
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
2164
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176

  // limit/offset query will affect this value
  pCtx->size = pSDataBlock->info.rows;

  // set the statistics data for primary time stamp column
//  if (pCtx->functionId == TSDB_FUNC_SPREAD &&colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
//    pCtx->preAggVals.isSet  = true;
//    pCtx->preAggVals.statis.min = pBlockInfo->window.skey;
//    pCtx->preAggVals.statis.max = pBlockInfo->window.ekey;
//  }
}

H
Haojun Liao 已提交
2177
void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY *tsCol, SDataBlockInfo* pBlockInfo,
H
Haojun Liao 已提交
2178
                   SDataStatis *pStatis, SExprInfo* pExprInfo) {
2179

H
Haojun Liao 已提交
2180 2181
//  int32_t functionId = pExprInfo->base.functionId;
//  int32_t colId = pExprInfo->base.colInfo.colId;
2182

2183
  SDataStatis *tpField = NULL;
H
Haojun Liao 已提交
2184
  pCtx->hasNull = hasNullValue(&pExprInfo->base.colInfo, pStatis, &tpField);
2185

2186
  if (tpField != NULL) {
H
Haojun Liao 已提交
2187
    pCtx->preAggVals.isSet  = true;
2188 2189
    pCtx->preAggVals.statis = *tpField;
    assert(pCtx->preAggVals.statis.numOfNull <= pBlockInfo->rows);
2190 2191 2192
  } else {
    pCtx->preAggVals.isSet = false;
  }
2193

H
Haojun Liao 已提交
2194 2195
  pCtx->preAggVals.dataBlockLoaded = (inputData != NULL);

H
Haojun Liao 已提交
2196 2197
  // limit/offset query will affect this value
  pCtx->size = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->rows - pQuery->pos : pQuery->pos + 1;
2198

H
Haojun Liao 已提交
2199
  // set the start position in current block
H
Haojun Liao 已提交
2200 2201 2202 2203 2204 2205 2206 2207 2208
//  int32_t offset = QUERY_IS_ASC_QUERY(pQuery) ? pQuery->pos: (pQuery->pos - pCtx->size + 1);
//  if (inputData != NULL) {
//    pCtx->pInput = (char*)inputData + offset * pCtx->inputBytes;
//  }
//
//  uint32_t status = aAggs[functionId].status;
//  if (((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) && (tsCol != NULL)) {
//    pCtx->ptsList = tsCol + offset;
//  }
2209

H
Haojun Liao 已提交
2210 2211 2212 2213 2214 2215
  // set the statistics data for primary time stamp column
//  if (functionId == TSDB_FUNC_SPREAD && colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
//    pCtx->preAggVals.isSet  = true;
//    pCtx->preAggVals.statis.min = pBlockInfo->window.skey;
//    pCtx->preAggVals.statis.max = pBlockInfo->window.ekey;
//  }
2216 2217 2218
}

// set the output buffer for the selectivity + tag query
H
Haojun Liao 已提交
2219
static int32_t setCtxTagColumnInfo(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx) {
H
Haojun Liao 已提交
2220 2221
  SQuery* pQuery = pRuntimeEnv->pQuery;

2222
  if (isSelectivityWithTagsQuery(pQuery)) {
2223
    int32_t num = 0;
2224
    int16_t tagLen = 0;
2225

2226
    SQLFunctionCtx *p = NULL;
2227
    SQLFunctionCtx **pTagCtx = calloc(pQuery->numOfOutput, POINTER_BYTES);
H
Haojun Liao 已提交
2228 2229 2230
    if (pTagCtx == NULL) {
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
H
Haojun Liao 已提交
2231

2232
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2233
      SSqlFuncMsg *pSqlFuncMsg = &pQuery->pExpr1[i].base;
2234

2235 2236 2237
      if (pSqlFuncMsg->functionId == TSDB_FUNC_TAG_DUMMY || pSqlFuncMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        tagLen += pCtx[i].outputBytes;
        pTagCtx[num++] = &pCtx[i];
H
Haojun Liao 已提交
2238
      } else if ((aAggs[pSqlFuncMsg->functionId].status & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
2239 2240 2241 2242 2243 2244 2245 2246 2247
        p = &pCtx[i];
      } else if (pSqlFuncMsg->functionId == TSDB_FUNC_TS || pSqlFuncMsg->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
      }
    }
dengyihao's avatar
dengyihao 已提交
2248 2249 2250 2251 2252
    if (p != NULL) {
      p->tagInfo.pTagCtxList = pTagCtx;
      p->tagInfo.numOfTagCols = num;
      p->tagInfo.tagsLen = tagLen;
    } else {
S
TD-1848  
Shengliang Guan 已提交
2253
      tfree(pTagCtx);
dengyihao's avatar
dengyihao 已提交
2254
    }
2255
  }
H
Haojun Liao 已提交
2256 2257

  return TSDB_CODE_SUCCESS;
2258 2259
}

H
Haojun Liao 已提交
2260 2261
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfOutput, SExprInfo* pExpr, int32_t order, int32_t vgId) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
2262

H
Haojun Liao 已提交
2263 2264 2265
  SQLFunctionCtx *pQCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pQCtx == NULL) {
    return NULL;
2266 2267
  }

H
Haojun Liao 已提交
2268 2269 2270
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base;
    SQLFunctionCtx* pCtx = &pQCtx[i];
2271

H
Haojun Liao 已提交
2272
    SColIndex *pIndex = &pSqlFuncMsg->colInfo;
2273

Y
TD-1230  
yihaoDeng 已提交
2274
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
2275 2276
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
2277
    } else {
2278 2279
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
2280

2281 2282
    int32_t index = pSqlFuncMsg->colInfo.colIndex;
    if (TSDB_COL_IS_TAG(pIndex->flag)) {
2283
      if (pIndex->colId == TSDB_TBNAME_COLUMN_INDEX) {  // todo refactor
H
Haojun Liao 已提交
2284
        SSchema *s = tGetTbnameColumnSchema();
H
Haojun Liao 已提交
2285

2286 2287
        pCtx->inputBytes = s->bytes;
        pCtx->inputType = s->type;
Y
yihaoDeng 已提交
2288 2289
      } else if (pIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
        SSchema s = tGetBlockDistColumnSchema();
H
Haojun Liao 已提交
2290 2291
        pCtx->inputBytes = s.bytes;
        pCtx->inputType = s.type;
2292 2293 2294 2295
      } else {
        pCtx->inputBytes = pQuery->tagColList[index].bytes;
        pCtx->inputType = pQuery->tagColList[index].type;
      }
H
Haojun Liao 已提交
2296 2297 2298
    } else if (TSDB_COL_IS_UD_COL(pIndex->flag)) {
      pCtx->inputBytes = pSqlFuncMsg->arg[0].argBytes;
      pCtx->inputType = pSqlFuncMsg->arg[0].argType;
2299 2300 2301 2302
    } else {
      pCtx->inputBytes = pQuery->colList[index].bytes;
      pCtx->inputType = pQuery->colList[index].type;
    }
2303

2304
    assert(isValidDataType(pCtx->inputType));
2305
    pCtx->ptsOutputBuf = NULL;
2306

H
Haojun Liao 已提交
2307 2308
    pCtx->outputBytes  = pExpr[i].bytes;
    pCtx->outputType   = pExpr[i].type;
2309

H
Haojun Liao 已提交
2310
    pCtx->order        = order;
H
Haojun Liao 已提交
2311
    pCtx->functionId   = pSqlFuncMsg->functionId;
H
Haojun Liao 已提交
2312
    pCtx->stableQuery  = pQuery->stableQuery;
H
Haojun Liao 已提交
2313
    pCtx->interBufBytes = pExpr[i].interBytes;
2314 2315
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
2316

H
Haojun Liao 已提交
2317
    pCtx->numOfParams  = pSqlFuncMsg->numOfParams;
2318 2319 2320
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
      int16_t type = pSqlFuncMsg->arg[j].argType;
      int16_t bytes = pSqlFuncMsg->arg[j].argBytes;
2321 2322 2323 2324
      if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) {
        continue;
      }

2325
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2326
        tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type);
2327 2328 2329 2330
      } else {
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type);
      }
    }
2331

2332 2333
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
2334

2335
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
2336
      int32_t f = pExpr[0].base.functionId;
2337
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
2338

H
Haojun Liao 已提交
2339
      pCtx->param[2].i64 = pQuery->order.order;
2340
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
2341
      pCtx->param[3].i64 = functionId;
2342
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
2343

2344
      pCtx->param[1].i64 = pQuery->order.orderColId;
H
Haojun Liao 已提交
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364
    } else if (functionId == TSDB_FUNC_INTERP) {
      pCtx->param[2].i64 = (int8_t)pQuery->fillType;
      if (pQuery->fillVal != NULL) {
        if (isNull((const char *)&pQuery->fillVal[i], pCtx->inputType)) {
          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) {
            tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQuery->fillVal[i], pCtx->inputBytes, pCtx->inputType);
          }
        }
      }
    } else if (functionId == TSDB_FUNC_TS_COMP) {
      pCtx->param[0].i64 = vgId;
      pCtx->param[0].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_TWA) {
      pCtx->param[1].i64 = pQuery->window.skey;
      pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT;
      pCtx->param[2].i64 = pQuery->window.ekey;
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_ARITHM) {
2365 2366 2367 2368
      pRuntimeEnv->sasArray[i].data = calloc(pQuery->numOfCols, POINTER_BYTES);
      if (pRuntimeEnv->sasArray[i].data == NULL) {
        goto _clean;
      }
H
Haojun Liao 已提交
2369 2370

      pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i];
2371
    }
2372

2373
    if (i > 0) {
H
Haojun Liao 已提交
2374
      pRuntimeEnv->offset[i] = pRuntimeEnv->offset[i - 1] + pQCtx[i - 1].outputBytes;
H
Haojun Liao 已提交
2375
      pRuntimeEnv->rowCellInfoOffset[i] =
H
Haojun Liao 已提交
2376
          pRuntimeEnv->rowCellInfoOffset[i - 1] + sizeof(SResultRowCellInfo) + pExpr[i - 1].interBytes;
2377 2378
    }
  }
2379

H
Haojun Liao 已提交
2380 2381 2382 2383 2384 2385 2386
  return pQCtx;

  _clean:
  tfree(pQCtx);
  return NULL;
}

H
Haojun Liao 已提交
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404
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 已提交
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables, int16_t order, int32_t vgId) {
  qDebug("QInfo:%p setup runtime env", GET_QINFO_ADDR(pRuntimeEnv));
  SQuery *pQuery = pRuntimeEnv->pQuery;

  pRuntimeEnv->prevGroupId = INT32_MIN;
  pRuntimeEnv->pQuery = pQuery;

  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);

  pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
  pRuntimeEnv->keyBuf  = malloc(pQuery->maxSrcColumnSize + sizeof(int64_t));
  pRuntimeEnv->pool    = initResultRowPool(getResultRowSize(pRuntimeEnv));
  pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQuery->numOfCols + pQuery->srcRowSize);
  pRuntimeEnv->tagVal  = malloc(pQuery->tagLen);
  pRuntimeEnv->offset  = calloc(pQuery->numOfOutput, sizeof(int16_t));
  pRuntimeEnv->rowCellInfoOffset = calloc(pQuery->numOfOutput, sizeof(int32_t));
  pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport));

  if (pRuntimeEnv->offset == NULL || pRuntimeEnv->rowCellInfoOffset == NULL || pRuntimeEnv->sasArray == NULL ||
      pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL || pRuntimeEnv->prevRow == NULL ||
      pRuntimeEnv->tagVal == NULL) {
    goto _clean;
  }

  char* start = POINTER_BYTES * pQuery->numOfCols + (char*) pRuntimeEnv->prevRow;
  pRuntimeEnv->prevRow[0] = start;
  for(int32_t i = 1; i < pQuery->numOfCols; ++i) {
    pRuntimeEnv->prevRow[i] = pRuntimeEnv->prevRow[i - 1] + pQuery->colList[i-1].bytes;
  }

  pRuntimeEnv->offset[0] = 0;
  pRuntimeEnv->pCtx = createSQLFunctionCtx(pRuntimeEnv, pQuery->numOfOutput, pQuery->pExpr1, order, vgId);
  if (pRuntimeEnv->pCtx == NULL) {
    goto _clean;
  }

2441 2442
  *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;

2443
  // if it is group by normal column, do not set output buffer, the output buffer is pResult
2444
  // fixed output query/multi-output query for normal table
H
Haojun Liao 已提交
2445
  if (!pQuery->groupbyColumn && !pQuery->stableQuery && !QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQuery)) {
H
Haojun Liao 已提交
2446
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
2447
  }
2448

H
Haojun Liao 已提交
2449 2450 2451
  if (setCtxTagColumnInfo(pRuntimeEnv, pRuntimeEnv->pCtx) != TSDB_CODE_SUCCESS) {
    goto _clean;
  }
2452

H
Haojun Liao 已提交
2453
  qDebug("QInfo:%p init runtime completed", GET_QINFO_ADDR(pRuntimeEnv));
H
Haojun Liao 已提交
2454 2455

  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475
//  if (!pQuery->stableQuery) {  // interval (down sampling operation)
    if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
      if (pQuery->stableQuery) {
        pRuntimeEnv->proot = createStableIntervalOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->pi);
        setTableScanFilterOperatorInfo(pRuntimeEnv->pi->optInfo, pRuntimeEnv->proot);
      } else {
        pRuntimeEnv->proot = createHashIntervalAggOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->pi);
        setTableScanFilterOperatorInfo(pRuntimeEnv->pi->optInfo, pRuntimeEnv->proot);

        if (pQuery->pExpr2 != NULL) {
          pRuntimeEnv->proot = createArithOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
        }

        if (pQuery->fillType != TSDB_FILL_NONE) {
          pRuntimeEnv->proot = createFillOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
        }
      }

    } else if (pQuery->groupbyColumn) {
      pRuntimeEnv->proot = createHashGroupbyAggOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->pi);
H
Haojun Liao 已提交
2476 2477
      setTableScanFilterOperatorInfo(pRuntimeEnv->pi->optInfo, pRuntimeEnv->proot);

H
Haojun Liao 已提交
2478 2479 2480
      if (pQuery->pExpr2 != NULL) {
        pRuntimeEnv->proot = createArithOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
      }
H
Haojun Liao 已提交
2481 2482
    } else if (isFixedOutputQuery(pQuery)) {
      pRuntimeEnv->proot = createAggOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->pi);
H
Haojun Liao 已提交
2483 2484 2485 2486 2487
      setTableScanFilterOperatorInfo(pRuntimeEnv->pi->optInfo, pRuntimeEnv->proot);

      if (pQuery->pExpr2 != NULL) {
        pRuntimeEnv->proot = createArithOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
      }
H
Haojun Liao 已提交
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499
    } else {  // diff/add/multiply/subtract/division
      assert(pQuery->checkResultBuf == 1);
      pRuntimeEnv->proot = createArithOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->pi);
    }

    if (pQuery->limit.offset > 0) {
      pRuntimeEnv->proot = createOffsetOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
    }

    if (pQuery->limit.limit > 0) {
      pRuntimeEnv->proot = createLimitOperatorInfo(pQuery->current, pRuntimeEnv, pRuntimeEnv->proot);
    }
H
Haojun Liao 已提交
2500
//  }
H
Haojun Liao 已提交
2501

2502
  return TSDB_CODE_SUCCESS;
2503

2504
_clean:
S
TD-1848  
Shengliang Guan 已提交
2505
  tfree(pRuntimeEnv->pCtx);
H
Haojun Liao 已提交
2506 2507
  tfree(pRuntimeEnv->offset);
  tfree(pRuntimeEnv->rowCellInfoOffset);
2508
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
2509 2510 2511 2512
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
2513

2514
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
2515 2516
}

H
Haojun Liao 已提交
2517 2518
static void doFreeQueryHandle(SQInfo* pQInfo) {
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
2519
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2520 2521 2522 2523 2524 2525 2526

  tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
  tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle);

  pRuntimeEnv->pQueryHandle = NULL;
  pRuntimeEnv->pSecQueryHandle = NULL;

H
Haojun Liao 已提交
2527
  SMemRef* pMemRef = &pQuery->memRef;
H
Haojun Liao 已提交
2528 2529 2530
  assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL);
}

D
fix bug  
dapan1121 已提交
2531

2532

H
Haojun Liao 已提交
2533
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
2534
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
2535
  SQInfo* pQInfo = (SQInfo*) GET_QINFO_ADDR(pRuntimeEnv);
2536

2537
  qDebug("QInfo:%p teardown runtime env", pQInfo);
H
Haojun Liao 已提交
2538
  cleanupResultRowInfo(&pRuntimeEnv->resultRowInfo);
2539

H
Haojun Liao 已提交
2540
  if (isTsCompQuery(pQuery)) {
D
fix bug  
dapan1121 已提交
2541 2542 2543 2544 2545 2546 2547 2548 2549
    FILE *f = *(FILE **)pQuery->sdata[0]->data;

    if (f) {
      fclose(f);
      *(FILE **)pQuery->sdata[0]->data = NULL;
    }
  }


2550
  if (pRuntimeEnv->pCtx != NULL) {
2551
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
2552
      SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
2553

2554 2555 2556
      for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
        tVariantDestroy(&pCtx->param[j]);
      }
2557

2558
      tVariantDestroy(&pCtx->tag);
S
TD-1848  
Shengliang Guan 已提交
2559
      tfree(pCtx->tagInfo.pTagCtxList);
2560
    }
2561

S
TD-1848  
Shengliang Guan 已提交
2562
    tfree(pRuntimeEnv->pCtx);
2563
  }
2564

2565 2566 2567 2568 2569 2570 2571 2572
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
    }

    tfree(pRuntimeEnv->sasArray);
  }

2573
  pRuntimeEnv->pFillInfo = taosDestroyFillInfo(pRuntimeEnv->pFillInfo);
2574

H
Haojun Liao 已提交
2575
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
2576
  doFreeQueryHandle(pQInfo);
2577

H
Haojun Liao 已提交
2578
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
2579 2580

  tfree(pRuntimeEnv->offset);
S
TD-1848  
Shengliang Guan 已提交
2581 2582
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->rowCellInfoOffset);
2583
  tfree(pRuntimeEnv->prevRow);
2584 2585
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
2586 2587
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
2588

H
Haojun Liao 已提交
2589
  pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool);
2590 2591
  taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult);
  pRuntimeEnv->prevResult = NULL;
H
Haojun Liao 已提交
2592 2593 2594

  pRuntimeEnv->outputBuf = destroyOutputBuf(pRuntimeEnv->outputBuf);
  destroyOperatorInfo(pRuntimeEnv->proot);
2595 2596
}

2597 2598 2599 2600
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
2601
bool isQueryKilled(SQInfo *pQInfo) {
2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619
  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);
    qDebug("QInfo:%p retrieve not arrive beyond %d sec, abort current query execution, start:%"PRId64", current:%d", pQInfo, 1,
           pQInfo->startExecTs, taosGetTimestampSec());
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
2622
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
2623
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
2624 2625
    return false;
  }
2626

2627
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
2628
  if (pQuery->topBotQuery || pQuery->groupbyColumn) {
2629 2630
    return true;
  }
2631

2632
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2633
    SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
2634

2635 2636
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
2637
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
2638 2639
      continue;
    }
2640

2641 2642 2643
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
2644

H
Haojun Liao 已提交
2645
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
2646 2647 2648
      return true;
    }
  }
2649

2650 2651 2652
  return false;
}

2653
// todo refactor with isLastRowQuery
2654
bool isPointInterpoQuery(SQuery *pQuery) {
2655
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2656 2657
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
2658 2659 2660
      return true;
    }
  }
2661

2662 2663 2664 2665
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
H
hjxilinx 已提交
2666
static bool isSumAvgRateQuery(SQuery *pQuery) {
2667
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2668
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2669 2670 2671
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
2672

2673 2674 2675 2676 2677
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
2678

2679 2680 2681
  return false;
}

H
hjxilinx 已提交
2682
static bool isFirstLastRowQuery(SQuery *pQuery) {
2683
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2684
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
2685 2686 2687 2688
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
2689

2690 2691 2692
  return false;
}

H
hjxilinx 已提交
2693
static bool needReverseScan(SQuery *pQuery) {
2694
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2695
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2696 2697 2698
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
2699

2700
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
2701 2702
      return true;
    }
2703 2704

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
2705
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
2706
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
2707 2708 2709
      if (order != pQuery->order.order) {
        return true;
      }
2710
    }
2711
  }
2712

2713 2714
  return false;
}
H
hjxilinx 已提交
2715

H
Haojun Liao 已提交
2716 2717 2718 2719
/**
 * 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 已提交
2720
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
2721
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2722
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
2723 2724

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
2725 2726 2727 2728

    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 已提交
2729
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
2730 2731 2732
      return false;
    }
  }
2733

H
hjxilinx 已提交
2734 2735 2736
  return true;
}

2737 2738
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2739
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
2740 2741
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
2742 2743

  /*
2744
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
2745 2746
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
2747 2748
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
2749
    win->ekey = INT64_MAX;
2750 2751
  } else if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
    win->ekey = taosTimeAdd(win->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
H
Haojun Liao 已提交
2752
  } else {
2753
    win->ekey = win->skey + pQuery->interval.interval - 1;
2754 2755 2756 2757 2758
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
2759
    pQuery->checkResultBuf = 0;
2760
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
2761
    pQuery->checkResultBuf = 0;
2762 2763
  } else {
    bool hasMultioutput = false;
2764
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2765
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
2766 2767 2768
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
2769

H
Haojun Liao 已提交
2770
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
2771 2772 2773 2774
      if (!hasMultioutput) {
        break;
      }
    }
2775

H
Haojun Liao 已提交
2776
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
2777 2778 2779 2780 2781 2782
  }
}

/*
 * todo add more parameters to check soon..
 */
2783
bool colIdCheck(SQuery *pQuery) {
2784 2785
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
2786
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
S
slguan 已提交
2787
      qError("QInfo:%p invalid data load column for query", GET_QINFO_ADDR(pQuery));
2788 2789 2790
      return false;
    }
  }
2791

2792 2793 2794 2795 2796 2797
  return true;
}

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

2801 2802 2803 2804
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2805

2806 2807 2808 2809
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2810

2811 2812 2813 2814 2815 2816 2817
  return true;
}

static bool onlyFirstQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSDB_FUNC_FIRST, TSDB_FUNC_FIRST_DST); }

static bool onlyLastQuery(SQuery *pQuery) { return onlyOneQueryType(pQuery, TSDB_FUNC_LAST, TSDB_FUNC_LAST_DST); }

2818
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2819 2820
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2821
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2822
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2823 2824 2825

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

2828 2829 2830 2831
      // 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 已提交
2832 2833 2834 2835
    }
  }
}

2836
static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bool stableQuery) {
H
Haojun Liao 已提交
2837 2838
  SQuery* pQuery = pQInfo->runtimeEnv.pQuery;

2839 2840 2841
  // in case of point-interpolation query, use asc order scan
  char msg[] = "QInfo:%p scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64
               "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64;
2842

2843 2844
  // 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 已提交
2845
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
2846
    qDebug("QInfo:%p scan order changed for last_row query, old:%d, new:%d", pQInfo, pQuery->order.order, TSDB_ORDER_ASC);
2847

H
Haojun Liao 已提交
2848
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2849 2850 2851
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2852

2853 2854
    return;
  }
2855

2856
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2857
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2858 2859 2860
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2861

2862
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2863 2864 2865
    return;
  }

2866
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2867 2868 2869 2870 2871
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      qDebug(msg, GET_QINFO_ADDR(pQuery), "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
             pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2872

2873
    pQuery->order.order = TSDB_ORDER_ASC;
2874 2875
    return;
  }
2876

2877
  if (pQuery->interval.interval == 0) {
2878 2879
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
2880
        qDebug(msg, GET_QINFO_ADDR(pQuery), "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2881 2882
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2883
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2884
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2885
      }
2886

2887
      pQuery->order.order = TSDB_ORDER_ASC;
2888 2889
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
2890
        qDebug(msg, GET_QINFO_ADDR(pQuery), "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2891 2892
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2893
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2894
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2895
      }
2896

2897
      pQuery->order.order = TSDB_ORDER_DESC;
2898
    }
2899

2900
  } else {  // interval query
2901
    if (stableQuery) {
2902 2903
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
2904
          qDebug(msg, GET_QINFO_ADDR(pQuery), "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2905 2906
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2907
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2908
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2909
        }
2910

2911
        pQuery->order.order = TSDB_ORDER_ASC;
2912 2913
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
2914
          qDebug(msg, GET_QINFO_ADDR(pQuery), "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2915 2916
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2917
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2918
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2919
        }
2920

2921
        pQuery->order.order = TSDB_ORDER_DESC;
2922 2923 2924 2925 2926 2927
      }
    }
  }
}

static int32_t getInitialPageNum(SQInfo *pQInfo) {
H
Haojun Liao 已提交
2928 2929 2930
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;
  
2931 2932
  int32_t INITIAL_RESULT_ROWS_VALUE = 16;
  int32_t num = 0;
2933

2934
  if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
2935
    num = 128;
H
Haojun Liao 已提交
2936
  } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) {  // time window query, allocate one page for each table
H
Haojun Liao 已提交
2937
    size_t s = pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
S
TD-1057  
Shengliang Guan 已提交
2938
    num = (int32_t)(MAX(s, INITIAL_RESULT_ROWS_VALUE));
2939 2940
  } else {    // for super table query, one page for each subset
    num = 1;  // pQInfo->pSidSet->numOfSubSet;
2941
  }
2942

2943 2944 2945 2946
  assert(num > 0);
  return num;
}

2947 2948
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2949
  int32_t MIN_ROWS_PER_PAGE = 4;
2950

H
Haojun Liao 已提交
2951
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2952 2953 2954 2955
  int32_t overhead = sizeof(tFilePage);

  // one page contains at least two rows
  *ps = DEFAULT_INTERN_BUF_PAGE_SIZE;
H
Haojun Liao 已提交
2956
  while(((*rowsize) * MIN_ROWS_PER_PAGE) > (*ps) - overhead) {
2957 2958 2959 2960
    *ps = (*ps << 1u);
  }

  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
2961
  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2962 2963
}

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

H
Haojun Liao 已提交
2966
static bool doDataBlockStaticFilter(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) {
H
Haojun Liao 已提交
2967
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2968

H
Haojun Liao 已提交
2969
  if (pDataStatis == NULL || (pQuery->numOfFilterCols == 0 && (!pQuery->topBotQuery))) {
2970 2971 2972 2973 2974
    return true;
  }

  for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
    SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
2975

H
Haojun Liao 已提交
2976 2977 2978 2979 2980 2981 2982 2983
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2984
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2985
    if (index == -1) {
H
Haojun Liao 已提交
2986
      return true;
2987
    }
2988

2989
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2990
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2991
      return true;
2992
    }
2993

2994
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2995
    if (pDataStatis[index].numOfNull == numOfRows) {
2996 2997 2998 2999

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
3000
        if (pFilterElem->fp == isNullOperator) {
3001 3002 3003 3004
          return true;
        }
      }

3005 3006
      continue;
    }
3007

H
Haojun Liao 已提交
3008 3009 3010
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

3014
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
3015
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
3016 3017 3018 3019 3020
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
3021
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
3022 3023 3024 3025 3026
          return true;
        }
      }
    }
  }
3027

H
Haojun Liao 已提交
3028
  return false;
3029 3030
}

H
Haojun Liao 已提交
3031 3032 3033 3034 3035 3036 3037 3038
static bool overlapWithTimeWindow(SQuery* pQuery, SDataBlockInfo* pBlockInfo) {
  STimeWindow w = {0};

  TSKEY sk = MIN(pQuery->window.skey, pQuery->window.ekey);
  TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey);

  if (QUERY_IS_ASC_QUERY(pQuery)) {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
3039
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
3040

H
Haojun Liao 已提交
3041
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
3042 3043 3044 3045
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
3046
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
3047
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
3048 3049 3050
        break;
      }

H
Haojun Liao 已提交
3051 3052
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
3053 3054 3055 3056 3057
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
3058 3059 3060
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
3061 3062 3063 3064
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
3065
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
3066 3067 3068 3069
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
3070 3071
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
3072 3073 3074 3075 3076 3077 3078 3079
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
3080
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo * pWindowResInfo, void* pQueryHandle, SDataBlockInfo* pBlockInfo, SDataStatis **pStatis, SArray** pDataBlock, uint32_t* status) {
H
Haojun Liao 已提交
3081 3082
  *status = BLK_DATA_NO_NEEDED;

3083
  SQuery *pQuery = pRuntimeEnv->pQuery;
3084 3085
  int64_t groupId = pQuery->current->groupIndex;

H
Haojun Liao 已提交
3086 3087
  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
  SQueryCostInfo* pCost = &pQInfo->summary;
3088

H
Haojun Liao 已提交
3089
  if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf > 0) {
3090
    *status = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
3091
  } else { // check if this data block is required to load
H
Haojun Liao 已提交
3092
    // Calculate all time windows that are overlapping or contain current data block.
3093
    // If current data block is contained by all possible time window, do not load current data block.
H
Haojun Liao 已提交
3094
    if (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, pBlockInfo)) {
3095
      *status = BLK_DATA_ALL_NEEDED;
3096
    }
3097

3098
    if ((*status) != BLK_DATA_ALL_NEEDED) {
H
Haojun Liao 已提交
3099 3100 3101
      // 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
      if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
3102 3103
        SResultRow* pResult = NULL;

H
Haojun Liao 已提交
3104 3105 3106 3107
        bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);

        TSKEY k = QUERY_IS_ASC_QUERY(pQuery)? pBlockInfo->window.skey:pBlockInfo->window.ekey;
        STimeWindow win = getActiveTimeWindow(pWindowResInfo, k, pQuery);
3108
        if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3109 3110 3111 3112
          // todo handle error in set result for timewindow
        }
      }

H
Haojun Liao 已提交
3113
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
3114
        SSqlFuncMsg* pSqlFunc = &pQuery->pExpr1[i].base;
H
Haojun Liao 已提交
3115 3116 3117

        int32_t functionId = pSqlFunc->functionId;
        int32_t colId = pSqlFunc->colInfo.colId;
H
Haojun Liao 已提交
3118
        (*status) |= aAggs[functionId].dataReqFunc(&pRuntimeEnv->pCtx[i], &pBlockInfo->window, colId);
3119
        if (((*status) & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) {
H
Haojun Liao 已提交
3120 3121 3122
          break;
        }
      }
3123 3124
    }
  }
3125

3126
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
3127 3128
    qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", GET_QINFO_ADDR(pRuntimeEnv),
           pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
3129
    pCost->discardBlocks += 1;
3130 3131 3132 3133
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {

    // this function never returns error?
    tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis);
3134
    pCost->loadBlockStatis += 1;
3135

3136
    if (*pStatis == NULL) { // data block statistics does not exist, load data block
H
Haojun Liao 已提交
3137
      *pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
3138
      pCost->totalCheckedRows += pBlockInfo->rows;
3139 3140
    }
  } else {
3141
    assert((*status) == BLK_DATA_ALL_NEEDED);
3142

3143
    // load the data block statistics to perform further filter
3144
    pCost->loadBlockStatis += 1;
3145
    tsdbRetrieveDataBlockStatisInfo(pQueryHandle, pStatis);
3146

H
Haojun Liao 已提交
3147
    if (!doDataBlockStaticFilter(pRuntimeEnv, *pStatis, pRuntimeEnv->pCtx, pBlockInfo->rows)) {
3148
      // current block has been discard due to filter applied
3149
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
3150 3151
      qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", GET_QINFO_ADDR(pRuntimeEnv),
          pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
3152
      (*status) = BLK_DATA_DISCARD;
3153
    }
3154

3155 3156
    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
3157
    *pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
3158 3159 3160
    if (*pDataBlock == NULL) {
      return terrno;
    }
3161
  }
3162

H
Haojun Liao 已提交
3163
  return TSDB_CODE_SUCCESS;
3164 3165
}

H
Haojun Liao 已提交
3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
void filterDataBlock_rv(SSingleColumnFilterInfo *pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock) {
  int32_t numOfRows = pBlock->info.rows;

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

  for (int32_t i = 0; i < numOfRows; ++i) {
    bool qualified = false;

    for (int32_t k = 0; k < numOfFilterCols; ++k) {
      char *pElem = (char *)pFilterInfo[k].pData + pFilterInfo[k].info.bytes * i;

      qualified = false;
      for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];

        bool isnull = isNull(pElem, pFilterInfo[k].info.type);
        if (isnull) {
          if (pFilterElem->fp == isNullOperator) {
            qualified = true;
            break;
          } else {
            continue;
          }
        } else {
          if (pFilterElem->fp == notNullOperator) {
            qualified = true;
            break;
          } else if (pFilterElem->fp == isNullOperator) {
            continue;
          }
        }

        if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
          qualified = true;
          break;
        }
      }

      if (!qualified) {
        break;
      }
    }

    p[i] = qualified ? 1 : 0;
    if (!qualified) {
      all = false;
    }
  }

  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;
            memmove(pColumnInfoData->pData + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
          }

          start += len;
        }
      }
    }

    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

    if (start > 0) {
      SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
      assert(pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP &&
             pColumnInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX);
H
Haojun Liao 已提交
3244

H
Haojun Liao 已提交
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254
      pBlock->info.window.skey = *(int64_t *)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t *)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
    }
  }

  tfree(p);
}

int32_t loadDataBlockOnDemand_rv(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, SResultRowInfo *pWindowResInfo,
                                 void *pQueryHandle, SSDataBlock *pBlock, uint32_t *status) {
H
Haojun Liao 已提交
3255
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
3256
  pBlock->pDataBlock   = NULL;
H
Haojun Liao 已提交
3257
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
3258 3259

  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3260
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
3261 3262 3263 3264 3265 3266 3267 3268 3269

  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
  SQueryCostInfo* pCost = &pQInfo->summary;

  if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf > 0) {
    *status = BLK_DATA_ALL_NEEDED;
  } else { // check if this data block is required to load
    // 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 已提交
3270
    if (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info)) {
H
Haojun Liao 已提交
3271
      *status = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
3272
    }
H
Haojun Liao 已提交
3273 3274 3275 3276

    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 已提交
3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297
      if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
        SResultRow* pResult = NULL;

        bool  masterScan = IS_MASTER_SCAN(pRuntimeEnv);
        TSKEY k = QUERY_IS_ASC_QUERY(pQuery)? pBlock->info.window.skey:pBlock->info.window.ekey;
        STimeWindow win = getActiveTimeWindow(pWindowResInfo, k, pQuery);
        if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, &win, masterScan, &pResult, groupId) != TSDB_CODE_SUCCESS) {
          // todo handle error in set result for timewindow
        }
      }

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

        int32_t functionId = pSqlFunc->functionId;
        int32_t colId = pSqlFunc->colInfo.colId;
        (*status) |= aAggs[functionId].dataReqFunc(&pCtx[i], &pBlock->info.window, colId);
        if (((*status) & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) {
          break;
        }
      }
H
Haojun Liao 已提交
3298 3299 3300
    }
  }

H
Haojun Liao 已提交
3301 3302
  SDataBlockInfo* pBlockInfo = &pBlock->info;

H
Haojun Liao 已提交
3303
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
3304 3305
    qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", pQInfo, pBlockInfo->window.skey,
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
3306 3307 3308 3309 3310
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {

    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
3311
    tsdbRetrieveDataBlockStatisInfo(pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
3312

H
Haojun Liao 已提交
3313 3314 3315
    if (pBlock->pBlockStatis == NULL) { // data block statistics does not exist, load data block
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
3316 3317 3318 3319 3320 3321
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344
    if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) {

      bool load = false;
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
        int32_t functionId = pCtx[i].functionId;
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
          load = topbot_datablock_filter(&pCtx[i], (char *)&(pBlock->pBlockStatis[i].min), (char *)&(pBlock->pBlockStatis[i].max));
          if (!load) {
            // current block has been discard due to filter applied
            pCost->discardBlocks += 1;
            qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", pQInfo, pBlockInfo->window.skey,
                   pBlockInfo->window.ekey, pBlockInfo->rows);
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
    if (!doDataBlockStaticFilter(pRuntimeEnv, pBlock->pBlockStatis, pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
3345
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
3346
      qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", pQInfo, pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
3347
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
3348
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3349 3350 3351 3352
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
3353 3354
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pQueryHandle, NULL);
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
3355 3356
      return terrno;
    }
H
Haojun Liao 已提交
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373

    if (pQuery->numOfFilterCols > 0) {
      if (pQuery->pFilterInfo[0].pData == NULL) {
        for(int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
          for(int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
            SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j);

            if (pQuery->pFilterInfo[i].info.colId == pColInfo->info.colId) {
              pQuery->pFilterInfo[i].pData = pColInfo->pData;
              break;
            }
          }
        }
      }

      filterDataBlock_rv(pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock);
    }
H
Haojun Liao 已提交
3374 3375 3376 3377 3378
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
3379
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
3380
  int32_t midPos = -1;
H
Haojun Liao 已提交
3381
  int32_t numOfRows;
3382

3383 3384 3385
  if (num <= 0) {
    return -1;
  }
3386

3387
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
3388 3389

  TSKEY * keyList = (TSKEY *)pValue;
3390
  int32_t firstPos = 0;
3391
  int32_t lastPos = num - 1;
3392

3393
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
3394 3395 3396 3397 3398
    // 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;
3399

H
Haojun Liao 已提交
3400 3401
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
3402

H
hjxilinx 已提交
3403 3404 3405 3406 3407 3408 3409 3410
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
3411

H
hjxilinx 已提交
3412 3413 3414 3415 3416
  } 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;
3417

H
hjxilinx 已提交
3418 3419 3420 3421 3422 3423 3424
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
3425

H
Haojun Liao 已提交
3426
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
3427
      midPos = (numOfRows >> 1u) + firstPos;
3428

H
hjxilinx 已提交
3429 3430 3431 3432 3433 3434 3435 3436 3437
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
3438

H
hjxilinx 已提交
3439 3440 3441
  return midPos;
}

H
Haojun Liao 已提交
3442
static void expandBuffer(SQueryRuntimeEnv* pRuntimeEnv, int32_t newSize, void* qinfo) {
3443
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3444
  SResultRec *pRec = &pQuery->rec;
3445

H
Haojun Liao 已提交
3446
  assert(newSize > 0);
3447 3448

  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
3449
    int32_t bytes = pQuery->pExpr1[i].bytes;
3450

H
Haojun Liao 已提交
3451
    char *tmp = realloc(pQuery->sdata[i], bytes * newSize + sizeof(tFilePage));
H
Haojun Liao 已提交
3452
    if (tmp == NULL) {
H
Haojun Liao 已提交
3453
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
3454
    } else {
H
Haojun Liao 已提交
3455
      memset(tmp + sizeof(tFilePage) + bytes * pRec->rows, 0, (size_t)((newSize - pRec->rows) * bytes));
3456 3457 3458 3459
      pQuery->sdata[i] = (tFilePage *)tmp;
    }
  }

H
Haojun Liao 已提交
3460 3461 3462
  pRec->capacity = newSize;
  qDebug("QInfo:%p realloc output buffer, new size: %d rows, old:%" PRId64 ", remain:%" PRId64, qinfo, newSize,
      pRec->capacity, newSize - pRec->rows);
3463 3464
}

H
Haojun Liao 已提交
3465
static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
3466 3467
  // in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3468
  if (!QUERY_IS_INTERVAL_QUERY(pQuery) && !pQuery->groupbyColumn && !isFixedOutputQuery(pQuery) && !isTsCompQuery(pQuery)) {
3469
    SResultRec *pRec = &pQuery->rec;
3470

H
Haojun Liao 已提交
3471 3472 3473 3474
    int32_t remain  = (int32_t)(pRec->capacity - pRec->rows);
    if (remain < numOfRows) {
      int32_t newSize = (int32_t)(pRec->capacity + (numOfRows - remain));
      expandBuffer(pRuntimeEnv, newSize, GET_QINFO_ADDR(pRuntimeEnv));
3475

3476
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
3477
        int32_t bytes = pQuery->pExpr1[i].bytes;
H
Haojun Liao 已提交
3478

3479
        // set the pCtx output buffer position
3480
        pRuntimeEnv->pCtx[i].pOutput = pQuery->sdata[i]->data + pRec->rows * bytes;
H
Haojun Liao 已提交
3481

H
Haojun Liao 已提交
3482
        int32_t functionId = pQuery->pExpr1[i].base.functionId;
3483
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3484
          pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput;
3485 3486 3487 3488 3489 3490
        }
      }
    }
  }
}

3491 3492 3493
static void doSetInitialTimewindow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pBlockInfo) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
3494
  if (QUERY_IS_INTERVAL_QUERY(pQuery) && pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL) {
3495
    STimeWindow w = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3496
    SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
3497 3498 3499 3500

    if (QUERY_IS_ASC_QUERY(pQuery)) {
      getAlignQueryTimeWindow(pQuery, pBlockInfo->window.skey, pBlockInfo->window.skey, pQuery->window.ekey, &w);
      pWindowResInfo->prevSKey = w.skey;
3501
    } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
3502 3503 3504 3505 3506 3507
      getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, pQuery->window.ekey, pBlockInfo->window.ekey, &w);
      pWindowResInfo->prevSKey = w.skey;
    }
  }
}

3508 3509
static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
3510
  STableQueryInfo* pTableQueryInfo = pQuery->current;
H
Haojun Liao 已提交
3511 3512 3513

  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
  SQueryCostInfo*  summary  = &pQInfo->summary;
3514

3515
  qDebug("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", lastkey:%" PRId64 ", order:%d",
H
hjxilinx 已提交
3516 3517
         GET_QINFO_ADDR(pRuntimeEnv), pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, pTableQueryInfo->lastKey,
         pQuery->order.order);
3518

3519
  TsdbQueryHandleT pQueryHandle = IS_MASTER_SCAN(pRuntimeEnv)? pRuntimeEnv->pQueryHandle : pRuntimeEnv->pSecQueryHandle;
H
Haojun Liao 已提交
3520
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
H
Haojun Liao 已提交
3521

H
Haojun Liao 已提交
3522
  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
H
Haojun Liao 已提交
3523
  while (tsdbNextDataBlock(pQueryHandle)) {
H
Haojun Liao 已提交
3524
    summary->totalBlocks += 1;
H
Haojun Liao 已提交
3525

3526 3527 3528 3529
    if (IS_MASTER_SCAN(pRuntimeEnv)) {
      pQuery->numOfCheckedBlocks += 1;
    }

3530
    if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) {
H
Haojun Liao 已提交
3531
      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
3532
    }
3533

H
Haojun Liao 已提交
3534
    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
3535
    doSetInitialTimewindow(pRuntimeEnv, &blockInfo);
3536

H
hjxilinx 已提交
3537
    // in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block
H
Haojun Liao 已提交
3538
    ensureOutputBuffer(pRuntimeEnv, blockInfo.rows);
3539

3540
    SDataStatis *pStatis = NULL;
3541 3542
    SArray *     pDataBlock = NULL;
    uint32_t     status = 0;
3543

H
Haojun Liao 已提交
3544
    int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, pQueryHandle, &blockInfo, &pStatis, &pDataBlock, &status);
3545
    if (ret != TSDB_CODE_SUCCESS) {
3546 3547 3548
      break;
    }

3549 3550 3551 3552 3553 3554
    if (status == BLK_DATA_DISCARD) {
      pQuery->current->lastKey =
              QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step;
      continue;
    }

H
Haojun Liao 已提交
3555 3556
    // query start position can not move into tableApplyFunctionsOnBlock due to limit/offset condition
    pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : blockInfo.rows - 1;
H
hjxilinx 已提交
3557
    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey, pDataBlock);
3558

H
Haojun Liao 已提交
3559
    summary->totalRows += blockInfo.rows;
3560
    qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QINFO_ADDR(pRuntimeEnv),
3561
           blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes, pQuery->current->lastKey);
3562

3563 3564
    // while the output buffer is full or limit/offset is applied, query may be paused here
    if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL | QUERY_COMPLETED)) {
H
hjxilinx 已提交
3565
      break;
3566 3567
    }
  }
3568

H
Haojun Liao 已提交
3569 3570 3571 3572
  if (terrno != TSDB_CODE_SUCCESS) {
    longjmp(pRuntimeEnv->env, terrno);
  }

H
hjxilinx 已提交
3573
  // if the result buffer is not full, set the query complete
3574 3575 3576
  if (!Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) {
    setQueryStatus(pQuery, QUERY_COMPLETED);
  }
3577

3578
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
3579 3580
    closeAllResultRows(&pRuntimeEnv->resultRowInfo);
    pRuntimeEnv->resultRowInfo.curIndex = pRuntimeEnv->resultRowInfo.size - 1;  // point to the last time window
3581
  }
3582

3583
  return 0;
3584 3585 3586 3587 3588 3589
}

/*
 * set tag value in SQLFunctionCtx
 * e.g.,tag information into input buffer
 */
3590
static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes) {
H
[td-90]  
Haojun Liao 已提交
3591
  tVariantDestroy(tag);
3592

3593
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
3594
    char* val = tsdbGetTableName(pTable);
H
[td-90]  
Haojun Liao 已提交
3595
    assert(val != NULL);
3596

H
[td-90]  
Haojun Liao 已提交
3597
    tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), TSDB_DATA_TYPE_BINARY);
3598
  } else {
3599
    char* val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
H
[td-90]  
Haojun Liao 已提交
3600 3601 3602 3603
    if (val == NULL) {
      tag->nType = TSDB_DATA_TYPE_NULL;
      return;
    }
3604

H
hjxilinx 已提交
3605
    if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Hongze Cheng 已提交
3606
      if (isNull(val, type)) {
H
Haojun Liao 已提交
3607 3608 3609 3610
        tag->nType = TSDB_DATA_TYPE_NULL;
        return;
      }

H
[td-90]  
Haojun Liao 已提交
3611
      tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
H
hjxilinx 已提交
3612
    } else {
H
Haojun Liao 已提交
3613 3614 3615 3616 3617
      if (isNull(val, type)) {
        tag->nType = TSDB_DATA_TYPE_NULL;
        return;
      }

H
[td-90]  
Haojun Liao 已提交
3618
      tVariantCreateFromBinary(tag, val, bytes, type);
H
hjxilinx 已提交
3619
    }
3620
  }
3621 3622
}

3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634
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;
}

3635
void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable) {
3636
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3637
  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
3638

H
Haojun Liao 已提交
3639
  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
H
Haojun Liao 已提交
3640
  if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQuery->stableQuery) {
H
[td-90]  
Haojun Liao 已提交
3641
    assert(pExprInfo->base.numOfParams == 1);
H
Haojun Liao 已提交
3642

S
TD-1057  
Shengliang Guan 已提交
3643
    int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64;
3644
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId);
H
Haojun Liao 已提交
3645

3646
    doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes);
3647 3648
  } else {
    // set tag value, by which the results are aggregated.
3649 3650
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
3651
    for (int32_t idx = 0; idx < pQuery->numOfOutput; ++idx) {
H
Haojun Liao 已提交
3652
      SExprInfo* pLocalExprInfo = &pQuery->pExpr1[idx];
3653

3654
      // ts_comp column required the tag value for join filter
H
Haojun Liao 已提交
3655
      if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) {
3656 3657
        continue;
      }
3658

3659
      // todo use tag column index to optimize performance
3660
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pRuntimeEnv->pCtx[idx].tag,
H
Haojun Liao 已提交
3661
                           pLocalExprInfo->type, pLocalExprInfo->bytes);
3662 3663 3664 3665 3666 3667 3668 3669

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pRuntimeEnv->pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
        memcpy(pRuntimeEnv->tagVal + offset, pRuntimeEnv->pCtx[idx].tag.pz, pRuntimeEnv->pCtx[idx].tag.nLen);
      }

      offset += pLocalExprInfo->bytes;
3670
    }
3671

3672
    // set the join tag for first column
H
[td-90]  
Haojun Liao 已提交
3673
    SSqlFuncMsg *pFuncMsg = &pExprInfo->base;
H
Haojun Liao 已提交
3674
    if ((pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) && pRuntimeEnv->pTsBuf != NULL &&
3675
        pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
3676
      assert(pFuncMsg->numOfParams == 1);
H
Haojun Liao 已提交
3677

3678 3679
      int16_t      tagColId = (int16_t)pExprInfo->base.arg->argValue.i64;
      SColumnInfo *pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId);
H
Haojun Liao 已提交
3680

3681
      doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
3682

3683 3684 3685 3686 3687 3688
      int16_t tagType = pRuntimeEnv->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", pQInfo,
               pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.pz);
      } else {
        qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pQInfo,
3689
               pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.i64);
3690
      }
3691 3692 3693
    }
  }
}
H
Haojun Liao 已提交
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751
void setTagVal_rv(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, SExprInfo* pExpr, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
  SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);

  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
  if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQuery->stableQuery) {
    assert(pExprInfo->base.numOfParams == 1);

    int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64;
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId);

    doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes);
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
    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
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type, pLocalExprInfo->bytes);

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pRuntimeEnv->pCtx[idx].tag.nLen);
      }

      offset += pLocalExprInfo->bytes;
    }

    // set the join tag for first column
    SSqlFuncMsg *pFuncMsg = &pExprInfo->base;
    if ((pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) && pRuntimeEnv->pTsBuf != NULL &&
        pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
      assert(pFuncMsg->numOfParams == 1);

      int16_t      tagColId = (int16_t)pExprInfo->base.arg->argValue.i64;
      SColumnInfo *pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId);

      doSetTagValueInParam(pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes);

      int16_t tagType = pRuntimeEnv->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", pQInfo,
               pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.pz);
      } else {
        qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pQInfo,
               pExprInfo->base.arg->argValue.i64, pRuntimeEnv->pCtx[0].tag.i64);
      }
    }
  }
}
3752

3753
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821
  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);
  }
}

3822
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
3823
  SQuery* pQuery = pRuntimeEnv->pQuery;
3824
  int32_t numOfCols = pQuery->numOfOutput;
3825
  printf("super table query intermediate result, total:%d\n", numOfRows);
3826

3827 3828
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
3829

H
Haojun Liao 已提交
3830
      switch (pQuery->pExpr1[i].type) {
3831
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
3832 3833
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
3834 3835 3836 3837 3838
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
3839
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3840 3841
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
3842
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3843 3844
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
3845
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3846 3847
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
3848
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3849 3850 3851 3852 3853 3854 3855
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
3856
static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType);
3857

3858
void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) {
H
Haojun Liao 已提交
3859
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3860
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
3861

H
Haojun Liao 已提交
3862 3863 3864 3865
  while(pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
    // 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 已提交
3866
      if ((pQInfo->code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3867
        return;
3868
      }
H
Haojun Liao 已提交
3869
    }
3870

H
Haojun Liao 已提交
3871
    pQuery->rec.rows = doCopyToSData(&pQInfo->runtimeEnv, pGroupResInfo, TSDB_ORDER_ASC);
3872

H
Haojun Liao 已提交
3873 3874 3875 3876
    // current data are all dumped to result buffer, clear it
    if (!hasRemainData(pGroupResInfo)) {
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3877
        SET_STABLE_QUERY_OVER(pRuntimeEnv);
3878 3879
      }
    }
3880

H
Haojun Liao 已提交
3881 3882 3883 3884
    // enough results in data buffer, return
    if (pQuery->rec.rows >= pQuery->rec.threshold) {
      break;
    }
3885 3886 3887
  }
}

H
Haojun Liao 已提交
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917
void copyResToQueryResultBuf_rv(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock) {
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;

  int32_t code = TSDB_CODE_SUCCESS;
  while(pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
    // 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);
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv)) != TSDB_CODE_SUCCESS) {
        return;
      }
    }

    doCopyToSData_rv(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);

    // current data are all dumped to result buffer, clear it
    if (!hasRemainData(pGroupResInfo)) {
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
        SET_STABLE_QUERY_OVER(pRuntimeEnv);
      }
    }

    // enough results in data buffer, return
    if (pBlock->info.rows >= threshold) {
      break;
    }
  }
}

3918 3919 3920 3921
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
3922

3923 3924
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3925

3926 3927
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
3928 3929

  // set the index at the end of time window
H
Haojun Liao 已提交
3930
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
3931 3932
}

H
Haojun Liao 已提交
3933
static void disableFuncInReverseScanImpl(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo *pWindowResInfo, int32_t order) {
3934
  SQuery* pQuery = pRuntimeEnv->pQuery;
3935

3936
  for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
3937
    bool closed = getResultRowStatus(pWindowResInfo, i);
3938
    if (!closed) {
3939 3940
      continue;
    }
3941

3942
    SResultRow *pRow = getResultRow(pWindowResInfo, i);
3943

3944
    // open/close the specified query for each group result
3945
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
3946
      int32_t functId = pQuery->pExpr1[j].base.functionId;
3947
      SResultRowCellInfo* pInfo = getResultCell(pRuntimeEnv, pRow, j);
3948

3949 3950
      if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSDB_ORDER_ASC) ||
          ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSDB_ORDER_DESC)) {
3951
        pInfo->complete = false;
3952
      } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
3953
        pInfo->complete = true;
3954 3955 3956 3957 3958
      }
    }
  }
}

H
Haojun Liao 已提交
3959
void disableFuncInReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
3960
  SQuery *pQuery = pRuntimeEnv->pQuery;
3961
  int32_t order = pQuery->order.order;
3962

3963
  // group by normal columns and interval query on normal table
H
Haojun Liao 已提交
3964
  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
3965
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
3966
    disableFuncInReverseScanImpl(pRuntimeEnv, pWindowResInfo, order);
3967
  } else {  // for simple result of table query,
3968
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {  // todo refactor
H
Haojun Liao 已提交
3969
      int32_t functId = pQuery->pExpr1[j].base.functionId;
3970

3971
      SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[j];
3972 3973 3974
      if (pCtx->resultInfo == NULL) {
        continue; // resultInfo is NULL, means no data checked in previous scan
      }
3975

3976 3977
      if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSDB_ORDER_ASC) ||
          ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSDB_ORDER_DESC)) {
3978 3979 3980 3981 3982 3983
        pCtx->resultInfo->complete = false;
      } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
        pCtx->resultInfo->complete = true;
      }
    }
  }
H
Haojun Liao 已提交
3984 3985
}

H
Haojun Liao 已提交
3986 3987
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3988
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
3989

H
hjxilinx 已提交
3990
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3991
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3992
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
3993

H
hjxilinx 已提交
3994 3995
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
3996 3997
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
3998

H
Haojun Liao 已提交
3999 4000
      // update the last key in tableKeyInfo list, the tableKeyInfo is used to build the tsdbQueryHandle and decide
      // the start check timestamp of tsdbQueryHandle
H
Haojun Liao 已提交
4001 4002 4003 4004
      STableKeyInfo *pTableKeyInfo = taosArrayGet(tableKeyGroup, j);
      pTableKeyInfo->lastKey = pCheckInfo->lastKey;

      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
hjxilinx 已提交
4005 4006
    }
  }
4007 4008
}

4009
void switchCtxOrder(SQueryRuntimeEnv *pRuntimeEnv) {
4010
  SQuery *pQuery = pRuntimeEnv->pQuery;
4011
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
4012
    SWITCH_ORDER(pRuntimeEnv->pCtx[i].order);
4013 4014 4015
  }
}

4016
int32_t initResultRow(SResultRow *pResultRow) {
H
Haojun Liao 已提交
4017
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
H
Haojun Liao 已提交
4018 4019
  pResultRow->pageId    = -1;
  pResultRow->rowId     = -1;
B
Bomin Zhang 已提交
4020
  return TSDB_CODE_SUCCESS;
4021 4022
}

H
Haojun Liao 已提交
4023
void resetDefaultResInfoOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) {
4024
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4025

H
Haojun Liao 已提交
4026
  int32_t tid = 0;
4027
  int64_t uid = 0;
H
Haojun Liao 已提交
4028
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, (char *)&tid, sizeof(tid), true, uid);
4029

4030
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
4031
    SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
4032
    pCtx->pOutput = pQuery->sdata[i]->data;
4033

4034 4035 4036 4037
    /*
     * set the output buffer information and intermediate buffer
     * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc.
     */
4038 4039 4040
    SResultRowCellInfo* pCellInfo = getResultCell(pRuntimeEnv, pRow, i);
    RESET_RESULT_INFO(pCellInfo);
    pCtx->resultInfo = pCellInfo;
4041

4042
    // set the timestamp output buffer for top/bottom/diff query
H
Haojun Liao 已提交
4043
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
4044
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
4045
      pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput;
4046
    }
4047

H
Haojun Liao 已提交
4048
    memset(pQuery->sdata[i]->data, 0, (size_t)(pQuery->pExpr1[i].bytes * pQuery->rec.capacity));
4049
  }
4050

H
Haojun Liao 已提交
4051
  initCtxOutputBuf(pRuntimeEnv, pRuntimeEnv->pCtx);
4052 4053
}

H
Haojun Liao 已提交
4054
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
4055 4056
  int32_t tid = 0;
  int64_t uid = 0;
H
Haojun Liao 已提交
4057
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
H
Haojun Liao 已提交
4058

H
Haojun Liao 已提交
4059 4060
  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
    SColumnInfoData* pData = taosArrayGet(pDataBlock->pDataBlock, i);
H
Haojun Liao 已提交
4061 4062 4063 4064 4065 4066 4067 4068

    /*
     * set the output buffer information and intermediate buffer
     * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc.
     */
    SResultRowCellInfo* pCellInfo = getResultCell(pRuntimeEnv, pRow, i);
    RESET_RESULT_INFO(pCellInfo);

H
Haojun Liao 已提交
4069 4070
    pCtx[i].resultInfo = pCellInfo;
    pCtx[i].pOutput = pData->pData;
H
Haojun Liao 已提交
4071 4072 4073 4074

    // set the timestamp output buffer for top/bottom/diff query
    int32_t functionId = pCtx->functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
4075
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
4076 4077 4078
    }
  }

H
Haojun Liao 已提交
4079
  initCtxOutputBuf_rv(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
4080 4081
}

4082 4083
void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
4084

4085
  // reset the execution contexts
4086
  for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4087
    int32_t functionId = pQuery->pExpr1[j].base.functionId;
4088
    assert(functionId != TSDB_FUNC_DIFF);
4089

4090
    // set next output position
H
Haojun Liao 已提交
4091
    if (IS_OUTER_FORWARD(aAggs[functionId].status)) {
4092
      pRuntimeEnv->pCtx[j].pOutput += pRuntimeEnv->pCtx[j].outputBytes * output;
4093
    }
4094

4095 4096 4097 4098 4099 4100 4101 4102
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      /*
       * NOTE: for top/bottom query, the value of first column of output (timestamp) are assigned
       * in the procedure of top/bottom routine
       * the output buffer in top/bottom routine is ptsOutputBuf, so we need to forward the output buffer
       *
       * diff function is handled in multi-output function
       */
S
TD-1057  
Shengliang Guan 已提交
4103
      pRuntimeEnv->pCtx[j].ptsOutputBuf = (char*)pRuntimeEnv->pCtx[j].ptsOutputBuf + TSDB_KEYSIZE * output;
4104
    }
4105

4106
    RESET_RESULT_INFO(pRuntimeEnv->pCtx[j].resultInfo);
4107 4108 4109
  }
}

H
Haojun Liao 已提交
4110
void initCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx) {
4111
  SQuery *pQuery = pRuntimeEnv->pQuery;
4112

4113
  for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4114 4115 4116 4117 4118 4119
    pCtx[j].currentStage = 0;

    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
    }
4120

H
Haojun Liao 已提交
4121 4122 4123 4124 4125 4126 4127 4128
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
  }
}
void initCtxOutputBuf_rv(SQLFunctionCtx* pCtx, int32_t size) {
  for (int32_t j = 0; j < size; ++j) {
    pCtx[j].currentStage = 0;

    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
H
Haojun Liao 已提交
4129 4130 4131
    if (pResInfo->initialized) {
      continue;
    }
4132

H
Haojun Liao 已提交
4133
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
4134 4135 4136
  }
}

4137
void skipResults(SQueryRuntimeEnv *pRuntimeEnv) {
4138
  SQuery *pQuery = pRuntimeEnv->pQuery;
4139
  if (pQuery->rec.rows == 0 || pQuery->limit.offset == 0) {
4140 4141
    return;
  }
4142

4143
  if (pQuery->rec.rows <= pQuery->limit.offset) {
4144
    qDebug("QInfo:%p skip rows:%" PRId64 ", new offset:%" PRIu64, GET_QINFO_ADDR(pRuntimeEnv), pQuery->rec.rows,
4145
        pQuery->limit.offset - pQuery->rec.rows);
4146

4147 4148
    pQuery->limit.offset -= pQuery->rec.rows;
    pQuery->rec.rows = 0;
4149

H
Haojun Liao 已提交
4150
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
4151

H
Haojun Liao 已提交
4152
    // clear the buffer full flag if exists
4153
    CLEAR_QUERY_STATUS(pQuery, QUERY_RESBUF_FULL);
4154
  } else {
4155
    int64_t numOfSkip = pQuery->limit.offset;
4156
    pQuery->rec.rows -= numOfSkip;
4157
    pQuery->limit.offset = 0;
4158

4159
    qDebug("QInfo:%p skip row:%"PRId64", new offset:%d, numOfRows remain:%" PRIu64, GET_QINFO_ADDR(pRuntimeEnv), numOfSkip,
4160
           0, pQuery->rec.rows);
4161

4162
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
4163
      int32_t functionId = pQuery->pExpr1[i].base.functionId;
4164
      int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes;
H
Haojun Liao 已提交
4165

4166
      memmove(pQuery->sdata[i]->data, (char*)pQuery->sdata[i]->data + bytes * numOfSkip, (size_t)(pQuery->rec.rows * bytes));
4167
      pRuntimeEnv->pCtx[i].pOutput = ((char*) pQuery->sdata[i]->data) + pQuery->rec.rows * bytes;
4168

4169
      if (functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
4170
        pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput;
4171 4172
      }
    }
4173

S
TD-1057  
Shengliang Guan 已提交
4174
    updateNumOfResult(pRuntimeEnv, (int32_t)pQuery->rec.rows);
4175 4176 4177 4178 4179 4180 4181 4182
  }
}

void setQueryStatus(SQuery *pQuery, int8_t status) {
  if (status == QUERY_NOT_COMPLETED) {
    pQuery->status = status;
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
4183
    CLEAR_QUERY_STATUS(pQuery, QUERY_NOT_COMPLETED);
4184 4185 4186 4187
    pQuery->status |= status;
  }
}

H
Haojun Liao 已提交
4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219
void prepareRepeatTableScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery *pQuery = pRuntimeEnv->pQuery;

  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
    // for each group result, call the finalize function for each column
    SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;

    for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
      SResultRow *pResult = getResultRow(pWindowResInfo, i);

      setResultOutputBuf(pRuntimeEnv, pResult);
      for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
        SQLFunctionCtx* pCtx = &pRuntimeEnv->pCtx[j];
        if (pCtx->functionId == TSDB_FUNC_TS) { // ignore more table
          continue;
        }

        aAggs[pCtx->functionId].xNextStep(pCtx);
      }
    }
  } else {
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
      SQLFunctionCtx* pCtx = &pRuntimeEnv->pCtx[j];
      if (pCtx->functionId == TSDB_FUNC_TS) {
        continue;
      }

      aAggs[pCtx->functionId].xNextStep(pCtx);
    }
  }
}

4220
bool needRepeatScan(SQueryRuntimeEnv *pRuntimeEnv) {
4221
  SQuery *pQuery = pRuntimeEnv->pQuery;
4222

H
hjxilinx 已提交
4223
  bool toContinue = false;
H
Haojun Liao 已提交
4224
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
4225
    // for each group result, call the finalize function for each column
H
Haojun Liao 已提交
4226
    SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
4227

4228
    for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
4229
      SResultRow *pResult = getResultRow(pWindowResInfo, i);
4230

4231
      setResultOutputBuf(pRuntimeEnv, pResult);
4232
      for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4233
        int16_t functId = pQuery->pExpr1[j].base.functionId;
4234 4235 4236
        if (functId == TSDB_FUNC_TS) {
          continue;
        }
4237

4238
        aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]);
H
Haojun Liao 已提交
4239
        SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
4240

4241 4242 4243 4244
        toContinue |= (!pResInfo->complete);
      }
    }
  } else {
4245
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4246
      int16_t functId = pQuery->pExpr1[j].base.functionId;
4247 4248 4249
      if (functId == TSDB_FUNC_TS) {
        continue;
      }
4250

4251
      aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]);
H
Haojun Liao 已提交
4252
      SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
4253

4254 4255 4256
      toContinue |= (!pResInfo->complete);
    }
  }
4257

4258 4259 4260
  return toContinue;
}

H
Haojun Liao 已提交
4261
static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
4262
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
4263
  STableQueryInfo* pTableQueryInfo = pQuery->current;
4264

H
Haojun Liao 已提交
4265 4266
  assert((start <= pTableQueryInfo->lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (start >= pTableQueryInfo->lastKey && !QUERY_IS_ASC_QUERY(pQuery)));
4267

4268
  SQueryStatusInfo info = {
H
hjxilinx 已提交
4269
      .status      = pQuery->status,
H
Haojun Liao 已提交
4270
      .windowIndex = pRuntimeEnv->resultRowInfo.curIndex,
H
Haojun Liao 已提交
4271
      .lastKey     = start,
4272
  };
4273

S
TD-1057  
Shengliang Guan 已提交
4274
  TIME_WINDOW_COPY(info.w, pQuery->window);
4275 4276 4277
  return info;
}

4278 4279 4280 4281
static void setEnvBeforeReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusInfo *pStatus) {
  SQInfo *pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
  SQuery *pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
4282 4283 4284 4285
  pStatus->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);  // save the cursor
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
4286
    assert(ret);
4287
  }
4288

4289
  // reverse order time range
4290
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
4291
  SWITCH_ORDER(pQuery->order.order);
4292 4293 4294 4295 4296 4297 4298

  if (QUERY_IS_ASC_QUERY(pQuery)) {
    assert(pQuery->window.skey <= pQuery->window.ekey);
  } else {
    assert(pQuery->window.skey >= pQuery->window.ekey);
  }

4299
  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
4300
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
4301

H
Haojun Liao 已提交
4302 4303
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
  switchCtxOrder(pRuntimeEnv);
H
Haojun Liao 已提交
4304
  disableFuncInReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
4305
  setupQueryRangeForReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
4306

4307 4308 4309 4310
  // clean unused handle
  if (pRuntimeEnv->pSecQueryHandle != NULL) {
    tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle);
  }
4311

H
Haojun Liao 已提交
4312
  pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
B
Bomin Zhang 已提交
4313 4314 4315
  if (pRuntimeEnv->pSecQueryHandle == NULL) {
    longjmp(pRuntimeEnv->env, terrno);
  }
4316 4317
}

H
Haojun Liao 已提交
4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333
static void setEnvBeforeReverseScan_rv(SQueryRuntimeEnv *pRuntimeEnv) {
  SQuery *pQuery = pRuntimeEnv->pQuery;

  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
  }

  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
  SWITCH_ORDER(pQuery->order.order);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
  switchCtxOrder(pRuntimeEnv);
H
Haojun Liao 已提交
4334
  disableFuncInReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
4335
  setupQueryRangeForReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
4336 4337
}

4338 4339
static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusInfo *pStatus) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
4340
  STableQueryInfo* pTableQueryInfo = pQuery->current;
4341

4342 4343
  SWITCH_ORDER(pQuery->order.order);
  switchCtxOrder(pRuntimeEnv);
4344

H
Haojun Liao 已提交
4345 4346 4347
  tsBufSetCursor(pRuntimeEnv->pTsBuf, &pStatus->cur);
  if (pRuntimeEnv->pTsBuf) {
    pRuntimeEnv->pTsBuf->cur.order = pQuery->order.order;
4348
  }
4349

4350
  SET_MASTER_SCAN_FLAG(pRuntimeEnv);
4351

4352
  // update the pQuery->window.skey and pQuery->window.ekey to limit the scan scope of sliding query during reverse scan
H
hjxilinx 已提交
4353
  pTableQueryInfo->lastKey = pStatus->lastKey;
4354
  pQuery->status = pStatus->status;
4355

H
hjxilinx 已提交
4356
  pTableQueryInfo->win = pStatus->w;
4357
  pQuery->window = pTableQueryInfo->win;
4358 4359
}

H
Haojun Liao 已提交
4360 4361 4362 4363 4364 4365 4366
static void restoreTimeWindow(STableGroupInfo* pTableGroupInfo, STsdbQueryCond* pCond) {
  assert(pTableGroupInfo->numOfTables == 1);
  SArray* pTableKeyGroup = taosArrayGetP(pTableGroupInfo->pGroupList, 0);
  STableKeyInfo* pKeyInfo = taosArrayGet(pTableKeyGroup, 0);
  pKeyInfo->lastKey = pCond->twindow.skey;
}

H
Haojun Liao 已提交
4367 4368 4369 4370 4371 4372 4373 4374
static void handleInterpolationQuery(SQInfo* pQInfo) {
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;

  SQuery *pQuery = pRuntimeEnv->pQuery;
  if (pQuery->numOfCheckedBlocks > 0 || !isPointInterpoQuery(pQuery)) {
    return;
  }

H
Haojun Liao 已提交
4375 4376
  SArray *prev = tsdbGetExternalRow(pRuntimeEnv->pQueryHandle, &pQuery->memRef, TSDB_PREV_ROW);
  SArray *next = tsdbGetExternalRow(pRuntimeEnv->pQueryHandle, &pQuery->memRef, TSDB_NEXT_ROW);
H
Haojun Liao 已提交
4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412
  if (prev == NULL || next == NULL) {
    return;
  }

  // setup the pCtx->start/end info and calculate the interpolation value
  SColumnInfoData *startTs = taosArrayGet(prev, 0);
  SColumnInfoData *endTs = taosArrayGet(next, 0);

  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];

    int32_t    functionId = pQuery->pExpr1[i].base.functionId;
    SColIndex *pColIndex = &pQuery->pExpr1[i].base.colInfo;

    if (!TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
      aAggs[functionId].xFunction(pCtx);
      continue;
    }

    SColumnInfoData *p = taosArrayGet(prev, pColIndex->colIndex);
    SColumnInfoData *n = taosArrayGet(next, pColIndex->colIndex);

    assert(p->info.colId == pColIndex->colId);

    pCtx->start.key = *(TSKEY *)startTs->pData;
    pCtx->end.key = *(TSKEY *)endTs->pData;

    if (p->info.type != TSDB_DATA_TYPE_BINARY && p->info.type != TSDB_DATA_TYPE_NCHAR) {
      GET_TYPED_DATA(pCtx->start.val, double, p->info.type, p->pData);
      GET_TYPED_DATA(pCtx->end.val, double, n->info.type, n->pData);
    } else {  // string pointer
      pCtx->start.ptr = p->pData;
      pCtx->end.ptr = n->pData;
    }

    pCtx->param[2].i64 = (int8_t)pQuery->fillType;
H
Haojun Liao 已提交
4413
    pCtx->startTs = pQuery->window.skey;
H
Haojun Liao 已提交
4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427
    if (pQuery->fillVal != NULL) {
      if (isNull((const char *)&pQuery->fillVal[i], pCtx->inputType)) {
        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) {
          tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQuery->fillVal[i], pCtx->inputBytes, pCtx->inputType);
        }
      }
    }

    aAggs[functionId].xFunction(pCtx);
  }
}

4428
void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
H
hjxilinx 已提交
4429
  SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv);
4430
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
4431
  STableQueryInfo *pTableQueryInfo = pQuery->current;
4432

4433
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
4434

4435
  // store the start query position
H
Haojun Liao 已提交
4436
  SQueryStatusInfo qstatus = getQueryStatusInfo(pRuntimeEnv, start);
4437
  SET_MASTER_SCAN_FLAG(pRuntimeEnv);
4438

H
Haojun Liao 已提交
4439
  if (!pQuery->groupbyColumn && pQuery->hasTagResults) {
4440
    setTagVal(pRuntimeEnv, pTableQueryInfo->pTable);
4441
  }
4442

4443 4444
  while (1) {
    doScanAllDataBlocks(pRuntimeEnv);
4445

4446 4447
    if (pRuntimeEnv->scanFlag == MASTER_SCAN) {
      qstatus.status = pQuery->status;
4448 4449

      // do nothing if no data blocks are found qualified during scan
4450
      if (qstatus.lastKey == pTableQueryInfo->lastKey) {
H
Haojun Liao 已提交
4451
        qDebug("QInfo:%p no results generated in this scan", pQInfo);
4452
      }
4453
    }
4454

4455
    if (!needRepeatScan(pRuntimeEnv)) {
4456
      // restore the status code and jump out of loop
4457
      if (pRuntimeEnv->scanFlag == REPEAT_SCAN) {
4458
        pQuery->status = qstatus.status;
4459
      }
4460

4461 4462
      break;
    }
4463

4464 4465
    if (pRuntimeEnv->pSecQueryHandle != NULL) {
      tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle);
4466
    }
4467

4468
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4469 4470
    restoreTimeWindow(&pQuery->tableGroupInfo, &cond);
    pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
B
Bomin Zhang 已提交
4471 4472 4473
    if (pRuntimeEnv->pSecQueryHandle == NULL) {
      longjmp(pRuntimeEnv->env, terrno);
    }
4474

H
Haojun Liao 已提交
4475
    pRuntimeEnv->resultRowInfo.curIndex = qstatus.windowIndex;
4476 4477
    setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
4478

D
fix bug  
dapan1121 已提交
4479 4480 4481 4482 4483
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4484
    qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%"PRId64"-%"PRId64, pQInfo,
4485
        cond.twindow.skey, cond.twindow.ekey);
4486
  }
4487

4488 4489
  if (needReverseScan(pQuery)) {
    setEnvBeforeReverseScan(pRuntimeEnv, &qstatus);
4490

4491 4492 4493
    // reverse scan from current position
    qDebug("QInfo:%p start to reverse scan", pQInfo);
    doScanAllDataBlocks(pRuntimeEnv);
4494

4495
    clearEnvAfterReverseScan(pRuntimeEnv, &qstatus);
4496
  }
4497

H
Haojun Liao 已提交
4498
  handleInterpolationQuery(pQInfo);
4499 4500
}

H
hjxilinx 已提交
4501
void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv) {
4502
  SQuery *pQuery = pRuntimeEnv->pQuery;
4503

H
Haojun Liao 已提交
4504
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
4505
    // for each group result, call the finalize function for each column
H
Haojun Liao 已提交
4506
    SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
4507
    if (pQuery->groupbyColumn) {
H
Haojun Liao 已提交
4508
      closeAllResultRows(pWindowResInfo);
4509
    }
4510

4511
    for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
H
Haojun Liao 已提交
4512
      SResultRow *buf = pWindowResInfo->pResult[i];
H
Haojun Liao 已提交
4513
      if (!isResultRowClosed(pWindowResInfo, i)) {
4514 4515
        continue;
      }
4516

4517
      setResultOutputBuf(pRuntimeEnv, buf);
4518

4519
      for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4520
        aAggs[pRuntimeEnv->pCtx[j].functionId].xFinalize(&pRuntimeEnv->pCtx[j]);
4521
      }
4522

4523 4524 4525 4526
      /*
       * 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
       */
S
TD-1057  
Shengliang Guan 已提交
4527
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv);
4528
    }
4529

4530
  } else {
4531
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4532
      aAggs[pQuery->pExpr1[j].base.functionId].xFinalize(&pRuntimeEnv->pCtx[j]);
4533 4534 4535 4536
    }
  }
}

H
Haojun Liao 已提交
4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570
void finalizeQueryResult_rv(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
    // for each group result, call the finalize function for each column
    if (pQuery->groupbyColumn) {
      closeAllResultRows(pResultRowInfo);
    }

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

      setResultOutputBuf_rv(pRuntimeEnv, buf, pCtx, numOfOutput);

      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
       */
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv);
    }

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

4571
static bool hasMainOutput(SQuery *pQuery) {
4572
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
4573
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
4574

4575 4576 4577 4578
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
4579

4580 4581 4582
  return false;
}

4583
static STableQueryInfo *createTableQueryInfo(SQuery* pQuery, void* pTable, bool groupbyColumn, STimeWindow win, void* buf) {
H
Haojun Liao 已提交
4584
  STableQueryInfo *pTableQueryInfo = buf;
4585

H
hjxilinx 已提交
4586 4587
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
4588

4589
  pTableQueryInfo->pTable = pTable;
4590
  pTableQueryInfo->cur.vgroupIndex = -1;
4591

H
Haojun Liao 已提交
4592
  // set more initial size of interval/groupby query
4593
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
4594
    int32_t initialSize = 128;
H
Haojun Liao 已提交
4595
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
4596 4597 4598
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
4599
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
4600 4601
  }

4602 4603 4604
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
4605
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
4606 4607 4608
  if (pTableQueryInfo == NULL) {
    return;
  }
4609

H
Haojun Liao 已提交
4610
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
4611
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
4612 4613 4614 4615 4616
}

/**
 * set output buffer for different group
 * @param pRuntimeEnv
4617
 * @param pDataBlockInfo
4618
 */
H
Haojun Liao 已提交
4619
void setExecutionContext(SQueryRuntimeEnv *pRuntimeEnv, int32_t groupIndex, TSKEY nextKey) {
H
Haojun Liao 已提交
4620
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->pQuery->current;
H
Haojun Liao 已提交
4621
  SResultRowInfo   *pWindowResInfo  = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
4622

H
Haojun Liao 已提交
4623 4624
  // lastKey needs to be updated
  pTableQueryInfo->lastKey = nextKey;
H
Haojun Liao 已提交
4625 4626 4627
  if (pRuntimeEnv->prevGroupId != INT32_MIN && pRuntimeEnv->prevGroupId == groupIndex) {
    return;
  }
4628

4629
  int64_t uid = 0;
H
Haojun Liao 已提交
4630
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pWindowResInfo, (char *)&groupIndex,
H
Haojun Liao 已提交
4631
      sizeof(groupIndex), true, uid);
4632
  assert (pResultRow != NULL);
4633

4634 4635 4636 4637
  /*
   * 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
   */
H
Haojun Liao 已提交
4638 4639
  if (pResultRow->pageId == -1) {
    if (addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->numOfRowsPerPage) !=
4640 4641 4642 4643
        TSDB_CODE_SUCCESS) {
      return;
    }
  }
4644

H
Haojun Liao 已提交
4645 4646
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
H
Haojun Liao 已提交
4647
  setResultOutputBuf(pRuntimeEnv, pResultRow);
H
Haojun Liao 已提交
4648
  initCtxOutputBuf(pRuntimeEnv, pRuntimeEnv->pCtx);
4649 4650
}

4651
void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) {
4652
  SQuery *pQuery = pRuntimeEnv->pQuery;
4653

4654
  // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group
4655
  tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId);
H
Haojun Liao 已提交
4656

4657
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
4658
    SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
4659
    pCtx->pOutput = getPosInResultPage(pRuntimeEnv, i, pResult, page);
4660

H
Haojun Liao 已提交
4661
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
4662
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
4663
      pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput;
4664
    }
4665

4666
    /*
4667
     * set the output buffer information and intermediate buffer,
4668 4669
     * not all queries require the interResultBuf, such as COUNT
     */
4670
    pCtx->resultInfo = getResultCell(pRuntimeEnv, pResult, i);
4671 4672 4673
  }
}

H
Haojun Liao 已提交
4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693
void setResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfCols) {
  // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group
  tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId);

  for (int32_t i = 0; i < numOfCols; ++i) {
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, i, pResult, page);

    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;
    }

    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
    pCtx[i].resultInfo = getResultCell(pRuntimeEnv, pResult, i);
  }
}

H
Haojun Liao 已提交
4694
void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) {
H
Haojun Liao 已提交
4695
  SQuery *pQuery = pRuntimeEnv->pQuery;
4696

H
Haojun Liao 已提交
4697
  // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group
4698
  tFilePage* bufPage = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pageId);
H
Haojun Liao 已提交
4699

H
Haojun Liao 已提交
4700 4701 4702
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];

4703
    pCtx->resultInfo = getResultCell(pRuntimeEnv, pResult, i);
H
Haojun Liao 已提交
4704
    if (pCtx->resultInfo->initialized && pCtx->resultInfo->complete) {
H
Haojun Liao 已提交
4705 4706
      continue;
    }
4707

4708
    pCtx->pOutput = getPosInResultPage(pRuntimeEnv, i, pResult, bufPage);
H
Haojun Liao 已提交
4709
    pCtx->currentStage = 0;
4710

H
Haojun Liao 已提交
4711 4712
    int32_t functionId = pCtx->functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
4713
      pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].pOutput;
H
Haojun Liao 已提交
4714
    }
4715

H
Haojun Liao 已提交
4716 4717 4718 4719 4720 4721
    if (!pCtx->resultInfo->initialized) {
      aAggs[functionId].init(pCtx);
    }
  }
}

H
Haojun Liao 已提交
4722 4723 4724
int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, STableQueryInfo *pTableQueryInfo) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

4725
  assert(pRuntimeEnv->pTsBuf != NULL);
4726

4727
  // both the master and supplement scan needs to set the correct ts comp start position
4728
  tVariant* pTag = &pRuntimeEnv->pCtx[0].tag;
H
Haojun Liao 已提交
4729

4730 4731
  if (pTableQueryInfo->cur.vgroupIndex == -1) {
    tVariantAssign(&pTableQueryInfo->tag, pTag);
4732

H
Haojun Liao 已提交
4733
    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, &pTableQueryInfo->tag);
H
Haojun Liao 已提交
4734

4735 4736
    // failed to find data with the specified tag value and vnodeId
    if (!tsBufIsValidElem(&elem)) {
H
Haojun Liao 已提交
4737
      if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
4738
        qError("QInfo:%p failed to find tag:%s in ts_comp", pRuntimeEnv->qinfo, pTag->pz);
H
Haojun Liao 已提交
4739
      } else {
H
Haojun Liao 已提交
4740
        qError("QInfo:%p failed to find tag:%" PRId64 " in ts_comp", pRuntimeEnv->qinfo, pTag->i64);
H
Haojun Liao 已提交
4741 4742
      }

4743 4744 4745 4746 4747 4748
      return false;
    }

    // keep the cursor info of current meter
    pTableQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
4749
      qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
4750
    } else {
H
Haojun Liao 已提交
4751
      qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
4752
    }
H
Haojun Liao 已提交
4753

4754 4755 4756 4757
  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);

    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
4758
      qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
4759
    } else {
H
Haojun Liao 已提交
4760
      qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
4761 4762 4763 4764 4765 4766 4767 4768 4769
    }
  }

  return 0;
}

int32_t setParamValue(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
4770
  if (pRuntimeEnv->prevResult == NULL || pQuery->groupbyColumn) {
4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785
    return TSDB_CODE_SUCCESS;
  }

  int32_t numOfExprs = pQuery->numOfOutput;
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SExprInfo* pExprInfo = &(pQuery->pExpr1[i]);
    if(pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) {
      continue;
    }

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

H
Haojun Liao 已提交
4786
    int32_t numOfGroup = (int32_t) taosArrayGetSize(pRuntimeEnv->prevResult);
4787 4788 4789 4790
    for(int32_t j = 0; j < numOfGroup; ++j) {
      SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, j);
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {

H
Haojun Liao 已提交
4791
        int32_t numOfCols = (int32_t) taosArrayGetSize(p->pResult);
4792 4793 4794 4795 4796 4797 4798
        for(int32_t k = 0; k < numOfCols; ++k) {
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pRuntimeEnv->pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
H
Haojun Liao 已提交
4799
      }
4800 4801
    }
  }
4802

4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814
  return 0;
}

/*
 * There are two cases to handle:
 *
 * 1. Query range is not set yet (queryRangeSet = 0). we need to set the query range info, including pQuery->lastKey,
 *    pQuery->window.skey, and pQuery->eKey.
 * 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 已提交
4815
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
4816 4817 4818
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
4819

H
Haojun Liao 已提交
4820 4821 4822
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
4823

H
Haojun Liao 已提交
4824 4825
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
4826

H
Haojun Liao 已提交
4827 4828 4829 4830 4831
  // for too small query range, no data in this interval.
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey < pQuery->window.skey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey < pQuery->window.ekey))) {
    return;
  }
4832

H
Haojun Liao 已提交
4833 4834 4835 4836 4837 4838
  /**
   * 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 已提交
4839
  STimeWindow w = TSWINDOW_INITIALIZER;
4840

H
Haojun Liao 已提交
4841 4842 4843
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
4844

H
Haojun Liao 已提交
4845 4846 4847
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
4848
    }
H
Haojun Liao 已提交
4849
    pWindowResInfo->prevSKey = w.skey;
4850
  }
H
Haojun Liao 已提交
4851 4852

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
4853 4854 4855
}

bool requireTimestamp(SQuery *pQuery) {
4856
  for (int32_t i = 0; i < pQuery->numOfOutput; i++) {
H
Haojun Liao 已提交
4857
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
H
Haojun Liao 已提交
4858
    if ((aAggs[functionId].status & TSDB_FUNCSTATE_NEED_TS) != 0) {
4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
      return true;
    }
  }
  return false;
}

bool needPrimaryTimestampCol(SQuery *pQuery, SDataBlockInfo *pDataBlockInfo) {
  /*
   * 1. if skey or ekey locates in this block, we need to load the timestamp column to decide the precise position
   * 2. if there are top/bottom, first_dst/last_dst functions, we need to load timestamp column in any cases;
   */
  STimeWindow *w = &pDataBlockInfo->window;
H
hjxilinx 已提交
4871
  STableQueryInfo* pTableQueryInfo = pQuery->current;
4872

H
hjxilinx 已提交
4873
  bool loadPrimaryTS = (pTableQueryInfo->lastKey >= w->skey && pTableQueryInfo->lastKey <= w->ekey) ||
4874 4875
                       (pQuery->window.ekey >= w->skey && pQuery->window.ekey <= w->ekey) || requireTimestamp(pQuery);

4876 4877 4878
  return loadPrimaryTS;
}

H
Haojun Liao 已提交
4879 4880 4881 4882 4883 4884
static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType) {
  void* qinfo = GET_QINFO_ADDR(pRuntimeEnv);
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
  int32_t numOfResult = pQuery->rec.rows; // there are already exists result rows
4885

4886
  int32_t start = 0;
4887
  int32_t step = -1;
4888

H
Haojun Liao 已提交
4889
  qDebug("QInfo:%p start to copy data from windowResInfo to output buf", qinfo);
4890
  if (orderType == TSDB_ORDER_ASC) {
H
Haojun Liao 已提交
4891
    start = pGroupResInfo->index;
4892 4893
    step = 1;
  } else {  // desc order copy all data
H
Haojun Liao 已提交
4894
    start = numOfRows - pGroupResInfo->index - 1;
4895 4896
    step = -1;
  }
4897

4898
  for (int32_t i = start; (i < numOfRows) && (i >= 0); i += step) {
H
Haojun Liao 已提交
4899 4900 4901
    SResultRow* pRow = taosArrayGetP(pGroupResInfo->pRows, i);
    if (pRow->numOfRows == 0) {
      pGroupResInfo->index += 1;
4902 4903
      continue;
    }
4904

H
Haojun Liao 已提交
4905
    int32_t numOfRowsToCopy = pRow->numOfRows;
4906

H
Haojun Liao 已提交
4907 4908 4909 4910
    //current output space is not enough to accommodate all data of this page, prepare more space
    if (numOfRowsToCopy > (pQuery->rec.capacity - numOfResult)) {
      int32_t newSize = pQuery->rec.capacity + (numOfRowsToCopy - numOfResult);
      expandBuffer(pRuntimeEnv, newSize, GET_QINFO_ADDR(pRuntimeEnv));
4911
    }
4912

H
Haojun Liao 已提交
4913
    pGroupResInfo->index += 1;
H
Haojun Liao 已提交
4914

H
Haojun Liao 已提交
4915
    tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pRow->pageId);
4916
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
4917
      int32_t size = pRuntimeEnv->pCtx[j].outputBytes;
4918

4919
      char *out = pQuery->sdata[j]->data + numOfResult * size;
H
Haojun Liao 已提交
4920 4921
      char *in  = getPosInResultPage(pRuntimeEnv, j, pRow, page);
      memcpy(out, in, size * numOfRowsToCopy);
4922
    }
4923

4924
    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
4925
    if (numOfResult == pQuery->rec.capacity) {  // output buffer is full
4926 4927
      break;
    }
4928
  }
4929

H
Haojun Liao 已提交
4930
  qDebug("QInfo:%p copy data to query buf completed", qinfo);
4931 4932 4933 4934
  return numOfResult;
}

/**
H
Haojun Liao 已提交
4935
 * copyToOutputBuf support copy data in ascending/descending order
4936 4937 4938 4939 4940 4941 4942
 * 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 已提交
4943 4944 4945
void copyToOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo *pResultInfo) {
  SQuery        *pQuery = pRuntimeEnv->pQuery;
  SGroupResInfo *pGroupResInfo = &pRuntimeEnv->groupResInfo;
4946

H
Haojun Liao 已提交
4947
  assert(pQuery->rec.rows == 0 && pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup);
H
Haojun Liao 已提交
4948
  if (!hasRemainData(pGroupResInfo)) {
H
Haojun Liao 已提交
4949 4950
    return;
  }
4951

H
Haojun Liao 已提交
4952
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013
  pQuery->rec.rows = doCopyToSData(pRuntimeEnv, pGroupResInfo, orderType);
}

static int32_t doCopyToSData_rv(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
  int32_t numOfResult = 0;//pQuery->rec.rows; // there are already exists result rows

  int32_t start = 0;
  int32_t step = -1;

  qDebug("QInfo:%p start to copy data from windowResInfo to output buf", pRuntimeEnv->qinfo);
  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;

    //current output space is not enough to accommodate all data of this page, prepare more space
//    if (numOfRowsToCopy > (pQuery->rec.capacity - numOfResult)) {
//      int32_t newSize = pQuery->rec.capacity + (numOfRowsToCopy - numOfResult);
//      expandBuffer(pRuntimeEnv, newSize, GET_QINFO_ADDR(pRuntimeEnv));
//    }

    pGroupResInfo->index += 1;

    tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pRow->pageId);
    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;
      char *in  = getPosInResultPage(pRuntimeEnv, j, pRow, page);
      memcpy(out, in, bytes * numOfRowsToCopy);
    }

    numOfResult += numOfRowsToCopy;
    if (numOfResult == pQuery->rec.capacity) {  // output buffer is full
      break;
    }
  }

  qDebug("QInfo:%p copy data to query buf completed", pRuntimeEnv->qinfo);
  pBlock->info.rows = numOfResult;
  return 0;
}

static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock) {
  assert(pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup);
H
Haojun Liao 已提交
5014
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
5015 5016 5017 5018 5019 5020 5021
  if (!hasRemainData(pGroupResInfo)) {
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
  doCopyToSData_rv(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
5022 5023 5024 5025 5026 5027

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

  STimeWindow* w = &pBlock->info.window;
  w->skey = *(int64_t*)pInfoData->pData;
  w->ekey = *(int64_t*)(pInfoData->pData + TSDB_KEYSIZE * (pBlock->info.rows - 1));
5028 5029
}

H
Haojun Liao 已提交
5030
static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv) {
5031
  SQuery *pQuery = pRuntimeEnv->pQuery;
5032

5033
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
5034 5035 5036
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
5037

H
Haojun Liao 已提交
5038 5039
  for (int32_t i = 0; i < pRuntimeEnv->resultRowInfo.size; ++i) {
    SResultRow *pResult = pRuntimeEnv->resultRowInfo.pResult[i];
5040

H
Haojun Liao 已提交
5041 5042 5043 5044
    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
      int32_t functionId = pRuntimeEnv->pCtx[j].functionId;
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
5045
      }
H
Haojun Liao 已提交
5046

5047 5048
      SResultRowCellInfo* pCell = getResultCell(pRuntimeEnv, pResult, j);
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
5049 5050 5051 5052
    }
  }
}

H
Haojun Liao 已提交
5053
static void stableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pDataBlockInfo, SDataStatis *pStatis,
5054
    SArray *pDataBlock, __block_search_fn_t searchFn) {
5055
  SQuery *         pQuery = pRuntimeEnv->pQuery;
5056
  STableQueryInfo* pTableQueryInfo = pQuery->current;
5057

H
Haojun Liao 已提交
5058
  SResultRowInfo * pResultRowInfo = &pTableQueryInfo->resInfo;
H
hjxilinx 已提交
5059
  pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : pDataBlockInfo->rows - 1;
5060

H
Haojun Liao 已提交
5061
  if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pQuery->groupbyColumn) {
5062
    rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, pDataBlock);
5063
  } else {
5064
    blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pResultRowInfo, searchFn, pDataBlock);
5065
  }
H
Haojun Liao 已提交
5066 5067

  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
5068
    updateResultRowIndex(pResultRowInfo, pTableQueryInfo, QUERY_IS_ASC_QUERY(pQuery), pQuery->timeWindowInterpo);
H
Haojun Liao 已提交
5069
  }
5070 5071
}

H
Haojun Liao 已提交
5072
bool hasNotReturnedResults(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo) {
5073 5074
  SQuery *pQuery = pRuntimeEnv->pQuery;
  SFillInfo *pFillInfo = pRuntimeEnv->pFillInfo;
5075

H
Haojun Liao 已提交
5076 5077 5078 5079
  if (!Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
      return false;
  }

H
Haojun Liao 已提交
5080
  if (pQuery->limit.limit > 0 && pQuery->rec.total >= pQuery->limit.limit) {
5081 5082
    return false;
  }
5083

5084
  if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
5085
    // There are results not returned to client yet, so filling applied to the remain result is required firstly.
5086
    if (taosFillHasMoreResults(pFillInfo)) {
H
Haojun Liao 已提交
5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098
      return true;
    }

    /*
     * While the code reaches here, there are no results remains now.
     * If query is not completed yet, the gaps between two results blocks need to be handled after next data block
     * is retrieved from TSDB.
     *
     * NOTE: If the result set is not the first block, the gap in front of the result set will be filled. If the result
     * set is the FIRST result block, the gap between the start time of query time window and the timestamp of the
     * first result row in the actual result set will fill nothing.
     */
H
Haojun Liao 已提交
5099 5100 5101 5102
    int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pQuery->window.ekey, (int32_t)pQuery->rec.capacity);
    return numOfTotal > 0;
  } else { // there are results waiting for returned to client.
    if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED) && hasRemainData(pGroupResInfo) &&
H
Haojun Liao 已提交
5103
        (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery))) {
H
Haojun Liao 已提交
5104 5105
      return true;
    }
5106
  }
5107 5108

  return false;
5109 5110
}

H
Haojun Liao 已提交
5111 5112 5113 5114
static int16_t getNumOfFinalResCol(SQuery* pQuery) {
  return pQuery->pExpr2 == NULL? pQuery->numOfOutput:pQuery->numOfExpr2;
}

5115
static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) {
H
Haojun Liao 已提交
5116 5117
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
5118

H
Haojun Liao 已提交
5119
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
5120

H
Haojun Liao 已提交
5121
  if (pQuery->pExpr2 == NULL) {
H
Haojun Liao 已提交
5122 5123 5124 5125
    for (int32_t col = 0; col < pQuery->numOfOutput; ++col) {
      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 已提交
5126 5127 5128
    }
  } else {
    for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) {
H
Haojun Liao 已提交
5129 5130 5131
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
5132
    }
5133
  }
5134

H
Haojun Liao 已提交
5135
  int32_t numOfTables = (int32_t) taosHashGetSize(pQInfo->arrTableIdInfo);
weixin_48148422's avatar
weixin_48148422 已提交
5136 5137
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
5138

5139
  int32_t total = 0;
5140
  STableIdInfo* item = taosHashIterate(pQInfo->arrTableIdInfo, NULL);
5141

5142
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
5143
    STableIdInfo* pDst = (STableIdInfo*)data;
5144 5145 5146 5147
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
5148
    data += sizeof(STableIdInfo);
5149 5150 5151
    total++;

    qDebug("QInfo:%p set subscribe info, tid:%d, uid:%"PRIu64", skey:%"PRId64, pQInfo, item->tid, item->uid, item->key);
5152
    item = taosHashIterate(pQInfo->arrTableIdInfo, item);
weixin_48148422's avatar
weixin_48148422 已提交
5153 5154
  }

5155 5156
  qDebug("QInfo:%p set %d subscribe info", pQInfo, total);

H
Haojun Liao 已提交
5157
  // Check if query is completed or not for stable query or normal table query respectively.
H
hjxilinx 已提交
5158
  if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
H
Haojun Liao 已提交
5159 5160
    if (pQInfo->query.stableQuery) {
      if (IS_STASBLE_QUERY_OVER(&pQInfo->runtimeEnv)) {
5161 5162 5163
        setQueryStatus(pQuery, QUERY_OVER);
      }
    } else {
H
Haojun Liao 已提交
5164
      if (!hasNotReturnedResults(&pQInfo->runtimeEnv, &pRuntimeEnv->groupResInfo)) {
5165 5166
        setQueryStatus(pQuery, QUERY_OVER);
      }
5167
    }
H
hjxilinx 已提交
5168
  }
5169 5170
}

H
Haojun Liao 已提交
5171
#if 0
H
Haojun Liao 已提交
5172
int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst) {
5173
  SQuery *pQuery = pRuntimeEnv->pQuery;
5174
  SFillInfo* pFillInfo = pRuntimeEnv->pFillInfo;
5175

5176
  while (1) {
H
Haojun Liao 已提交
5177
    int32_t ret = (int32_t)taosFillResultDataBlock(pFillInfo, (tFilePage**)pQuery->sdata, (int32_t)pQuery->rec.capacity);
5178

5179
    // todo apply limit output function
5180 5181
    /* reached the start position of according to offset value, return immediately */
    if (pQuery->limit.offset == 0) {
H
Haojun Liao 已提交
5182
      qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows", pRuntimeEnv->qinfo, pFillInfo->numOfRows, ret);
5183 5184
      return ret;
    }
5185

5186
    if (pQuery->limit.offset < ret) {
5187
      qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, remain:%" PRId64 ", new offset:%d",
H
Haojun Liao 已提交
5188
             pRuntimeEnv->qinfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, ret - pQuery->limit.offset, 0);
5189

S
TD-1057  
Shengliang Guan 已提交
5190
      ret -= (int32_t)pQuery->limit.offset;
H
Haojun Liao 已提交
5191
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { //???pExpr1 or pExpr2
H
Haojun Liao 已提交
5192 5193
        memmove(pDst[i]->data, pDst[i]->data + pQuery->pExpr1[i].bytes * pQuery->limit.offset,
                ret * pQuery->pExpr1[i].bytes);
5194
      }
5195

5196 5197 5198
      pQuery->limit.offset = 0;
      return ret;
    } else {
5199
      qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, "
H
Haojun Liao 已提交
5200
             "remain:%d, new offset:%" PRId64, pRuntimeEnv->qinfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, 0,
5201
          pQuery->limit.offset - ret);
5202

5203 5204 5205
      pQuery->limit.offset -= ret;
      ret = 0;
    }
5206

H
Haojun Liao 已提交
5207 5208 5209 5210
    // no data in current data after fill
    int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, (int32_t)pQuery->rec.capacity);
    if (numOfTotal == 0) {
      return 0;
5211 5212 5213
    }
  }
}
H
Haojun Liao 已提交
5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235
#endif

int32_t doFillGapsInResults_rv(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock *pOutput) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
  SFillInfo* pFillInfo = pRuntimeEnv->pFillInfo;

  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;
  }

  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, (int32_t)pQuery->rec.capacity);

  // no data in current data after fill
  int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, (int32_t)pQuery->rec.capacity);
  if (numOfTotal == 0) {
    return 0;
  }

  return pOutput->info.rows;
}
5236

H
Haojun Liao 已提交
5237
void queryCostStatis(SQInfo *pQInfo) {
5238
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
5239
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
5240

H
Haojun Liao 已提交
5241
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
5242
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
5243 5244
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
5245 5246 5247
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
5248
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
5249 5250 5251 5252 5253 5254 5255
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
5256

H
Haojun Liao 已提交
5257 5258 5259
  qDebug("QInfo:%p :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, "
         "load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64,
         pQInfo, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
H
Haojun Liao 已提交
5260
         pSummary->loadBlocks, pSummary->totalRows, pSummary->totalCheckedRows);
5261

5262
  qDebug("QInfo:%p :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo, pSummary->winInfoSize/1024.0,
H
Haojun Liao 已提交
5263
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
5264 5265
}

5266 5267
static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
hjxilinx 已提交
5268
  STableQueryInfo* pTableQueryInfo = pQuery->current;
5269

5270
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
5271

5272
  if (pQuery->limit.offset == pBlockInfo->rows) {  // current block will ignore completed
H
hjxilinx 已提交
5273
    pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step;
5274 5275 5276
    pQuery->limit.offset = 0;
    return;
  }
5277

5278
  if (QUERY_IS_ASC_QUERY(pQuery)) {
S
TD-1057  
Shengliang Guan 已提交
5279
    pQuery->pos = (int32_t)pQuery->limit.offset;
5280
  } else {
S
TD-1057  
Shengliang Guan 已提交
5281
    pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1;
5282
  }
5283

5284
  assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1);
5285

5286
  SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
5287
  SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
5288

5289
  // update the pQuery->limit.offset value, and pQuery->pos value
H
Haojun Liao 已提交
5290
  TSKEY *keys = (TSKEY *) pColInfoData->pData;
5291 5292

  // update the offset value
H
hjxilinx 已提交
5293
  pTableQueryInfo->lastKey = keys[pQuery->pos];
5294
  pQuery->limit.offset = 0;
5295

H
hjxilinx 已提交
5296
  int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
5297

5298
  qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QINFO_ADDR(pRuntimeEnv),
5299
         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
5300
}
H
Haojun Liao 已提交
5301

Y
yihaoDeng 已提交
5302 5303 5304 5305 5306 5307 5308
static void freeTableBlockDist(STableBlockDist *pTableBlockDist) {
  if (pTableBlockDist != NULL) {
    taosArrayDestroy(pTableBlockDist->dataBlockInfos); 
    free(pTableBlockDist->result);
    free(pTableBlockDist);
  }
}
H
Haojun Liao 已提交
5309

Y
yihaoDeng 已提交
5310
static int32_t getPercentileFromSortedArray(const SArray* pArray, double rate) {
Y
yihaoDeng 已提交
5311
  int32_t len = (int32_t)taosArrayGetSize(pArray);
Y
yihaoDeng 已提交
5312
  if (len <= 0) {
Y
yihaoDeng 已提交
5313 5314 5315 5316 5317 5318
    return 0;
  }
  assert(rate >= 0 && rate <= 1.0);
  int idx = (int32_t)((len - 1) * rate);
  return ((SDataBlockInfo *)(taosArrayGet(pArray, idx)))->rows;
}
Y
yihaoDeng 已提交
5319
static int compareBlockInfo(const void *pLeft, const void *pRight) {
Y
yihaoDeng 已提交
5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340
  int32_t left = ((SDataBlockInfo *)pLeft)->rows;
  int32_t right = ((SDataBlockInfo *)pRight)->rows; 
  if (left > right) return 1; 
  if (left < right) return -1; 
  return 0;
} 

static void generateBlockDistResult(STableBlockDist *pTableBlockDist) {
  if (pTableBlockDist == NULL) {
     return;
  }
  int64_t min = INT64_MAX, max = INT64_MIN, avg = 0;    
  SArray* blockInfos= pTableBlockDist->dataBlockInfos;  
  int64_t totalRows = 0, totalBlocks = taosArrayGetSize(blockInfos); 
  for (size_t i = 0; i < taosArrayGetSize(blockInfos); i++) {
    SDataBlockInfo *blockInfo = taosArrayGet(blockInfos, i); 
    int64_t rows = blockInfo->rows;
    min = MIN(min, rows);       
    max = MAX(max, rows);
    totalRows += rows;  
  }
Y
yihaoDeng 已提交
5341
  avg = totalBlocks > 0 ? (int64_t)(totalRows/totalBlocks) : 0;
Y
yihaoDeng 已提交
5342 5343 5344

  taosArraySort(blockInfos, compareBlockInfo);

Y
yihaoDeng 已提交
5345
  int sz = sprintf(pTableBlockDist->result, 
Y
yihaoDeng 已提交
5346
          "summery: \n\t 5th=[%d], 25th=[%d], 50th=[%d],75th=[%d], 95th=[%d], 99th=[%d] \n\t min=[%"PRId64"], max=[%"PRId64"], avg = [%"PRId64"] \n\t totalRows=[%"PRId64"], totalBlocks=[%"PRId64"] \n\t seekHeaderTimeCost=[%"PRId64"(us)] \n\t rowsInMem=[%"PRId64"]",  
Y
yihaoDeng 已提交
5347 5348 5349 5350 5351 5352
          getPercentileFromSortedArray(blockInfos, 0.05), getPercentileFromSortedArray(blockInfos, 0.25), getPercentileFromSortedArray(blockInfos, 0.50), 
          getPercentileFromSortedArray(blockInfos, 0.75), getPercentileFromSortedArray(blockInfos, 0.95), getPercentileFromSortedArray(blockInfos, 0.99),
          min, max, avg,
          totalRows, totalBlocks,
          pTableBlockDist->firstSeekTimeUs,
          pTableBlockDist->numOfRowsInMemTable);
Y
yihaoDeng 已提交
5353
  UNUSED(sz);
Y
yihaoDeng 已提交
5354
  return;
Y
yihaoDeng 已提交
5355
} 
5356 5357 5358 5359 5360
void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
  SQuery *pQuery = pRuntimeEnv->pQuery;

  if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0) {
    return;
5361
  }
5362

5363 5364 5365
  pQuery->pos = 0;
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

H
hjxilinx 已提交
5366
  STableQueryInfo* pTableQueryInfo = pQuery->current;
5367
  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
5368

H
Haojun Liao 已提交
5369
  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
H
Haojun Liao 已提交
5370
  while (tsdbNextDataBlock(pQueryHandle)) {
5371
    if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) {
H
Haojun Liao 已提交
5372
      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
5373
    }
5374

H
Haojun Liao 已提交
5375
    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
5376

5377 5378
    if (pQuery->limit.offset > blockInfo.rows) {
      pQuery->limit.offset -= blockInfo.rows;
H
hjxilinx 已提交
5379 5380
      pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.window.ekey : blockInfo.window.skey;
      pTableQueryInfo->lastKey += step;
5381

5382
      qDebug("QInfo:%p skip rows:%d, offset:%" PRId64, GET_QINFO_ADDR(pRuntimeEnv), blockInfo.rows,
5383 5384
             pQuery->limit.offset);
    } else {  // find the appropriated start position in current block
5385 5386 5387
      updateOffsetVal(pRuntimeEnv, &blockInfo);
      break;
    }
5388
  }
H
Haojun Liao 已提交
5389 5390 5391 5392

  if (terrno != TSDB_CODE_SUCCESS) {
    longjmp(pRuntimeEnv->env, terrno);
  }
5393
}
5394

H
Haojun Liao 已提交
5395 5396
static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
5397
  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412

  assert(pQuery->limit.offset == 0);
  STimeWindow tw = *win;
  getNextTimeWindow(pQuery, &tw);

  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {

    // 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 已提交
5413
        getNextQualifiedWindow(pQuery, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
H
Haojun Liao 已提交
5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424
    assert(startPos >= 0);

    // set the abort info
    pQuery->pos = startPos;

    // reset the query start timestamp
    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
    pQuery->window.skey = pTableQueryInfo->win.skey;
    TSKEY key = pTableQueryInfo->win.skey;

    pWindowResInfo->prevSKey = tw.skey;
H
Haojun Liao 已提交
5425
    int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
H
Haojun Liao 已提交
5426 5427

    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
H
Haojun Liao 已提交
5428
    pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
H
Haojun Liao 已提交
5429 5430 5431 5432 5433 5434 5435

    qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
           GET_QINFO_ADDR(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
           pQuery->current->lastKey);

    return key;
  } else {  // do nothing
5436
    pQuery->window.skey      = tw.skey;
H
Haojun Liao 已提交
5437
    pWindowResInfo->prevSKey = tw.skey;
5438
    pTableQueryInfo->lastKey = tw.skey;
H
Haojun Liao 已提交
5439 5440 5441 5442 5443 5444 5445

    return tw.skey;
  }

  return true;
}

H
Haojun Liao 已提交
5446
static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
5447
  SQuery *pQuery = pRuntimeEnv->pQuery;
5448 5449 5450 5451
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    assert(*start <= pQuery->current->lastKey);
  } else {
    assert(*start >= pQuery->current->lastKey);
H
Haojun Liao 已提交
5452 5453
  }

5454
  // if queried with value filter, do NOT forward query start position
H
Haojun Liao 已提交
5455
  if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
5456
    return true;
5457
  }
5458

5459
  /*
5460 5461
   * 1. for interval without interpolation query we forward pQuery->interval.interval at a time for
   *    pQuery->limit.offset times. Since hole exists, pQuery->interval.interval*pQuery->limit.offset value is
5462 5463
   *    not valid. otherwise, we only forward pQuery->limit.offset number of points
   */
H
Haojun Liao 已提交
5464
  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
5465

H
Haojun Liao 已提交
5466
  STimeWindow w = TSWINDOW_INITIALIZER;
5467
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
5468

H
Haojun Liao 已提交
5469
  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
hjxilinx 已提交
5470
  STableQueryInfo *pTableQueryInfo = pQuery->current;
5471

H
Haojun Liao 已提交
5472
  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
H
Haojun Liao 已提交
5473
  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
H
Haojun Liao 已提交
5474
    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
5475

H
Haojun Liao 已提交
5476 5477
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
5478
        getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &w);
H
Haojun Liao 已提交
5479 5480
        pWindowResInfo->prevSKey = w.skey;
      }
5481
    } else {
H
Haojun Liao 已提交
5482
      getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &w);
5483 5484
      pWindowResInfo->prevSKey = w.skey;
    }
5485

5486 5487
    // the first time window
    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQuery);
5488

5489
    while (pQuery->limit.offset > 0) {
H
Haojun Liao 已提交
5490 5491
      STimeWindow tw = win;

5492
      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
5493 5494
        pQuery->limit.offset -= 1;
        pWindowResInfo->prevSKey = win.skey;
5495 5496 5497 5498 5499 5500

        // 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 已提交
5501
      }
5502

5503
      if (pQuery->limit.offset == 0) {
H
Haojun Liao 已提交
5504 5505
        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
        return true;
5506 5507
      }

5508 5509 5510
      // current window does not ended in current data block, try next data block
      getNextTimeWindow(pQuery, &tw);

H
Haojun Liao 已提交
5511 5512 5513 5514 5515 5516 5517
      /*
       * 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.
       */
5518 5519 5520
      if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) {

        SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
5521 5522
        SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);

5523
        if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
5524 5525 5526 5527
          pQuery->limit.offset -= 1;
        }

        if (pQuery->limit.offset == 0) {
H
Haojun Liao 已提交
5528 5529
          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
          return true;
H
Haojun Liao 已提交
5530 5531 5532
        } else {
          tw = win;
          int32_t startPos =
H
Haojun Liao 已提交
5533
              getNextQualifiedWindow(pQuery, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
H
Haojun Liao 已提交
5534
          assert(startPos >= 0);
5535

H
Haojun Liao 已提交
5536 5537 5538 5539 5540 5541
          // set the abort info
          pQuery->pos = startPos;
          pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos];
          pWindowResInfo->prevSKey = tw.skey;
          win = tw;
        }
5542
      } else {
H
Haojun Liao 已提交
5543
        break;  // offset is not 0, and next time window begins or ends in the next block.
5544 5545 5546
      }
    }
  }
5547

H
Haojun Liao 已提交
5548 5549 5550 5551 5552
  // check for error
  if (terrno != TSDB_CODE_SUCCESS) {
    longjmp(pRuntimeEnv->env, terrno);
  }

5553 5554 5555
  return true;
}

H
Haojun Liao 已提交
5556 5557
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

B
Bomin Zhang 已提交
5558
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
5559
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
5560 5561
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

B
Bomin Zhang 已提交
5562
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
5563
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
5564 5565
  }

H
Haojun Liao 已提交
5566 5567 5568
//  if (isSTableQuery && (!QUERY_IS_INTERVAL_QUERY(pQuery)) && (!isFixedOutputQuery(pQuery))) {
//    return TSDB_CODE_SUCCESS;
//  }
5569

H
Haojun Liao 已提交
5570
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
5571

B
Bomin Zhang 已提交
5572
  if (!isSTableQuery
H
Haojun Liao 已提交
5573
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
5574
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
5575
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
5576
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
5577
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
5578
  ) {
H
Haojun Liao 已提交
5579
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
5580 5581
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
5582
  }
B
Bomin Zhang 已提交
5583

B
Bomin Zhang 已提交
5584
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
5585
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
5586
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
5587

H
Haojun Liao 已提交
5588 5589
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
5590
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
5591
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
5592
    } else {
H
Haojun Liao 已提交
5593
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
5594
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
5595
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
5596

H
Haojun Liao 已提交
5597 5598 5599
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
5600

H
Haojun Liao 已提交
5601 5602 5603
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
5604 5605
      }
    }
5606
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
5607
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
5608
  } else {
H
Haojun Liao 已提交
5609
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
5610
  }
5611

B
Bomin Zhang 已提交
5612
  return terrno;
B
Bomin Zhang 已提交
5613 5614
}

H
Haojun Liao 已提交
5615
static SFillColInfo* createFillColInfo(SQuery* pQuery) {
H
Haojun Liao 已提交
5616
  int32_t numOfCols = getNumOfFinalResCol(pQuery);
5617
  int32_t offset = 0;
5618

5619
  SFillColInfo* pFillCol = calloc(numOfCols, sizeof(SFillColInfo));
H
Haojun Liao 已提交
5620 5621 5622 5623
  if (pFillCol == NULL) {
    return NULL;
  }

H
Haojun Liao 已提交
5624
  // TODO refactor
5625
  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
5626
    SExprInfo* pExprInfo = (pQuery->pExpr2 == NULL)? &pQuery->pExpr1[i]:&pQuery->pExpr2[i];
5627

5628
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
5629
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
5630
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
5631
    pFillCol[i].tagIndex   = -2;
5632 5633
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
5634
    pFillCol[i].fillVal.i = pQuery->fillVal[i];
5635

5636 5637
    offset += pExprInfo->bytes;
  }
5638

5639 5640 5641
  return pFillCol;
}

5642
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *tsdb, int32_t vgId, bool isSTableQuery) {
5643 5644 5645
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
H
Haojun Liao 已提交
5646

H
Haojun Liao 已提交
5647 5648
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
5649
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
5650 5651
  pRuntimeEnv->prevResult = prevResult;

5652
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
5653

H
Haojun Liao 已提交
5654
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
5655 5656 5657
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
5658

H
Haojun Liao 已提交
5659
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
5660
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
5661
  pRuntimeEnv->groupResInfo.totalGroup = isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0;
5662 5663

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
5664
  pRuntimeEnv->pTsBuf = pTsBuf;
5665
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
5666

H
Haojun Liao 已提交
5667
  pQuery->stableQuery = isSTableQuery;
H
Haojun Liao 已提交
5668

H
Haojun Liao 已提交
5669
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);
5670

H
Haojun Liao 已提交
5671
  if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
5672
    pRuntimeEnv->pi = createBiDirectionTableScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
5673
  } else {
H
Haojun Liao 已提交
5674
    pRuntimeEnv->pi = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
5675 5676
  }

H
Haojun Liao 已提交
5677
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
5678 5679
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
5680 5681
  }

5682 5683 5684
  int32_t ps = DEFAULT_PAGE_SIZE;
  int32_t rowsize = 0;
  getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize);
H
Haojun Liao 已提交
5685
  int32_t TENMB = 1024*1024*10;
5686

H
Haojun Liao 已提交
5687
  if (isSTableQuery && !onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
5688
    code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TENMB, pQInfo);
5689 5690 5691 5692
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }

H
Haojun Liao 已提交
5693
    if (!QUERY_IS_INTERVAL_QUERY(pQuery)) {
5694
      int16_t type = TSDB_DATA_TYPE_NULL;
H
Haojun Liao 已提交
5695
      if (pQuery->groupbyColumn) {  // group by columns not tags;
5696 5697 5698 5699 5700
        type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr);
      } else {
        type = TSDB_DATA_TYPE_INT;  // group id
      }

H
Haojun Liao 已提交
5701
      code = initResultRowInfo(&pRuntimeEnv->resultRowInfo, 8, type);
B
Bomin Zhang 已提交
5702 5703 5704
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
5705
    }
H
Haojun Liao 已提交
5706
  } else if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || (!isSTableQuery)) {
5707 5708
    int32_t numOfResultRows = getInitialPageNum(pQInfo);
    getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize);
H
Haojun Liao 已提交
5709
    code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TENMB, pQInfo);
5710 5711 5712 5713 5714
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }

    int16_t type = TSDB_DATA_TYPE_NULL;
H
Haojun Liao 已提交
5715
    if (pQuery->groupbyColumn) {
5716 5717 5718 5719 5720
      type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr);
    } else {
      type = TSDB_DATA_TYPE_TIMESTAMP;
    }

H
Haojun Liao 已提交
5721
    code = initResultRowInfo(&pRuntimeEnv->resultRowInfo, numOfResultRows, type);
B
Bomin Zhang 已提交
5722 5723 5724
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
5725 5726
  }

H
Haojun Liao 已提交
5727
  // create runtime environment
H
Haojun Liao 已提交
5728
  int32_t numOfTables = pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
5729
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
5730
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables, pQuery->order.order, pQuery->vgId);
H
Haojun Liao 已提交
5731 5732 5733 5734
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

5735
  if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
5736
    SFillColInfo* pColInfo = createFillColInfo(pQuery);
H
Haojun Liao 已提交
5737 5738 5739 5740 5741 5742
    STimeWindow w = TSWINDOW_INITIALIZER;

    TSKEY sk = MIN(pQuery->window.skey, pQuery->window.ekey);
    TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey);
    getAlignQueryTimeWindow(pQuery, pQuery->window.skey, sk, ek, &w);

H
Haojun Liao 已提交
5743
    int32_t numOfCols = getNumOfFinalResCol(pQuery);
5744
    pRuntimeEnv->pFillInfo = taosCreateFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pQuery->rec.capacity, numOfCols,
5745
                                              pQuery->interval.sliding, pQuery->interval.slidingUnit, (int8_t)pQuery->precision,
H
Haojun Liao 已提交
5746
                                              pQuery->fillType, pColInfo, pQInfo);
5747
  }
5748

H
Haojun Liao 已提交
5749
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
5750
  return TSDB_CODE_SUCCESS;
5751 5752
}

5753
static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) {
5754
  SQuery *pQuery = pRuntimeEnv->pQuery;
5755

5756
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
5757
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[i]);
5758 5759 5760 5761 5762 5763
    if (pResInfo != NULL) {
      pResInfo->complete = false;
    }
  }
}

H
Haojun Liao 已提交
5764 5765
static FORCE_INLINE void setEnvForEachBlock(SQueryRuntimeEnv* pRuntimeEnv, STableQueryInfo* pTableQueryInfo, SDataBlockInfo* pBlockInfo) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
5766 5767
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

H
Haojun Liao 已提交
5768
  if (pQuery->hasTagResults || pRuntimeEnv->pTsBuf != NULL) {
5769 5770 5771 5772
    setTagVal(pRuntimeEnv, pTableQueryInfo->pTable);
  }

  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
5773
    setTimestampListJoinInfo(pRuntimeEnv, pTableQueryInfo);
5774 5775
  }

H
Haojun Liao 已提交
5776
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
5777
    setIntervalQueryRange(pRuntimeEnv, pBlockInfo->window.skey);
H
Haojun Liao 已提交
5778
  } else {  // non-interval query
H
Haojun Liao 已提交
5779
    setExecutionContext(pRuntimeEnv, pTableQueryInfo->groupIndex, pBlockInfo->window.ekey + step);
H
Haojun Liao 已提交
5780 5781 5782
  }
}

H
Haojun Liao 已提交
5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796
static void doTableQueryInfoTimeWindowCheck(SQuery* pQuery, STableQueryInfo* pTableQueryInfo) {
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey >= pTableQueryInfo->win.skey) &&
        (pTableQueryInfo->win.skey >= pQuery->window.skey && pTableQueryInfo->win.ekey <= pQuery->window.ekey));
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey <= pTableQueryInfo->win.skey) &&
        (pTableQueryInfo->win.skey <= pQuery->window.skey && pTableQueryInfo->win.ekey >= pQuery->window.ekey));
  }
}

H
Haojun Liao 已提交
5797
static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) {
5798
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
5799
  SQuery*           pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
5800
  SQueryCostInfo*   summary = &pQInfo->summary;
H
Haojun Liao 已提交
5801

H
hjxilinx 已提交
5802
  int64_t st = taosGetTimestampMs();
5803

5804
  TsdbQueryHandleT pQueryHandle = IS_MASTER_SCAN(pRuntimeEnv)? pRuntimeEnv->pQueryHandle : pRuntimeEnv->pSecQueryHandle;
H
Haojun Liao 已提交
5805
  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
H
Haojun Liao 已提交
5806

H
Haojun Liao 已提交
5807 5808
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

H
Haojun Liao 已提交
5809
  while (tsdbNextDataBlock(pQueryHandle)) {
5810
    summary->totalBlocks += 1;
H
Haojun Liao 已提交
5811

5812
    if (isQueryKilled(pQInfo)) {
H
Haojun Liao 已提交
5813
      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
5814
    }
5815

H
Haojun Liao 已提交
5816
    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
H
Haojun Liao 已提交
5817
    STableQueryInfo **pTableQueryInfo = (STableQueryInfo**) taosHashGet(pRuntimeEnv->tableqinfoGroupInfo.map, &blockInfo.tid, sizeof(blockInfo.tid));
H
Haojun Liao 已提交
5818 5819 5820
    if(pTableQueryInfo == NULL) {
      break;
    }
5821

H
Haojun Liao 已提交
5822
    pQuery->current = *pTableQueryInfo;
H
Haojun Liao 已提交
5823
    doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo);
5824

H
Haojun Liao 已提交
5825
    if (!pQuery->groupbyColumn) {
H
Haojun Liao 已提交
5826
      setEnvForEachBlock(pRuntimeEnv, *pTableQueryInfo, &blockInfo);
5827
    }
5828

H
Haojun Liao 已提交
5829
    if (pQuery->stabledev) {
5830 5831 5832 5833 5834 5835 5836 5837
      for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
        if (pQuery->pExpr1[i].base.functionId == TSDB_FUNC_STDDEV_DST) {
          setParamValue(pRuntimeEnv);
          break;
        }
      }
    }

5838
    uint32_t     status = 0;
H
Haojun Liao 已提交
5839 5840
    SDataStatis *pStatis = NULL;
    SArray      *pDataBlock = NULL;
5841

H
Haojun Liao 已提交
5842
    int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pQuery->current->resInfo, pQueryHandle, &blockInfo, &pStatis, &pDataBlock, &status);
5843 5844 5845 5846 5847
    if (ret != TSDB_CODE_SUCCESS) {
      break;
    }

    if (status == BLK_DATA_DISCARD) {
H
Haojun Liao 已提交
5848
      pQuery->current->lastKey = QUERY_IS_ASC_QUERY(pQuery)? blockInfo.window.ekey + step : blockInfo.window.skey + step;
H
Haojun Liao 已提交
5849 5850 5851
      continue;
    }

5852 5853
    summary->totalRows += blockInfo.rows;
    stableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, pDataBlock, binarySearchForKey);
H
Haojun Liao 已提交
5854

H
Haojun Liao 已提交
5855 5856 5857 5858
    qDebug("QInfo:%p check data block completed, uid:%"PRId64", tid:%d, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, "
           "lastKey:%" PRId64,
           pQInfo, blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows,
           pQuery->current->lastKey);
5859
  }
5860

H
Haojun Liao 已提交
5861 5862 5863 5864
  if (terrno != TSDB_CODE_SUCCESS) {
    longjmp(pRuntimeEnv->env, terrno);
  }

H
Haojun Liao 已提交
5865 5866
  updateWindowResNumOfRes(pRuntimeEnv);

H
hjxilinx 已提交
5867 5868
  int64_t et = taosGetTimestampMs();
  return et - st;
5869 5870
}

5871 5872
static bool multiTableMultioutputHelper(SQInfo *pQInfo, int32_t index) {
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
5873
  SQuery *          pQuery = pRuntimeEnv->pQuery;
5874

5875
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
5876
  SArray *group = GET_TABLEGROUP(pRuntimeEnv, 0);
5877
  STableQueryInfo* pCheckInfo = taosArrayGetP(group, index);
5878

H
Haojun Liao 已提交
5879
  if (pQuery->hasTagResults || pRuntimeEnv->pTsBuf != NULL) {
5880
    setTagVal(pRuntimeEnv, pCheckInfo->pTable);
H
Haojun Liao 已提交
5881
  }
5882

H
Haojun Liao 已提交
5883
  STableId* id = TSDB_TABLEID(pCheckInfo->pTable);
5884
  qDebug("QInfo:%p query on (%d): uid:%" PRIu64 ", tid:%d, qrange:%" PRId64 "-%" PRId64, pQInfo, index,
H
Haojun Liao 已提交
5885
         id->uid, id->tid, pCheckInfo->lastKey, pCheckInfo->win.ekey);
5886

5887
  STsdbQueryCond cond = {
5888
      .twindow   = {pCheckInfo->lastKey, pCheckInfo->win.ekey},
H
hjxilinx 已提交
5889 5890
      .order     = pQuery->order.order,
      .colList   = pQuery->colList,
5891
      .numOfCols = pQuery->numOfCols,
5892
      .loadExternalRows = false,
5893
  };
5894

H
hjxilinx 已提交
5895
  // todo refactor
5896
  SArray *g1 = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
5897 5898 5899 5900
  SArray *tx = taosArrayInit(1, sizeof(STableKeyInfo));

  STableKeyInfo info = {.pTable = pCheckInfo->pTable, .lastKey = pCheckInfo->lastKey};
  taosArrayPush(tx, &info);
5901

5902
  taosArrayPush(g1, &tx);
5903
  STableGroupInfo gp = {.numOfTables = 1, .pGroupList = g1};
5904

5905
  // include only current table
5906 5907 5908 5909
  if (pRuntimeEnv->pQueryHandle != NULL) {
    tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
    pRuntimeEnv->pQueryHandle = NULL;
  }
5910

H
Haojun Liao 已提交
5911
  pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &gp, pQInfo, &pQuery->memRef);
5912 5913
  taosArrayDestroy(tx);
  taosArrayDestroy(g1);
B
Bomin Zhang 已提交
5914 5915 5916
  if (pRuntimeEnv->pQueryHandle == NULL) {
    longjmp(pRuntimeEnv->env, terrno);
  }
5917

H
Haojun Liao 已提交
5918
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
5919 5920
      tVariant* pTag = &pRuntimeEnv->pCtx[0].tag;

5921
    if (pRuntimeEnv->cur.vgroupIndex == -1) {
H
Haojun Liao 已提交
5922
      STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, pTag);
H
Haojun Liao 已提交
5923
      // failed to find data with the specified tag value and vnodeId
5924
      if (!tsBufIsValidElem(&elem)) {
H
Haojun Liao 已提交
5925 5926 5927
        if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
          qError("QInfo:%p failed to find tag:%s in ts_comp", pQInfo, pTag->pz);
        } else {
5928
          qError("QInfo:%p failed to find tag:%"PRId64" in ts_comp", pQInfo, pTag->i64);
H
Haojun Liao 已提交
5929 5930
        }

5931
        return false;
H
Haojun Liao 已提交
5932
      } else {
H
Haojun Liao 已提交
5933
        STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
5934 5935 5936 5937 5938

        if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
          qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz,
                 cur.blockIndex, cur.tsIndex);
        } else {
5939
          qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64,
H
Haojun Liao 已提交
5940 5941
                 cur.blockIndex, cur.tsIndex);
        }
5942 5943
      }
    } else {
H
Haojun Liao 已提交
5944
      STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
5945
      if (tVariantCompare(elem.tag, &pRuntimeEnv->pCtx[0].tag) != 0) {
H
Haojun Liao 已提交
5946

H
Haojun Liao 已提交
5947
        STSElem elem1 = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, pTag);
H
Haojun Liao 已提交
5948
        // failed to find data with the specified tag value and vnodeId
5949
        if (!tsBufIsValidElem(&elem1)) {
H
Haojun Liao 已提交
5950 5951 5952
          if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
            qError("QInfo:%p failed to find tag:%s in ts_comp", pQInfo, pTag->pz);
          } else {
5953
            qError("QInfo:%p failed to find tag:%"PRId64" in ts_comp", pQInfo, pTag->i64);
H
Haojun Liao 已提交
5954
          }
H
Haojun Liao 已提交
5955

H
Haojun Liao 已提交
5956
          return false;
H
Haojun Liao 已提交
5957
        } else {
H
Haojun Liao 已提交
5958
          STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
5959 5960 5961
          if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
            qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, cur.blockIndex, cur.tsIndex);
          } else {
5962
            qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, cur.blockIndex, cur.tsIndex);
H
Haojun Liao 已提交
5963
          }
H
Haojun Liao 已提交
5964
        }
H
Haojun Liao 已提交
5965

H
Haojun Liao 已提交
5966
      } else {
H
Haojun Liao 已提交
5967 5968
        tsBufSetCursor(pRuntimeEnv->pTsBuf, &pRuntimeEnv->cur);
        STSCursor cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
5969 5970 5971
        if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
          qDebug("QInfo:%p continue scan ts_comp file, tag:%s blockIndex:%d, tsIndex:%d", pQInfo, pTag->pz, cur.blockIndex, cur.tsIndex);
        } else {
5972
          qDebug("QInfo:%p continue scan ts_comp file, tag:%"PRId64" blockIndex:%d, tsIndex:%d", pQInfo, pTag->i64, cur.blockIndex, cur.tsIndex);
H
Haojun Liao 已提交
5973
        }
H
Haojun Liao 已提交
5974
      }
5975 5976
    }
  }
5977

H
Haojun Liao 已提交
5978
  initCtxOutputBuf(pRuntimeEnv, pRuntimeEnv->pCtx);
5979 5980 5981
  return true;
}

H
Haojun Liao 已提交
5982
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
5983 5984 5985 5986
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
5987
      .loadExternalRows = false,
5988 5989
  };

H
Haojun Liao 已提交
5990
  TIME_WINDOW_COPY(cond.twindow, *win);
5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017
  return cond;
}

static STableIdInfo createTableIdInfo(SQuery* pQuery) {
  assert(pQuery != NULL && pQuery->current != NULL);

  STableIdInfo tidInfo;
  STableId* id = TSDB_TABLEID(pQuery->current->pTable);

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
  tidInfo.key = pQuery->current->lastKey;

  return tidInfo;
}

static void updateTableIdInfo(SQuery* pQuery, SHashObj* pTableIdInfo) {
  STableIdInfo tidInfo = createTableIdInfo(pQuery);
  STableIdInfo* idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
  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));
  }
}

6018 6019 6020 6021 6022 6023 6024
/**
 * super table query handler
 * 1. super table projection query, group-by on normal columns query, ts-comp query
 * 2. point interpolation query, last row query
 *
 * @param pQInfo
 */
H
Haojun Liao 已提交
6025
static UNUSED_FUNC void sequentialTableProcess(SQInfo *pQInfo) {
6026
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
6027
  SQuery *          pQuery = pRuntimeEnv->pQuery;
6028
  setQueryStatus(pQuery, QUERY_COMPLETED);
6029

H
Haojun Liao 已提交
6030
  size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
6031

6032
  if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
6033
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
6034
    assert(pQuery->limit.offset == 0 && pQuery->limit.limit != 0);
6035

H
Haojun Liao 已提交
6036
    while (pRuntimeEnv->groupIndex < numOfGroups) {
H
Haojun Liao 已提交
6037
      SArray *group = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, pRuntimeEnv->groupIndex);
H
Haojun Liao 已提交
6038

6039
      qDebug("QInfo:%p point interpolation query on group:%d, total group:%" PRIzu ", current group:%p", pQInfo,
H
Haojun Liao 已提交
6040
             pRuntimeEnv->groupIndex, numOfGroups, group);
H
Haojun Liao 已提交
6041
      STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
6042

H
Haojun Liao 已提交
6043
      SArray *g1 = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
6044
      SArray *tx = taosArrayDup(group);
H
Haojun Liao 已提交
6045
      taosArrayPush(g1, &tx);
6046

H
Haojun Liao 已提交
6047 6048 6049 6050 6051 6052 6053
      STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1};

      // include only current table
      if (pRuntimeEnv->pQueryHandle != NULL) {
        tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
        pRuntimeEnv->pQueryHandle = NULL;
      }
6054

H
Haojun Liao 已提交
6055
      pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(pQuery->tsdb, &cond, &gp, pQInfo, &pQuery->memRef);
B
Bomin Zhang 已提交
6056 6057 6058 6059 6060 6061

      taosArrayDestroy(tx);
      taosArrayDestroy(g1);
      if (pRuntimeEnv->pQueryHandle == NULL) {
        longjmp(pRuntimeEnv->env, terrno);
      }
H
Haojun Liao 已提交
6062

H
Haojun Liao 已提交
6063
      initCtxOutputBuf(pRuntimeEnv, pRuntimeEnv->pCtx);
6064

6065
      SArray *s = tsdbGetQueriedTableList(pRuntimeEnv->pQueryHandle);
6066
      assert(taosArrayGetSize(s) >= 1);
6067

6068
      setTagVal(pRuntimeEnv, taosArrayGetP(s, 0));
dengyihao's avatar
dengyihao 已提交
6069
      taosArrayDestroy(s);
H
Haojun Liao 已提交
6070

H
Haojun Liao 已提交
6071
      // here we simply set the first table as current table
H
Haojun Liao 已提交
6072
      SArray *first = GET_TABLEGROUP(pRuntimeEnv, pRuntimeEnv->groupIndex);
6073 6074
      pQuery->current = taosArrayGetP(first, 0);

6075
      scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
6076

H
Haojun Liao 已提交
6077 6078 6079 6080 6081
      int64_t numOfRes = getNumOfResult(pRuntimeEnv);
      if (numOfRes > 0) {
        pQuery->rec.rows += numOfRes;
        forwardCtxOutputBuf(pRuntimeEnv, numOfRes);
      }
6082

H
Haojun Liao 已提交
6083
      skipResults(pRuntimeEnv);
H
Haojun Liao 已提交
6084
      pRuntimeEnv->groupIndex += 1;
H
Haojun Liao 已提交
6085 6086 6087

      // enable execution for next table, when handling the projection query
      enableExecutionForNextTable(pRuntimeEnv);
6088 6089 6090 6091 6092 6093

      if (pQuery->rec.rows >= pQuery->rec.capacity) {
        setQueryStatus(pQuery, QUERY_RESBUF_FULL);
        break;
      }
    }
H
Haojun Liao 已提交
6094
  } else if (pQuery->groupbyColumn) {  // group-by on normal columns query
H
Haojun Liao 已提交
6095
    while (pRuntimeEnv->groupIndex < numOfGroups) {
H
Haojun Liao 已提交
6096
      SArray *group = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, pRuntimeEnv->groupIndex);
6097

H
Haojun Liao 已提交
6098
      qDebug("QInfo:%p group by normal columns group:%d, total group:%" PRIzu "", pQInfo, pRuntimeEnv->groupIndex,
6099
             numOfGroups);
6100

H
Haojun Liao 已提交
6101
      STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
6102

6103
      SArray *g1 = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
6104
      SArray *tx = taosArrayDup(group);
6105 6106 6107 6108 6109 6110 6111 6112 6113 6114
      taosArrayPush(g1, &tx);

      STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1};

      // include only current table
      if (pRuntimeEnv->pQueryHandle != NULL) {
        tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
        pRuntimeEnv->pQueryHandle = NULL;
      }

H
Haojun Liao 已提交
6115
      // no need to update the lastkey for each table
H
Haojun Liao 已提交
6116
      pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &gp, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
6117

B
Bomin Zhang 已提交
6118 6119
      taosArrayDestroy(g1);
      taosArrayDestroy(tx);
B
Bomin Zhang 已提交
6120 6121 6122
      if (pRuntimeEnv->pQueryHandle == NULL) {
        longjmp(pRuntimeEnv->env, terrno);
      }
6123

6124
      SArray *s = tsdbGetQueriedTableList(pRuntimeEnv->pQueryHandle);
6125 6126
      assert(taosArrayGetSize(s) >= 1);

6127
      setTagVal(pRuntimeEnv, taosArrayGetP(s, 0));
6128 6129 6130

      // here we simply set the first table as current table
      scanMultiTableDataBlocks(pQInfo);
H
Haojun Liao 已提交
6131
      pRuntimeEnv->groupIndex += 1;
6132

6133
      taosArrayDestroy(s);
6134

6135
      // no results generated for current group, continue to try the next group
H
Haojun Liao 已提交
6136
      SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
6137 6138 6139 6140 6141
      if (pWindowResInfo->size <= 0) {
        continue;
      }

      for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
6142
        pWindowResInfo->pResult[i]->closed = true;  // enable return all results for group by normal columns
6143

H
Haojun Liao 已提交
6144
        SResultRow *pResult = pWindowResInfo->pResult[i];
6145
        for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
6146
          SResultRowCellInfo *pCell = getResultCell(pRuntimeEnv, pResult, j);
6147
          pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
6148 6149 6150
        }
      }

6151
      qDebug("QInfo:%p generated groupby columns results %d rows for group %d completed", pQInfo, pWindowResInfo->size,
H
Haojun Liao 已提交
6152
             pRuntimeEnv->groupIndex);
6153 6154

      pQuery->rec.rows = 0;
H
Haojun Liao 已提交
6155 6156 6157
      if (pWindowResInfo->size > pQuery->rec.capacity) {
        expandBuffer(pRuntimeEnv, pWindowResInfo->size, pQInfo);
      }
6158

H
Haojun Liao 已提交
6159 6160
      initGroupResInfo(&pRuntimeEnv->groupResInfo, &pRuntimeEnv->resultRowInfo, 0);
      copyToOutputBuf(pRuntimeEnv, pWindowResInfo);
6161
      assert(pQuery->rec.rows == pWindowResInfo->size);
H
Haojun Liao 已提交
6162 6163

      resetResultRowInfo(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
H
Haojun Liao 已提交
6164
      cleanupGroupResInfo(&pRuntimeEnv->groupResInfo);
6165
      break;
6166
    }
H
Haojun Liao 已提交
6167
  } else if (pQuery->queryWindowIdentical && pRuntimeEnv->pTsBuf == NULL && !isTsCompQuery(pQuery)) {
6168 6169 6170 6171
    //super table projection query with identical query time range for all tables.
    SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
    resetDefaultResInfoOutputBuf(pRuntimeEnv);

H
Haojun Liao 已提交
6172
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, 0);
H
Haojun Liao 已提交
6173 6174
    assert(taosArrayGetSize(group) == pRuntimeEnv->tableqinfoGroupInfo.numOfTables &&
           1 == taosArrayGetSize(pRuntimeEnv->tableqinfoGroupInfo.pGroupList));
6175 6176 6177

    void *pQueryHandle = pRuntimeEnv->pQueryHandle;
    if (pQueryHandle == NULL) {
H
Haojun Liao 已提交
6178
      STsdbQueryCond con = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
6179
      pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQuery->tsdb, &con, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
6180 6181 6182 6183 6184 6185 6186 6187 6188 6189
      pQueryHandle = pRuntimeEnv->pQueryHandle;
    }

    // skip blocks without load the actual data block from file if no filter condition present
    //    skipBlocks(&pQInfo->runtimeEnv);
    //    if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0) {
    //      setQueryStatus(pQuery, QUERY_COMPLETED);
    //      return;
    //    }

H
Haojun Liao 已提交
6190 6191 6192 6193 6194 6195
    if (pQuery->prjInfo.vgroupLimit != -1) {
      assert(pQuery->limit.limit == -1 && pQuery->limit.offset == 0);
    } else if (pQuery->limit.limit != -1) {
      assert(pQuery->prjInfo.vgroupLimit == -1);
    }

6196
    bool hasMoreBlock = true;
H
Haojun Liao 已提交
6197
    int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
H
Haojun Liao 已提交
6198
    SQueryCostInfo *summary = &pQInfo->summary;
6199 6200 6201
    while ((hasMoreBlock = tsdbNextDataBlock(pQueryHandle)) == true) {
      summary->totalBlocks += 1;

6202
      if (isQueryKilled(pQInfo)) {
6203 6204 6205 6206 6207
        longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
      }

      tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
      STableQueryInfo **pTableQueryInfo =
H
Haojun Liao 已提交
6208
          (STableQueryInfo **) taosHashGet(pRuntimeEnv->tableqinfoGroupInfo.map, &blockInfo.tid, sizeof(blockInfo.tid));
6209 6210 6211 6212 6213
      if (pTableQueryInfo == NULL) {
        break;
      }

      pQuery->current = *pTableQueryInfo;
H
Haojun Liao 已提交
6214
      doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo);
6215

H
Haojun Liao 已提交
6216
      if (pQuery->hasTagResults) {
6217
        setTagVal(pRuntimeEnv, pQuery->current->pTable);
6218 6219
      }

H
Haojun Liao 已提交
6220
      if (pQuery->prjInfo.vgroupLimit > 0 && pQuery->current->resInfo.size > pQuery->prjInfo.vgroupLimit) {
H
Haojun Liao 已提交
6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238
        pQuery->current->lastKey =
                QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step;
        continue;
      }

      // it is a super table ordered projection query, check for the number of output for each vgroup
      if (pQuery->prjInfo.vgroupLimit > 0 && pQuery->rec.rows >= pQuery->prjInfo.vgroupLimit) {
        if (QUERY_IS_ASC_QUERY(pQuery) && blockInfo.window.skey >= pQuery->prjInfo.ts) {
          pQuery->current->lastKey =
                  QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step;
          continue;
        } else if (!QUERY_IS_ASC_QUERY(pQuery) && blockInfo.window.ekey <= pQuery->prjInfo.ts) {
          pQuery->current->lastKey =
                  QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step;
          continue;
        }
      }

6239 6240
      uint32_t     status = 0;
      SDataStatis *pStatis = NULL;
6241
      SArray      *pDataBlock = NULL;
6242

H
Haojun Liao 已提交
6243
      int32_t ret = loadDataBlockOnDemand(pRuntimeEnv, &pQuery->current->resInfo, pQueryHandle, &blockInfo,
6244 6245 6246 6247 6248
                                          &pStatis, &pDataBlock, &status);
      if (ret != TSDB_CODE_SUCCESS) {
        break;
      }

H
Haojun Liao 已提交
6249 6250 6251 6252 6253
      if(status == BLK_DATA_DISCARD) {
        pQuery->current->lastKey =
                QUERY_IS_ASC_QUERY(pQuery) ? blockInfo.window.ekey + step : blockInfo.window.skey + step;
        continue;
      }
6254

H
Haojun Liao 已提交
6255
      ensureOutputBuffer(pRuntimeEnv, blockInfo.rows);
H
Haojun Liao 已提交
6256 6257
      int64_t prev = getNumOfResult(pRuntimeEnv);

6258 6259 6260 6261 6262 6263 6264 6265 6266 6267
      pQuery->pos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : blockInfo.rows - 1;
      int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, binarySearchForKey, pDataBlock);

      summary->totalRows += blockInfo.rows;
      qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
             GET_QINFO_ADDR(pRuntimeEnv), blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, numOfRes,
             pQuery->current->lastKey);

      pQuery->rec.rows = getNumOfResult(pRuntimeEnv);

H
Haojun Liao 已提交
6268
      int64_t inc = pQuery->rec.rows - prev;
H
Haojun Liao 已提交
6269
      pQuery->current->resInfo.size += (int32_t) inc;
H
Haojun Liao 已提交
6270

6271 6272 6273 6274 6275
      // the flag may be set by tableApplyFunctionsOnBlock, clear it here
      CLEAR_QUERY_STATUS(pQuery, QUERY_COMPLETED);

      updateTableIdInfo(pQuery, pQInfo->arrTableIdInfo);

H
Haojun Liao 已提交
6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286
      if (pQuery->prjInfo.vgroupLimit >= 0) {
        if (((pQuery->rec.rows + pQuery->rec.total) < pQuery->prjInfo.vgroupLimit) || ((pQuery->rec.rows + pQuery->rec.total) > pQuery->prjInfo.vgroupLimit && prev < pQuery->prjInfo.vgroupLimit)) {
          if (QUERY_IS_ASC_QUERY(pQuery) && pQuery->prjInfo.ts < blockInfo.window.ekey) {
            pQuery->prjInfo.ts = blockInfo.window.ekey;
          } else if (!QUERY_IS_ASC_QUERY(pQuery) && pQuery->prjInfo.ts > blockInfo.window.skey) {
            pQuery->prjInfo.ts = blockInfo.window.skey;
          }
        }
      } else {
        // the limitation of output result is reached, set the query completed
        skipResults(pRuntimeEnv);
H
Haojun Liao 已提交
6287
        if (limitOperator(pQuery, pQInfo)) {
H
Haojun Liao 已提交
6288
          SET_STABLE_QUERY_OVER(pRuntimeEnv);
H
Haojun Liao 已提交
6289 6290
          break;
        }
6291 6292 6293 6294 6295 6296 6297 6298 6299 6300
      }

      // while the output buffer is full or limit/offset is applied, query may be paused here
      if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL|QUERY_COMPLETED)) {
        break;
      }
    }

    if (!hasMoreBlock) {
      setQueryStatus(pQuery, QUERY_COMPLETED);
H
Haojun Liao 已提交
6301
      SET_STABLE_QUERY_OVER(pRuntimeEnv);
6302
    }
6303 6304
  } else {
    /*
6305 6306 6307
     * the following two cases handled here.
     * 1. ts-comp query, and 2. the super table projection query with different query time range for each table.
     * If the subgroup index is larger than 0, results generated by group by tbname,k is existed.
6308 6309
     * we need to return it to client in the first place.
     */
H
Haojun Liao 已提交
6310 6311
    if (hasRemainData(&pRuntimeEnv->groupResInfo)) {
      copyToOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
6312
      pQuery->rec.total += pQuery->rec.rows;
6313

6314
      if (pQuery->rec.rows > 0) {
6315 6316 6317
        return;
      }
    }
6318

6319
    // all data have returned already
H
Haojun Liao 已提交
6320
    if (pRuntimeEnv->tableIndex >= pRuntimeEnv->tableqinfoGroupInfo.numOfTables) {
6321 6322
      return;
    }
6323

H
Haojun Liao 已提交
6324
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
H
Haojun Liao 已提交
6325
    resetResultRowInfo(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
6326

H
Haojun Liao 已提交
6327
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, 0);
H
Haojun Liao 已提交
6328 6329
    assert(taosArrayGetSize(group) == pRuntimeEnv->tableqinfoGroupInfo.numOfTables &&
           1 == taosArrayGetSize(pRuntimeEnv->tableqinfoGroupInfo.pGroupList));
6330

H
Haojun Liao 已提交
6331
    while (pRuntimeEnv->tableIndex < pRuntimeEnv->tableqinfoGroupInfo.numOfTables) {
6332
      if (isQueryKilled(pQInfo)) {
H
Haojun Liao 已提交
6333
        longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
6334
      }
6335

H
Haojun Liao 已提交
6336 6337 6338
      pQuery->current = taosArrayGetP(group, pRuntimeEnv->tableIndex);
      if (!multiTableMultioutputHelper(pQInfo, pRuntimeEnv->tableIndex)) {
        pRuntimeEnv->tableIndex++;
6339 6340
        continue;
      }
6341

H
hjxilinx 已提交
6342
      // TODO handle the limit offset problem
6343
      if (pQuery->numOfFilterCols == 0 && pQuery->limit.offset > 0) {
6344
        if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
H
Haojun Liao 已提交
6345
          pRuntimeEnv->tableIndex++;
6346 6347 6348
          continue;
        }
      }
6349

6350
      scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
6351
      skipResults(pRuntimeEnv);
6352

6353
      // the limitation of output result is reached, set the query completed
H
Haojun Liao 已提交
6354
      if (limitOperator(pQuery, pQInfo)) {
H
Haojun Liao 已提交
6355
        SET_STABLE_QUERY_OVER(pRuntimeEnv);
6356 6357
        break;
      }
6358

6359 6360
      // enable execution for next table, when handling the projection query
      enableExecutionForNextTable(pRuntimeEnv);
6361

6362
      if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
6363 6364 6365 6366 6367 6368
        /*
         * query range is identical in terms of all meters involved in query,
         * so we need to restore them at the *beginning* of query on each meter,
         * not the consecutive query on meter on which is aborted due to buffer limitation
         * to ensure that, we can reset the query range once query on a meter is completed.
         */
H
Haojun Liao 已提交
6369
        pRuntimeEnv->tableIndex++;
6370
        updateTableIdInfo(pQuery, pQInfo->arrTableIdInfo);
weixin_48148422's avatar
weixin_48148422 已提交
6371

6372
        // if the buffer is full or group by each table, we need to jump out of the loop
H
Haojun Liao 已提交
6373
        if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) {
6374 6375
          break;
        }
6376

H
Haojun Liao 已提交
6377 6378
        if (pRuntimeEnv->pTsBuf != NULL) {
          pRuntimeEnv->cur = pRuntimeEnv->pTsBuf->cur;
H
Haojun Liao 已提交
6379 6380
        }

6381
      } else {
6382
        // all data in the result buffer are skipped due to the offset, continue to retrieve data from current meter
6383 6384
        if (pQuery->rec.rows == 0) {
          assert(!Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL));
6385 6386
          continue;
        } else {
6387 6388 6389
          // buffer is full, wait for the next round to retrieve data from current meter
          assert(Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL));
          break;
6390 6391 6392
        }
      }
    }
H
Haojun Liao 已提交
6393

H
Haojun Liao 已提交
6394
    if (pRuntimeEnv->tableIndex >= pRuntimeEnv->tableqinfoGroupInfo.numOfTables) {
H
Haojun Liao 已提交
6395 6396
      setQueryStatus(pQuery, QUERY_COMPLETED);
    }
6397

6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408
    /*
     * 1. super table projection query, group-by on normal columns query, ts-comp query
     * 2. point interpolation query, last row query
     *
     * group-by on normal columns query and last_row query do NOT invoke the finalizer here,
     * since the finalize stage will be done at the client side.
     *
     * projection query, point interpolation query do not need the finalizer.
     *
     * Only the ts-comp query requires the finalizer function to be executed here.
     */
H
Haojun Liao 已提交
6409
    if (isTsCompQuery(pQuery)) {
6410 6411
      finalizeQueryResult(pRuntimeEnv);
    }
6412

H
Haojun Liao 已提交
6413 6414
    if (pRuntimeEnv->pTsBuf != NULL) {
      pRuntimeEnv->cur = pRuntimeEnv->pTsBuf->cur;
6415
    }
6416

6417 6418
    qDebug("QInfo %p numOfTables:%" PRIu64 ", index:%d, numOfGroups:%" PRIzu ", %" PRId64
           " points returned, total:%" PRId64 ", offset:%" PRId64,
H
Haojun Liao 已提交
6419
           pQInfo, (uint64_t)pRuntimeEnv->tableqinfoGroupInfo.numOfTables, pRuntimeEnv->tableIndex, numOfGroups, pQuery->rec.rows,
6420 6421
           pQuery->rec.total, pQuery->limit.offset);
  }
6422 6423
}

H
Haojun Liao 已提交
6424
static int32_t doSaveContext(SQInfo *pQInfo) {
6425 6426 6427
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *          pQuery = pRuntimeEnv->pQuery;

6428 6429 6430
  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
  SWITCH_ORDER(pQuery->order.order);
6431

H
Haojun Liao 已提交
6432 6433
  if (pRuntimeEnv->pTsBuf != NULL) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
6434
  }
6435

H
Haojun Liao 已提交
6436
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
6437

6438 6439 6440 6441
  // clean unused handle
  if (pRuntimeEnv->pSecQueryHandle != NULL) {
    tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle);
  }
H
Haojun Liao 已提交
6442

H
Haojun Liao 已提交
6443 6444
  setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
  switchCtxOrder(pRuntimeEnv);
H
Haojun Liao 已提交
6445
  disableFuncInReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
6446
  setupQueryRangeForReverseScan(pRuntimeEnv);
H
Haojun Liao 已提交
6447

H
Haojun Liao 已提交
6448
  pRuntimeEnv->prevGroupId = INT32_MIN;
H
Haojun Liao 已提交
6449
  pRuntimeEnv->pSecQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
6450
  return (pRuntimeEnv->pSecQueryHandle == NULL)? -1:0;
H
hjxilinx 已提交
6451 6452
}

6453 6454 6455 6456
static void doRestoreContext(SQInfo *pQInfo) {
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *          pQuery = pRuntimeEnv->pQuery;

H
hjxilinx 已提交
6457
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
6458
  SWITCH_ORDER(pQuery->order.order);
6459

H
Haojun Liao 已提交
6460 6461
  if (pRuntimeEnv->pTsBuf != NULL) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
6462
  }
6463

6464
  switchCtxOrder(pRuntimeEnv);
6465 6466 6467
  SET_MASTER_SCAN_FLAG(pRuntimeEnv);
}

H
Haojun Liao 已提交
6468
static void doCloseAllTimeWindow(SQInfo *pQInfo) {
6469
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
H
Haojun Liao 已提交
6470
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6471

H
Haojun Liao 已提交
6472
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
6473
    size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
6474
    for (int32_t i = 0; i < numOfGroup; ++i) {
H
Haojun Liao 已提交
6475
      SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
6476

6477
      size_t num = taosArrayGetSize(group);
6478
      for (int32_t j = 0; j < num; ++j) {
6479
        STableQueryInfo* item = taosArrayGetP(group, j);
H
Haojun Liao 已提交
6480
        closeAllResultRows(&item->resInfo);
6481
      }
H
hjxilinx 已提交
6482 6483
    }
  } else {  // close results for group result
H
Haojun Liao 已提交
6484
    closeAllResultRows(&pQInfo->runtimeEnv.resultRowInfo);
H
hjxilinx 已提交
6485 6486 6487
  }
}

H
Haojun Liao 已提交
6488
static UNUSED_FUNC void multiTableQueryProcess(SQInfo *pQInfo) {
6489
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
6490
  SQuery           *pQuery = pRuntimeEnv->pQuery;
6491

H
Haojun Liao 已提交
6492
  if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
H
Haojun Liao 已提交
6493
    if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
6494 6495
      copyResToQueryResultBuf(pQInfo, pQuery);
    } else {
H
Haojun Liao 已提交
6496
      copyToOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
6497
    }
6498

H
Haojun Liao 已提交
6499
    qDebug("QInfo:%p current:%"PRId64", total:%"PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total);
6500 6501
    return;
  }
6502

6503
  qDebug("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", order:%d, forward scan start", pQInfo,
6504 6505
         pQuery->window.skey, pQuery->window.ekey, pQuery->order.order);

H
hjxilinx 已提交
6506
  // do check all qualified data blocks
H
Haojun Liao 已提交
6507
  int64_t el = scanMultiTableDataBlocks(pQInfo);
6508
  qDebug("QInfo:%p master scan completed, elapsed time: %" PRId64 "ms, reverse scan start", pQInfo, el);
6509

H
hjxilinx 已提交
6510
  // query error occurred or query is killed, abort current execution
6511
  if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) {
6512
    qDebug("QInfo:%p query killed or error occurred, code:%s, abort", pQInfo, tstrerror(pQInfo->code));
H
Haojun Liao 已提交
6513
    longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
6514
  }
6515

H
hjxilinx 已提交
6516
  // close all time window results
H
Haojun Liao 已提交
6517
  doCloseAllTimeWindow(pQInfo);
6518

H
hjxilinx 已提交
6519
  if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
6520 6521 6522 6523 6524 6525 6526 6527
    int32_t code = doSaveContext(pQInfo);
    if (code == TSDB_CODE_SUCCESS) {
      el = scanMultiTableDataBlocks(pQInfo);
      qDebug("QInfo:%p reversed scan completed, elapsed time: %" PRId64 "ms", pQInfo, el);
      doRestoreContext(pQInfo);
    } else {
      pQInfo->code = code;
    }
H
hjxilinx 已提交
6528
  } else {
6529
    qDebug("QInfo:%p no need to do reversed scan, query completed", pQInfo);
6530
  }
6531

6532
  setQueryStatus(pQuery, QUERY_COMPLETED);
6533

6534
  if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) {
6535
    qDebug("QInfo:%p query killed or error occurred, code:%s, abort", pQInfo, tstrerror(pQInfo->code));
H
Haojun Liao 已提交
6536
    //TODO finalizeQueryResult may cause SEGSEV, since the memory may not allocated yet, add a cleanup function instead
H
Haojun Liao 已提交
6537
    longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
H
hjxilinx 已提交
6538
  }
6539

H
Haojun Liao 已提交
6540
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || isSumAvgRateQuery(pQuery)) {
H
Haojun Liao 已提交
6541
    copyResToQueryResultBuf(pQInfo, pQuery);
6542
  } else {  // not a interval query
H
Haojun Liao 已提交
6543 6544
    initGroupResInfo(&pRuntimeEnv->groupResInfo, &pRuntimeEnv->resultRowInfo, 0);
    copyToOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
6545
  }
6546

6547
  // handle the limitation of output buffer
6548
  qDebug("QInfo:%p points returned:%" PRId64 ", total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows);
6549 6550
}

H
Haojun Liao 已提交
6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567
static char *getArithemicInputSrc(void *param, const char *name, int32_t colId) {
  SArithmeticSupport *pSupport = (SArithmeticSupport *) param;
  SExprInfo* pExprInfo = (SExprInfo*) pSupport->exprList;

  int32_t index = -1;
  for (int32_t i = 0; i < pSupport->numOfCols; ++i) {
    if (colId == pExprInfo[i].base.resColId) {
      index = i;
      break;
    }
  }

  assert(index >= 0 && index < pSupport->numOfCols);
  return pSupport->data[index] + pSupport->offset * pExprInfo[index].bytes;
}

static void doSecondaryArithmeticProcess(SQuery* pQuery) {
H
Haojun Liao 已提交
6568 6569 6570
  if (pQuery->numOfExpr2 == 0) {
    return;
  }
H
Haojun Liao 已提交
6571

H
Haojun Liao 已提交
6572
  SArithmeticSupport arithSup = {0};
H
Haojun Liao 已提交
6573 6574 6575
  tFilePage **data = calloc(pQuery->numOfExpr2, POINTER_BYTES);
  for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) {
    int32_t bytes = pQuery->pExpr2[i].bytes;
P
plum-lihui 已提交
6576
    data[i] = (tFilePage *)malloc((size_t)(bytes * pQuery->rec.rows) + sizeof(tFilePage));
H
Haojun Liao 已提交
6577 6578
  }

H
Haojun Liao 已提交
6579 6580 6581 6582
  arithSup.offset = 0;
  arithSup.numOfCols = (int32_t)pQuery->numOfOutput;
  arithSup.exprList  = pQuery->pExpr1;
  arithSup.data      = calloc(arithSup.numOfCols, POINTER_BYTES);
H
Haojun Liao 已提交
6583

H
Haojun Liao 已提交
6584 6585
  for (int32_t k = 0; k < arithSup.numOfCols; ++k) {
    arithSup.data[k] = pQuery->sdata[k]->data;
H
Haojun Liao 已提交
6586 6587 6588 6589 6590 6591 6592 6593 6594 6595
  }

  for (int i = 0; i < pQuery->numOfExpr2; ++i) {
    SExprInfo *pExpr = &pQuery->pExpr2[i];

    // calculate the result from several other columns
    SSqlFuncMsg* pSqlFunc = &pExpr->base;
    if (pSqlFunc->functionId != TSDB_FUNC_ARITHM) {

      for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
6596 6597
        if (pSqlFunc->functionId == pQuery->pExpr1[j].base.functionId &&
            pSqlFunc->colInfo.colId == pQuery->pExpr1[j].base.colInfo.colId) {
P
plum-lihui 已提交
6598
          memcpy(data[i]->data, pQuery->sdata[j]->data, (size_t)(pQuery->pExpr1[j].bytes * pQuery->rec.rows));
H
Haojun Liao 已提交
6599 6600 6601 6602
          break;
        }
      }
    } else {
H
Haojun Liao 已提交
6603
      arithSup.pArithExpr = pExpr;
H
Haojun Liao 已提交
6604
      arithmeticTreeTraverse(arithSup.pArithExpr->pExpr, (int32_t)pQuery->rec.rows, data[i]->data, &arithSup, TSDB_ORDER_ASC,
H
Haojun Liao 已提交
6605 6606 6607 6608 6609
                            getArithemicInputSrc);
    }
  }

  for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) {
P
plum-lihui 已提交
6610
    memcpy(pQuery->sdata[i]->data, data[i]->data, (size_t)(pQuery->pExpr2[i].bytes * pQuery->rec.rows));
H
Haojun Liao 已提交
6611 6612
  }

H
Haojun Liao 已提交
6613 6614 6615 6616 6617 6618
  for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) {
    tfree(data[i]);
  }

  tfree(data);
  tfree(arithSup.data);
H
Haojun Liao 已提交
6619 6620
}

H
Haojun Liao 已提交
6621
static SSDataBlock* doTableScanImpl(STableScanInfo *pTableScanInfo) {
H
Haojun Liao 已提交
6622
  SSDataBlock *pBlock = &pTableScanInfo->block;
H
Haojun Liao 已提交
6623
  SQuery* pQuery = pTableScanInfo->pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
6624

H
Haojun Liao 已提交
6625 6626
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
6627

H
Haojun Liao 已提交
6628 6629
    // todo check for query cancel
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
6630

H
Haojun Liao 已提交
6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641
    if (pTableScanInfo->pRuntimeEnv->tableqinfoGroupInfo.numOfTables > 1) {
      STableQueryInfo **pTableQueryInfo = (STableQueryInfo **)taosHashGet(
          pTableScanInfo->pRuntimeEnv->tableqinfoGroupInfo.map, &pBlock->info.tid, sizeof(pBlock->info.tid));
      if (pTableQueryInfo == NULL) {
        break;
      }

      pQuery->current = *pTableQueryInfo;
      doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo);
    }

H
Haojun Liao 已提交
6642
    // this function never returns error?
H
Haojun Liao 已提交
6643
    uint32_t status;
H
Haojun Liao 已提交
6644 6645 6646
    int32_t  code =
        loadDataBlockOnDemand_rv(pTableScanInfo->pRuntimeEnv, pTableScanInfo->pCtx, pTableScanInfo->pResultRowInfo,
                                 pTableScanInfo->pQueryHandle, pBlock, &status);
H
Haojun Liao 已提交
6647 6648 6649
    if (code != TSDB_CODE_SUCCESS) {
      longjmp(pTableScanInfo->pRuntimeEnv->env, code);
    }
H
Haojun Liao 已提交
6650

H
Haojun Liao 已提交
6651 6652 6653
    // current block is ignored according to filter result by block statistics data, continue load the next block
    if (status == BLK_DATA_DISCARD) {
      continue;
H
Haojun Liao 已提交
6654 6655 6656 6657
    }

    return pBlock;
  }
H
Haojun Liao 已提交
6658 6659

  return NULL;
H
Haojun Liao 已提交
6660 6661 6662
}

static SSDataBlock* doTableScan(void* param) {
H
Haojun Liao 已提交
6663 6664 6665
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

  STableScanInfo   *pTableScanInfo = pOperator->optInfo;
H
Haojun Liao 已提交
6666
  SQueryRuntimeEnv *pRuntimeEnv = pTableScanInfo->pRuntimeEnv;
H
Haojun Liao 已提交
6667
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
6668 6669

  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
6670
    SSDataBlock* p = doTableScanImpl(pTableScanInfo);
H
Haojun Liao 已提交
6671 6672
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
6673 6674
    }

H
Haojun Liao 已提交
6675
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
6676 6677 6678 6679 6680
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
6681
    }
H
Haojun Liao 已提交
6682

H
Haojun Liao 已提交
6683
    // do prepare for the next round table scan operation
H
Haojun Liao 已提交
6684
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
6685
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
6686

H
Haojun Liao 已提交
6687
    pRuntimeEnv->resultRowInfo.curIndex = 0;
H
Haojun Liao 已提交
6688
    setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
6689
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
6690

H
Haojun Liao 已提交
6691 6692 6693 6694 6695 6696
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

    qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
6697
           pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
6698 6699
  }

H
Haojun Liao 已提交
6700 6701 6702
  if (pTableScanInfo->reverseTimes > 0) {
    setEnvBeforeReverseScan_rv(pRuntimeEnv);

H
Haojun Liao 已提交
6703
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
6704
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
6705

H
Haojun Liao 已提交
6706
    qDebug("QInfo:%p start to reverse scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
6707
           pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
6708

H
Haojun Liao 已提交
6709 6710
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
6711 6712
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
6713

H
Haojun Liao 已提交
6714
    SSDataBlock* p = doTableScanImpl(pTableScanInfo);
H
Haojun Liao 已提交
6715 6716
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
6717 6718
    }
  }
H
Haojun Liao 已提交
6719

H
Haojun Liao 已提交
6720 6721 6722
  return NULL;
}

H
Haojun Liao 已提交
6723
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
6724 6725
  assert(repeatTime > 0);

H
Haojun Liao 已提交
6726 6727
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
6728
  pInfo->times = repeatTime;
H
Haojun Liao 已提交
6729
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
6730
  pInfo->order = pRuntimeEnv->pQuery->order.order;
H
Haojun Liao 已提交
6731 6732

  pInfo->current = 0;
H
Haojun Liao 已提交
6733
  pInfo->pRuntimeEnv = pRuntimeEnv;
H
Haojun Liao 已提交
6734

H
Haojun Liao 已提交
6735 6736 6737 6738 6739 6740 6741
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name = "SeqScanTableOp";
  pOperator->blockingOptr = false;
  pOperator->completed    = false;
  pOperator->optInfo      = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
  pOperator->exec = doTableScan;
H
Haojun Liao 已提交
6742

H
Haojun Liao 已提交
6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754
  return pOperator;
}

void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

  char* name = pDownstream->name;
  if (strcasecmp(name, "AggregationOp") == 0) {
    SAggOperatorInfo* pAggInfo = pDownstream->optInfo;

    pTableScanInfo->pCtx = pAggInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->resultRowInfo;
H
Haojun Liao 已提交
6755 6756
  } else if (strcasecmp(name, "HashIntervalAggOp") == 0) {
    SHashIntervalOperatorInfo *pIntervalInfo = pDownstream->optInfo;
H
Haojun Liao 已提交
6757 6758 6759

    pTableScanInfo->pCtx = pIntervalInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pIntervalInfo->resultRowInfo;
H
Haojun Liao 已提交
6760 6761 6762 6763 6764 6765 6766 6767 6768 6769
  } else if (strcasecmp(name, "HashGroupbyAggOp") == 0) {
    SHashGroupbyOperatorInfo *pGroupbyInfo = pDownstream->optInfo;

    pTableScanInfo->pCtx = pGroupbyInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->resultRowInfo;
  } else if (strcasecmp(name, "STableIntervalAggOp") == 0) {
    SHashIntervalOperatorInfo *pInfo = pDownstream->optInfo;

    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
6770 6771 6772
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
6773 6774
}

H
Haojun Liao 已提交
6775
static SOperatorInfo* createBiDirectionTableScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
6776 6777 6778 6779 6780 6781 6782 6783
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
  pInfo->times = repeatTime;
  pInfo->reverseTimes = reverseTime;

  pInfo->current = 0;
H
Haojun Liao 已提交
6784 6785
  pInfo->order = pRuntimeEnv->pQuery->order.order;

H
Haojun Liao 已提交
6786
  pInfo->pRuntimeEnv = pRuntimeEnv;
H
Haojun Liao 已提交
6787 6788 6789 6790 6791 6792 6793 6794

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
  pOptr->name = "BidirectionSeqScanTableOp";
  pOptr->blockingOptr = false;
  pOptr->optInfo = pInfo;
  pOptr->exec = doTableScan;

  return pOptr;
H
Haojun Liao 已提交
6795 6796
}

H
Haojun Liao 已提交
6797
static UNUSED_FUNC int32_t getTableScanId(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
6798 6799 6800
  return pTableScanInfo->current;
}

H
Haojun Liao 已提交
6801
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
6802 6803 6804
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
6805
// this is a blocking operator
H
Haojun Liao 已提交
6806 6807
static SSDataBlock* doAggregation(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
6808 6809 6810
  if (pOperator->completed) {
    return NULL;
  }
H
Haojun Liao 已提交
6811

H
Haojun Liao 已提交
6812 6813
  SAggOperatorInfo* pAggInfo = pOperator->optInfo;
  SQueryRuntimeEnv* pRuntimeEnv = pAggInfo->pRuntimeEnv;
H
Haojun Liao 已提交
6814

H
Haojun Liao 已提交
6815
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
6816
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
6817

H
Haojun Liao 已提交
6818
  SQLFunctionCtx* pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, order, pQuery->vgId);
H
Haojun Liao 已提交
6819

H
Haojun Liao 已提交
6820
  SSDataBlock* pRes = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
H
Haojun Liao 已提交
6821
  setDefaultOutputBuf(pRuntimeEnv, pCtx, &pRuntimeEnv->resultRowInfo, pRes);
H
Haojun Liao 已提交
6822 6823

  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
6824
  pQuery->pos = 0;
H
Haojun Liao 已提交
6825

H
Haojun Liao 已提交
6826
  while(1) {
H
Haojun Liao 已提交
6827
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
6828 6829 6830 6831
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
6832 6833 6834 6835 6836
    if (strncasecmp(upstream->name, "BidirectionSeqScanTableOp", strlen("BidirectionSeqScanTableOp")) == 0) {
      STableScanInfo* pScanInfo = upstream->optInfo;
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
6837
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
6838
    setInputSDataBlock(pOperator, pCtx, pBlock, order);
H
Haojun Liao 已提交
6839
    aggApplyFunctions(pRuntimeEnv, pOperator, pCtx, pBlock);
H
Haojun Liao 已提交
6840 6841
  }

H
Haojun Liao 已提交
6842
  pOperator->completed = true;
H
Haojun Liao 已提交
6843 6844
  setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);

H
Haojun Liao 已提交
6845 6846 6847 6848 6849
  if (!pQuery->stableQuery) {
    finalizeQueryResult(pRuntimeEnv);
  }

  pRes->info.rows = getNumOfResult_rv(pRuntimeEnv, pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
6850
  destroySQLFunctionCtx(pCtx, pRes->info.numOfCols);
H
Haojun Liao 已提交
6851

H
Haojun Liao 已提交
6852
  return pRes;
H
Haojun Liao 已提交
6853 6854 6855 6856 6857 6858 6859
}

static SSDataBlock* doArithmeticOperation(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

  SArithOperatorInfo* pArithInfo = pOperator->optInfo;
  SQueryRuntimeEnv* pRuntimeEnv = pArithInfo->pRuntimeEnv;
H
Haojun Liao 已提交
6860

H
Haojun Liao 已提交
6861
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
6862

H
Haojun Liao 已提交
6863
  if (pArithInfo->pCtx == NULL) {
H
Haojun Liao 已提交
6864
    pArithInfo->pOutput = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
H
Haojun Liao 已提交
6865
    pArithInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, pQuery->order.order, pQuery->vgId);
H
Haojun Liao 已提交
6866
    initResultRowInfo(&pArithInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
6867 6868
  }

H
Haojun Liao 已提交
6869
  setDefaultOutputBuf(pRuntimeEnv, pArithInfo->pCtx, &pArithInfo->resultRowInfo, pArithInfo->pOutput);
H
Haojun Liao 已提交
6870

H
Haojun Liao 已提交
6871
  pRuntimeEnv->pQuery->pos = 0;
H
Haojun Liao 已提交
6872 6873
  pArithInfo->pOutput->info.rows = 0;

H
Haojun Liao 已提交
6874
  while(1) {
H
Haojun Liao 已提交
6875
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
6876
    if (pBlock == NULL) {
H
Haojun Liao 已提交
6877
      setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);
H
Haojun Liao 已提交
6878
      break;
H
Haojun Liao 已提交
6879 6880
    }

H
Haojun Liao 已提交
6881 6882
    setTagVal_rv(pRuntimeEnv, pRuntimeEnv->pQuery->current->pTable, pOperator->pExpr, pArithInfo->pCtx, pOperator->numOfOutput);

H
Haojun Liao 已提交
6883
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
6884 6885 6886
    for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
      pArithInfo->pCtx[i].size = pBlock->info.rows;
      if (pArithInfo->pCtx[i].functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6887
        setArithParams((SArithmeticSupport*) pArithInfo->pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock);
H
Haojun Liao 已提交
6888 6889 6890 6891 6892 6893 6894
      } else {
        SColIndex *pCol = &pOperator->pExpr[i].base.colInfo;
        if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) {
          for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
            SColumnInfoData *p = taosArrayGet(pBlock->pDataBlock, j);
            if (p->info.colId == pCol->colId) {
              pArithInfo->pCtx[i].pInput = p->pData;
H
Haojun Liao 已提交
6895 6896
              pArithInfo->pCtx[i].inputType = p->info.type;
              pArithInfo->pCtx[i].inputBytes = p->info.bytes;
H
Haojun Liao 已提交
6897 6898 6899 6900 6901 6902 6903 6904
              break;
            }
          }
        }
      }
    }

    arithmeticApplyFunctions(pRuntimeEnv, pArithInfo->pCtx, pOperator->pExpr, pOperator->numOfOutput);
H
Haojun Liao 已提交
6905 6906
    pArithInfo->pOutput->info.rows += pBlock->info.rows;
    if (pArithInfo->pOutput->info.rows > 4096) {
H
Haojun Liao 已提交
6907 6908 6909 6910
      break;
    }
  }

H
Haojun Liao 已提交
6911
  return pArithInfo->pOutput;
H
Haojun Liao 已提交
6912 6913 6914 6915 6916 6917
}

static SSDataBlock* doLimit(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->completed) {
    return NULL;
H
Haojun Liao 已提交
6918 6919
  }

H
Haojun Liao 已提交
6920 6921
  SLimitOperatorInfo* pInfo = pOperator->optInfo;

H
Haojun Liao 已提交
6922
  SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944
  if (pBlock == NULL) {
    setQueryStatus(pInfo->pRuntimeEnv->pQuery, QUERY_COMPLETED);
    pOperator->completed = true;
    return NULL;
  }

  if (pInfo->total + pBlock->info.rows >= pInfo->limit) {
    pBlock->info.rows = (pInfo->limit - pInfo->total);

    setQueryStatus(pInfo->pRuntimeEnv->pQuery, QUERY_COMPLETED);
    pOperator->completed = true;
  }

  return pBlock;
}

static SSDataBlock* doOffset(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;

  SOffsetOperatorInfo *pInfo = pOperator->optInfo;

  while (1) {
H
Haojun Liao 已提交
6945
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977
    if (pBlock == NULL) {
      setQueryStatus(pInfo->pRuntimeEnv->pQuery, QUERY_COMPLETED);
      return NULL;
    }

    if (pInfo->currentOffset == 0) {
      return pBlock;
    } else if (pInfo->currentOffset > pBlock->info.rows) {
      pInfo->currentOffset -= pBlock->info.rows;
    } else {
      int32_t remain = pBlock->info.rows - pInfo->currentOffset;
      pBlock->info.rows = remain;

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

        int16_t bytes = pColInfoData->info.bytes;
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pInfo->currentOffset, remain * bytes);
      }

      pInfo->currentOffset = 0;
      return pBlock;
    }
  }
}

static SSDataBlock* doHashIntervalAgg(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->completed) {
    return NULL;
  }

H
Haojun Liao 已提交
6978 6979 6980
  SHashIntervalOperatorInfo* pIntervalInfo = pOperator->optInfo;

  SQueryRuntimeEnv* pRuntimeEnv = pIntervalInfo->pRuntimeEnv;
H
Haojun Liao 已提交
6981 6982 6983 6984 6985 6986 6987 6988 6989
  if (hasRemainData(&pRuntimeEnv->groupResInfo)) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
      pOperator->completed = true;
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
6992
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
6993

H
Haojun Liao 已提交
6994
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
6995 6996 6997 6998 6999 7000 7001 7002
  pQuery->pos = 0;

  while(1) {
    SSDataBlock* pBlock = upstream->exec(upstream);
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
7003 7004 7005 7006 7007
    if (strncasecmp(upstream->name, "BidirectionSeqScanTableOp", strlen("BidirectionSeqScanTableOp")) == 0) {
      STableScanInfo* pScanInfo = upstream->optInfo;
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
7008
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
7009
    setInputSDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
7010
    hashIntervalAgg(pRuntimeEnv, &pRuntimeEnv->resultRowInfo, pIntervalInfo->pCtx, pBlock);
H
Haojun Liao 已提交
7011 7012
  }

H
Haojun Liao 已提交
7013
  closeAllResultRows(&pRuntimeEnv->resultRowInfo);
H
Haojun Liao 已提交
7014
  setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);
H
Haojun Liao 已提交
7015
  finalizeQueryResult_rv(pRuntimeEnv, pIntervalInfo->pCtx, pOperator->numOfOutput, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
7016

H
Haojun Liao 已提交
7017
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pRuntimeEnv->resultRowInfo, 0);
H
Haojun Liao 已提交
7018
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
7019

H
Haojun Liao 已提交
7020 7021 7022 7023 7024
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
    pOperator->completed = true;
  }

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

H
Haojun Liao 已提交
7027
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
7028 7029 7030 7031 7032
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->completed) {
    return NULL;
  }

H
Haojun Liao 已提交
7033 7034 7035 7036 7037
  SHashIntervalOperatorInfo* pIntervalInfo = pOperator->optInfo;

  SQueryRuntimeEnv* pRuntimeEnv = pIntervalInfo->pRuntimeEnv;
  if (hasRemainData(&pRuntimeEnv->groupResInfo)) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
7038

H
Haojun Liao 已提交
7039 7040 7041 7042 7043 7044 7045
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
      pOperator->completed = true;
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
7046 7047 7048
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
7049
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
7050
  pQuery->pos = 0;
H
Haojun Liao 已提交
7051 7052

  while(1) {
H
Haojun Liao 已提交
7053
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
7054
    if (pBlock == NULL) {
H
Haojun Liao 已提交
7055
      break;
H
Haojun Liao 已提交
7056 7057
    }

H
Haojun Liao 已提交
7058 7059 7060 7061 7062
    if (strncasecmp(upstream->name, "BidirectionSeqScanTableOp", strlen("BidirectionSeqScanTableOp")) == 0) {
      STableScanInfo* pScanInfo = upstream->optInfo;
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
7063
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
7064 7065 7066 7067
    setInputSDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, order);
    setEnvForEachBlock(pRuntimeEnv, pRuntimeEnv->pQuery->current, &pBlock->info);

    hashIntervalAgg(pRuntimeEnv, &pRuntimeEnv->pQuery->current->resInfo, pIntervalInfo->pCtx, pBlock);
H
Haojun Liao 已提交
7068
  }
H
Haojun Liao 已提交
7069

H
Haojun Liao 已提交
7070 7071
  closeAllResultRows(&pRuntimeEnv->resultRowInfo);
  setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);
H
Haojun Liao 已提交
7072
  finalizeQueryResult_rv(pRuntimeEnv, pIntervalInfo->pCtx, pOperator->numOfOutput, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
7073

H
Haojun Liao 已提交
7074 7075 7076
  copyResToQueryResultBuf_rv(pRuntimeEnv, 3000, pIntervalInfo->pRes);
//  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pRuntimeEnv->resultRowInfo, 0);
//  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
7077

H
Haojun Liao 已提交
7078 7079 7080 7081 7082 7083
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
    pOperator->completed = true;
  }

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

H
Haojun Liao 已提交
7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133
static SSDataBlock* doHashGroupbyAgg(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->completed) {
    return NULL;
  }

  SHashGroupbyOperatorInfo *pInfo = pOperator->optInfo;

  SQueryRuntimeEnv* pRuntimeEnv = pInfo->pRuntimeEnv;
  if (hasRemainData(&pRuntimeEnv->groupResInfo)) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
    if (pInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
      pOperator->completed = true;
    }
    return pInfo->pRes;
  }

  SOperatorInfo* upstream = pOperator->upstream;
  pRuntimeEnv->pQuery->pos = 0;

  while(1) {
    SSDataBlock* pBlock = upstream->exec(upstream);
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
    setInputSDataBlock(pOperator, pInfo->pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
    if (pInfo->colIndex == -1) {
      pInfo->colIndex = getGroupbyColumnData_rv(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
    }

    hashGroupbyAgg(pRuntimeEnv, pOperator, &pInfo->resultRowInfo, pInfo->pCtx, pBlock, pInfo->colIndex);
  }

  closeAllResultRows(&pInfo->resultRowInfo);
  setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);
  finalizeQueryResult_rv(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo);

  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->resultRowInfo, 0);
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);

  if (pInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
    pOperator->completed = true;
  }

  return pInfo->pRes;
}

H
Haojun Liao 已提交
7134 7135 7136
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->completed) {
H
Haojun Liao 已提交
7137 7138 7139
    return NULL;
  }

H
Haojun Liao 已提交
7140 7141
  SFillOperatorInfo *pInfo = pOperator->optInfo;
  SQueryRuntimeEnv* pRuntimeEnv = pInfo->pRuntimeEnv;
H
Haojun Liao 已提交
7142

H
Haojun Liao 已提交
7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163
  if (taosFillHasMoreResults(pRuntimeEnv->pFillInfo)) {
    doFillGapsInResults_rv(pRuntimeEnv, pInfo->pRes);
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
      taosFillSetStartInfo(pRuntimeEnv->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
      setQueryStatus(pRuntimeEnv->pQuery, QUERY_COMPLETED);
    } else {
      taosFillSetStartInfo(pRuntimeEnv->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey);
      taosFillSetInputDataBlock(pRuntimeEnv->pFillInfo, pBlock);
    }

    doFillGapsInResults_rv(pRuntimeEnv, pInfo->pRes);
    return pInfo->pRes;
  }

  return pInfo->pRes;
}
H
Haojun Liao 已提交
7164

H
Haojun Liao 已提交
7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176
// todo set the attribute of query scan count
static int32_t getNumOfScanTimes(SQuery* pQuery) {
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) {
      return 2;
    }
  }

  return 1;
}

H
Haojun Liao 已提交
7177 7178 7179 7180 7181
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
7182 7183 7184 7185
  if (pOperator->cleanup != NULL) {
    pOperator->cleanup(pOperator->optInfo);
  }

H
Haojun Liao 已提交
7186 7187 7188 7189 7190
  destroyOperatorInfo(pOperator->upstream);
  tfree(pOperator->optInfo);
  tfree(pOperator);
}

H
Haojun Liao 已提交
7191
static SOperatorInfo* createAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7192 7193 7194 7195 7196
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

  pInfo->pTableQueryInfo = pTableQueryInfo;
  pInfo->pRuntimeEnv = pRuntimeEnv;

H
Haojun Liao 已提交
7197 7198
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
7199 7200 7201
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name = "AggregationOp";
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
7202
  pOperator->completed    = false;
H
Haojun Liao 已提交
7203
  pOperator->optInfo      = pInfo;
H
Haojun Liao 已提交
7204
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7205
  pOperator->exec         = doAggregation;
H
Haojun Liao 已提交
7206 7207
  pOperator->pExpr        = pRuntimeEnv->pQuery->pExpr1;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfOutput;
H
Haojun Liao 已提交
7208

H
Haojun Liao 已提交
7209 7210 7211 7212

  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, pQuery->order.order, pQuery->vgId);
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);

H
Haojun Liao 已提交
7213
  return pOperator;
H
Haojun Liao 已提交
7214 7215
}

H
Haojun Liao 已提交
7216
static SOperatorInfo* createArithOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7217 7218 7219 7220 7221 7222 7223 7224
  SArithOperatorInfo* pInfo = calloc(1, sizeof(SArithOperatorInfo));

  pInfo->pTableQueryInfo = pTableQueryInfo;
  pInfo->pRuntimeEnv = pRuntimeEnv;

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "ArithmeticOp";
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
7225
  pOperator->completed    = false;
H
Haojun Liao 已提交
7226
  pOperator->optInfo      = pInfo;
H
Haojun Liao 已提交
7227
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7228
  pOperator->exec         = doArithmeticOperation;
H
Haojun Liao 已提交
7229 7230 7231 7232 7233 7234
  pOperator->pExpr        = (pRuntimeEnv->pQuery->pExpr2 == NULL)? pRuntimeEnv->pQuery->pExpr1:pRuntimeEnv->pQuery->pExpr2;
  pOperator->numOfOutput  = (pRuntimeEnv->pQuery->pExpr2 == NULL)? pRuntimeEnv->pQuery->numOfOutput:pRuntimeEnv->pQuery->numOfExpr2;

  return pOperator;
}

H
Haojun Liao 已提交
7235
static SOperatorInfo* createLimitOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7236 7237 7238 7239 7240 7241 7242 7243 7244 7245
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));

  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;
  pInfo->pRuntimeEnv = pRuntimeEnv;

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

  pOperator->name         = "LimitOp";
  pOperator->blockingOptr = false;
  pOperator->completed    = false;
H
Haojun Liao 已提交
7246
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7247 7248 7249 7250 7251 7252 7253 7254
  pOperator->exec         = doLimit;
  pOperator->pExpr        = NULL;
  pOperator->numOfOutput  = 0;
  pOperator->optInfo      = pInfo;

  return pOperator;
}

H
Haojun Liao 已提交
7255
static SOperatorInfo* createOffsetOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

  pInfo->offset = pRuntimeEnv->pQuery->limit.offset;
  pInfo->currentOffset = pInfo->offset;
  pInfo->pRuntimeEnv = pRuntimeEnv;

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

  pOperator->name         = "OffsetOp";
  pOperator->blockingOptr = false;
  pOperator->completed    = false;
H
Haojun Liao 已提交
7267
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7268 7269 7270 7271
  pOperator->exec         = doOffset;
  pOperator->pExpr        = NULL;
  pOperator->numOfOutput  = 0;
  pOperator->optInfo      = pInfo;
H
Haojun Liao 已提交
7272 7273 7274 7275

  return pOperator;
}

H
Haojun Liao 已提交
7276
static SOperatorInfo* createHashIntervalAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7277 7278 7279 7280 7281
  SHashIntervalOperatorInfo* pInfo = calloc(1, sizeof(SHashIntervalOperatorInfo));

  pInfo->pRuntimeEnv = pRuntimeEnv;
  pInfo->pTableQueryInfo = pTableQueryInfo;

H
Haojun Liao 已提交
7282
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
7283 7284 7285 7286 7287
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "HashIntervalAggOp";
  pOperator->blockingOptr = true;
  pOperator->completed    = false;
H
Haojun Liao 已提交
7288
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7289
  pOperator->exec         = doHashIntervalAgg;
H
Haojun Liao 已提交
7290 7291 7292 7293 7294
  pOperator->pExpr        = pQuery->pExpr1;
  pOperator->numOfOutput  = pQuery->numOfOutput;
  pOperator->optInfo      = pInfo;

  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, pQuery->order.order, pQuery->vgId);
H
Haojun Liao 已提交
7295
  pInfo->pRes = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
H
Haojun Liao 已提交
7296 7297 7298 7299 7300
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  return pOperator;
}

H
Haojun Liao 已提交
7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326
static SOperatorInfo* createStableIntervalOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
  SHashIntervalOperatorInfo* pInfo = calloc(1, sizeof(SHashIntervalOperatorInfo));

  pInfo->pRuntimeEnv = pRuntimeEnv;
  pInfo->pTableQueryInfo = pTableQueryInfo;

  SQuery* pQuery = pRuntimeEnv->pQuery;
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "STableIntervalAggOp";
  pOperator->blockingOptr = true;
  pOperator->completed    = false;
  pOperator->upstream     = upstream;
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->pExpr        = pQuery->pExpr1;
  pOperator->numOfOutput  = pQuery->numOfOutput;
  pOperator->optInfo      = pInfo;

  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, pQuery->order.order, pQuery->vgId);
  pInfo->pRes = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  return pOperator;
}

SOperatorInfo* createHashGroupbyAggOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
7327
  SHashGroupbyOperatorInfo* pInfo = calloc(1, sizeof(SHashGroupbyOperatorInfo));
H
Haojun Liao 已提交
7328 7329 7330

  pInfo->pRuntimeEnv = pRuntimeEnv;
  pInfo->pTableQueryInfo = pTableQueryInfo;
H
Haojun Liao 已提交
7331
  pInfo->colIndex = -1;
H
Haojun Liao 已提交
7332

H
Haojun Liao 已提交
7333
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
7334 7335
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
7336
  pOperator->name         = "HashGroupbyAggOp";
H
Haojun Liao 已提交
7337
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
7338 7339
  pOperator->completed    = false;
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7340 7341 7342
  pOperator->exec         = doHashGroupbyAgg;
  pOperator->pExpr        = pQuery->pExpr1;
  pOperator->numOfOutput  = pQuery->numOfOutput;
H
Haojun Liao 已提交
7343 7344
  pOperator->optInfo      = pInfo;

H
Haojun Liao 已提交
7345 7346 7347 7348
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pOperator->numOfOutput, pOperator->pExpr, pQuery->order.order, pQuery->vgId);
  pInfo->pRes = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);

H
Haojun Liao 已提交
7349 7350
  return pOperator;
}
H
Haojun Liao 已提交
7351

H
Haojun Liao 已提交
7352 7353
static SOperatorInfo* createFillOperatorInfo(STableQueryInfo* pTableQueryInfo, SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
7354 7355 7356 7357 7358 7359 7360 7361

  pInfo->pRuntimeEnv = pRuntimeEnv;

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

  pOperator->name         = "FillOp";
  pOperator->blockingOptr = false;
  pOperator->completed    = false;
H
Haojun Liao 已提交
7362
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
7363 7364 7365 7366 7367
  pOperator->exec         = doFill;
  pOperator->pExpr        = pRuntimeEnv->pQuery->pExpr1;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfOutput;
  pOperator->optInfo      = pInfo;

H
Haojun Liao 已提交
7368
  pInfo->pRes = createOutputBuf(pOperator->pExpr, pOperator->numOfOutput);
H
Haojun Liao 已提交
7369 7370 7371 7372 7373
  return pOperator;
}



7374 7375 7376 7377 7378 7379
/*
 * in each query, this function will be called only once, no retry for further result.
 *
 * select count(*)/top(field,k)/avg(field name) from table_name [where ts>now-1a];
 * select count(*) from table_name group by status_column;
 */
H
Haojun Liao 已提交
7380
void tableAggregationProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
7381
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
7382

H
hjxilinx 已提交
7383
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
7384
  if (!pQuery->topBotQuery && pQuery->limit.offset > 0) {  // no need to execute, since the output will be ignore.
H
Haojun Liao 已提交
7385 7386
    return;
  }
7387

H
Haojun Liao 已提交
7388
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
H
Haojun Liao 已提交
7389
  pQuery->rec.rows = (pRuntimeEnv->outputBuf != NULL)? pRuntimeEnv->outputBuf->info.rows:0;
7390 7391
}

H
Haojun Liao 已提交
7392
static void tableProjectionProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
7393
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
7394

7395
  // for ts_comp query, re-initialized is not allowed
H
Haojun Liao 已提交
7396
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
7397
  if (!isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
7398
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
7399
  }
7400

7401
  // skip blocks without load the actual data block from file if no filter condition present
H
Haojun Liao 已提交
7402 7403 7404 7405 7406
//  skipBlocks(&pQInfo->runtimeEnv);
//  if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0) {
//    setQueryStatus(pQuery, QUERY_COMPLETED);
//    return;
//  }
7407

H
Haojun Liao 已提交
7408 7409
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
  pQuery->rec.rows = (pRuntimeEnv->outputBuf != NULL)? pRuntimeEnv->outputBuf->info.rows : 0;
H
Haojun Liao 已提交
7410 7411

#if 0
7412
  while (1) {
7413
    scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
H
hjxilinx 已提交
7414
    finalizeQueryResult(pRuntimeEnv);
7415

7416 7417
    pQuery->rec.rows = getNumOfResult(pRuntimeEnv);
    if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols > 0 && pQuery->rec.rows > 0) {
7418
      skipResults(pRuntimeEnv);
7419 7420 7421
    }

    /*
H
hjxilinx 已提交
7422 7423
     * 1. if pQuery->size == 0, pQuery->limit.offset >= 0, still need to check data
     * 2. if pQuery->size > 0, pQuery->limit.offset must be 0
7424
     */
7425
    if (pQuery->rec.rows > 0 || Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
7426 7427 7428
      break;
    }

7429
    qDebug("QInfo:%p skip current result, offset:%" PRId64 ", next qrange:%" PRId64 "-%" PRId64,
B
Bomin Zhang 已提交
7430
           pQInfo, pQuery->limit.offset, pQuery->current->lastKey, pQuery->current->win.ekey);
7431

H
Haojun Liao 已提交
7432
    resetDefaultResInfoOutputBuf(pRuntimeEnv);
7433 7434
  }

H
Haojun Liao 已提交
7435
  limitOperator(pQuery, pQInfo);
7436
  if (Q_STATUS_EQUAL(pQuery->status, QUERY_RESBUF_FULL)) {
7437
    qDebug("QInfo:%p query paused due to output limitation, next qrange:%" PRId64 "-%" PRId64, pQInfo,
H
hjxilinx 已提交
7438
        pQuery->current->lastKey, pQuery->window.ekey);
weixin_48148422's avatar
weixin_48148422 已提交
7439
  } else if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
7440 7441
    STableIdInfo tidInfo = createTableIdInfo(pQuery);
    taosHashPut(pQInfo->arrTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo));
7442 7443
  }

H
Haojun Liao 已提交
7444
  if (!isTsCompQuery(pQuery)) {
7445 7446
    assert(pQuery->rec.rows <= pQuery->rec.capacity);
  }
H
Haojun Liao 已提交
7447
#endif
7448 7449
}

H
Haojun Liao 已提交
7450
static UNUSED_FUNC void copyAndFillResult(SQInfo* pQInfo) {
H
Haojun Liao 已提交
7451 7452 7453 7454
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery* pQuery = pRuntimeEnv->pQuery;

  while(1) {
H
Haojun Liao 已提交
7455
    copyToOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
H
Haojun Liao 已提交
7456 7457 7458
    doSecondaryArithmeticProcess(pQuery);

    TSKEY lastKey = 0;
H
Haojun Liao 已提交
7459
    if (!hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
7460 7461 7462 7463 7464 7465 7466 7467 7468 7469
      lastKey = pQuery->window.ekey;
    } else {
      lastKey = ((TSKEY*)pQuery->sdata[0]->data)[pQuery->rec.rows - 1];
    }

    assert(lastKey <= pQuery->window.ekey);

    taosFillSetStartInfo(pRuntimeEnv->pFillInfo, (int32_t)pQuery->rec.rows, lastKey);
    taosFillSetDataBlockFromFilePage(pRuntimeEnv->pFillInfo, (const tFilePage **)pQuery->sdata);

H
Haojun Liao 已提交
7470
//    pQuery->rec.rows = doFillGapsInResults(pRuntimeEnv, (tFilePage **)pQuery->sdata);
H
Haojun Liao 已提交
7471 7472 7473 7474 7475 7476 7477

    if (pQuery->rec.rows > 0) {
      limitOperator(pQuery, pQInfo);
      break;
    }

    // here the pQuery->rec.rows == 0
H
Haojun Liao 已提交
7478
    if (!hasRemainData(&pRuntimeEnv->groupResInfo) && !taosFillHasMoreResults(pRuntimeEnv->pFillInfo)) {
H
Haojun Liao 已提交
7479 7480 7481 7482 7483
      break;
    }
  }
}

7484
// handle time interval query on table
H
hjxilinx 已提交
7485
static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
7486
  SQueryRuntimeEnv *pRuntimeEnv = &(pQInfo->runtimeEnv);
H
hjxilinx 已提交
7487
  SQuery *pQuery = pRuntimeEnv->pQuery;
7488

7489
  TSKEY newStartKey = QUERY_IS_ASC_QUERY(pQuery)? INT64_MIN:INT64_MAX;
7490

7491
  // skip blocks without load the actual data block from file if no filter condition present
H
Haojun Liao 已提交
7492
  if (!pQuery->groupbyColumn) {
H
Haojun Liao 已提交
7493 7494 7495 7496 7497
    skipTimeInterval(pRuntimeEnv, &newStartKey);
    if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) {
      setQueryStatus(pQuery, QUERY_COMPLETED);
      return;
    }
7498 7499
  }

H
Haojun Liao 已提交
7500
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
H
Haojun Liao 已提交
7501
  pQuery->rec.rows = (pRuntimeEnv->outputBuf != NULL)? pRuntimeEnv->outputBuf->info.rows:0;
7502 7503
}

H
Haojun Liao 已提交
7504
void tableQueryImpl(SQInfo *pQInfo) {
7505 7506 7507
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *          pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
7508
#if 0
H
Haojun Liao 已提交
7509
  if (hasNotReturnedResults(pRuntimeEnv, &pRuntimeEnv->groupResInfo)) {
7510
    if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
7511 7512 7513 7514
      /*
       * There are remain results that are not returned due to result interpolation
       * So, we do keep in this procedure instead of launching retrieve procedure for next results.
       */
H
Haojun Liao 已提交
7515
//      pQuery->rec.rows = doFillGapsInResults(pRuntimeEnv, (tFilePage **)pQuery->sdata);
H
Haojun Liao 已提交
7516
      if (pQuery->rec.rows > 0) {
H
Haojun Liao 已提交
7517 7518 7519 7520
        limitOperator(pQuery, pQInfo);
        qDebug("QInfo:%p current:%" PRId64 " returned, total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total);
      } else {
        return copyAndFillResult(pQInfo);
H
Haojun Liao 已提交
7521 7522 7523
      }

    } else {
7524
      pQuery->rec.rows = 0;
H
Haojun Liao 已提交
7525
      assert(pRuntimeEnv->resultRowInfo.size > 0);
H
Haojun Liao 已提交
7526
      copyToOutputBuf(pRuntimeEnv, &pRuntimeEnv->resultRowInfo);
H
Haojun Liao 已提交
7527
      doSecondaryArithmeticProcess(pQuery);
7528

H
Haojun Liao 已提交
7529 7530
      if (pQuery->rec.rows > 0) {
        limitOperator(pQuery, pQInfo);
7531
      }
H
Haojun Liao 已提交
7532

7533 7534 7535
      if (pQuery->rec.rows > 0) {
        qDebug("QInfo:%p %" PRId64 " rows returned from group results, total:%" PRId64 "", pQInfo, pQuery->rec.rows,
               pQuery->rec.total);
H
Haojun Liao 已提交
7536
      } else {
7537
        qDebug("QInfo:%p query over, %" PRId64 " rows are returned", pQInfo, pQuery->rec.total);
7538 7539
      }
    }
H
Haojun Liao 已提交
7540 7541

    return;
7542
  }
H
Haojun Liao 已提交
7543
#endif
7544

H
hjxilinx 已提交
7545
  // number of points returned during this query
7546
  pQuery->rec.rows = 0;
7547
  int64_t st = taosGetTimestampUs();
7548

H
Haojun Liao 已提交
7549
  assert(pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1);
H
Haojun Liao 已提交
7550
  SArray* g = GET_TABLEGROUP(pRuntimeEnv, 0);
H
Haojun Liao 已提交
7551

7552
  STableQueryInfo* item = taosArrayGetP(g, 0);
H
Haojun Liao 已提交
7553
  pQuery->current = item;
7554

7555
  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
7556
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || pQuery->groupbyColumn) {  // interval (down sampling operation)
7557
    tableIntervalProcess(pQInfo, item);
H
Haojun Liao 已提交
7558
  } else if (isFixedOutputQuery(pQuery)) {
H
Haojun Liao 已提交
7559
    tableAggregationProcess(pQInfo, item);
7560
  } else {  // diff/add/multiply/subtract/division
H
Haojun Liao 已提交
7561
    assert(pQuery->checkResultBuf == 1);
H
Haojun Liao 已提交
7562
    tableProjectionProcess(pQInfo, item);
7563
  }
7564

7565
  // record the total elapsed time
H
Haojun Liao 已提交
7566
  pQInfo->summary.elapsedTime += (taosGetTimestampUs() - st);
H
Haojun Liao 已提交
7567
  assert(pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1);
7568
}
H
Haojun Liao 已提交
7569 7570

void buildTableBlockDistResult(SQInfo *pQInfo) {
Y
yihaoDeng 已提交
7571 7572 7573 7574 7575 7576
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;
  pQuery->pos = 0;

  STableBlockDist *pTableBlockDist  = calloc(1, sizeof(STableBlockDist)); 
  pTableBlockDist->dataBlockInfos   = taosArrayInit(512, sizeof(SDataBlockInfo));
Y
yihaoDeng 已提交
7577
  pTableBlockDist->result           = (char *)malloc(512);
Y
yihaoDeng 已提交
7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612

  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
  SSchema blockDistSchema = tGetBlockDistColumnSchema();

  int64_t startTime = taosGetTimestampUs();
  while (tsdbNextDataBlockWithoutMerge(pQueryHandle)) {
    if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) {
      freeTableBlockDist(pTableBlockDist);
      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
    if (pTableBlockDist->firstSeekTimeUs == 0) {
       pTableBlockDist->firstSeekTimeUs = taosGetTimestampUs() - startTime;
    }   
   
    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
    taosArrayPush(pTableBlockDist->dataBlockInfos, &blockInfo); 
  }
  if (terrno != TSDB_CODE_SUCCESS) {
    freeTableBlockDist(pTableBlockDist);
    longjmp(pRuntimeEnv->env, terrno);
  }

  pTableBlockDist->numOfRowsInMemTable = tsdbGetNumOfRowsInMemTable(pQueryHandle); 
  
  generateBlockDistResult(pTableBlockDist); 

  int type = -1;
  assert(pQuery->numOfOutput == 1);
  SExprInfo* pExprInfo = pQuery->pExpr1;
  for (int32_t j = 0; j < pQuery->numOfOutput; j++) {
    if (pExprInfo[j].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      type = blockDistSchema.type;
    }
    assert(type == TSDB_DATA_TYPE_BINARY);
Y
yihaoDeng 已提交
7613
    STR_WITH_SIZE_TO_VARSTR(pQuery->sdata[j]->data, pTableBlockDist->result, (VarDataLenT)strlen(pTableBlockDist->result)); 
Y
yihaoDeng 已提交
7614 7615 7616 7617 7618 7619 7620 7621
  }

  freeTableBlockDist(pTableBlockDist);

  pQuery->rec.rows = 1;
  setQueryStatus(pQuery, QUERY_COMPLETED);
  return;
}
7622

H
Haojun Liao 已提交
7623
void stableQueryImpl(SQInfo *pQInfo) {
H
Haojun Liao 已提交
7624 7625
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;
7626
  pQuery->rec.rows = 0;
7627

7628
  int64_t st = taosGetTimestampUs();
7629

H
Haojun Liao 已提交
7630 7631 7632 7633 7634 7635 7636 7637 7638
//  if (QUERY_IS_INTERVAL_QUERY(pQuery) ||
//      (isFixedOutputQuery(pQuery) && (!isPointInterpoQuery(pQuery)) && (!pQuery->groupbyColumn))) {
    //multiTableQueryProcess(pQInfo);
    pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
    pQuery->rec.rows = pRuntimeEnv->outputBuf != NULL? pRuntimeEnv->outputBuf->info.rows:0;
//  } else {
//    assert(pQuery->checkResultBuf == 1 || isPointInterpoQuery(pQuery) || pQuery->groupbyColumn);
//    sequentialTableProcess(pQInfo);
//  }
7639

H
hjxilinx 已提交
7640
  // record the total elapsed time
H
Haojun Liao 已提交
7641
  pQInfo->summary.elapsedTime += (taosGetTimestampUs() - st);
H
hjxilinx 已提交
7642 7643
}

7644
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
7645
  int32_t j = 0;
7646

7647
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
7648
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
7649
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
7650 7651
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
7652
    }
Y
yihaoDeng 已提交
7653
    
H
Haojun Liao 已提交
7654

7655 7656 7657 7658
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
7659

7660 7661
      j += 1;
    }
7662

Y
TD-1230  
yihaoDeng 已提交
7663
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
7664
    return TSDB_UD_COLUMN_INDEX;
7665 7666 7667 7668 7669
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
7670

7671
      j += 1;
7672 7673
    }
  }
7674 7675

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
7676 7677
}

7678 7679
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
7680
  return j != INT32_MIN;
7681 7682
}

7683
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
7684 7685
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
7686
    return false;
7687 7688
  }

H
hjxilinx 已提交
7689
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
7690
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
7691
    return false;
7692 7693
  }

H
hjxilinx 已提交
7694
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
7695
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
7696
    return false;
7697 7698
  }

7699 7700
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
7701
    return false;
7702 7703
  }

7704 7705 7706
  return true;
}

7707
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
7708 7709 7710 7711
  int32_t numOfTotal = pQueryMsg->numOfCols + pQueryMsg->numOfTags;
  if (pQueryMsg->numOfCols < 0 || pQueryMsg->numOfTags < 0 || numOfTotal > TSDB_MAX_COLUMNS) {
    qError("qmsg:%p illegal value of numOfCols %d numOfTags:%d", pQueryMsg, pQueryMsg->numOfCols, pQueryMsg->numOfTags);
    return false;
7712 7713 7714
  }

  if (numOfTotal == 0) {
7715
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
7716 7717 7718 7719 7720
      SSqlFuncMsg* pFuncMsg = pExprMsg[i];

      if ((pFuncMsg->functionId == TSDB_FUNC_TAGPRJ) ||
          (pFuncMsg->functionId == TSDB_FUNC_TID_TAG && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX)) {
7721
        continue;
7722
      }
7723

7724
      return false;
7725 7726
    }
  }
7727

7728 7729 7730 7731 7732 7733
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

7734
  return true;
7735 7736
}

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

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

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

7745
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
7746 7747
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
7748

H
hjxilinx 已提交
7749 7750 7751
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
7752

H
hjxilinx 已提交
7753 7754
  return pMsg;
}
7755

7756
/**
H
hjxilinx 已提交
7757
 * pQueryMsg->head has been converted before this function is called.
7758
 *
H
hjxilinx 已提交
7759
 * @param pQueryMsg
7760 7761 7762 7763
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
7764
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
7765 7766
  int32_t code = TSDB_CODE_SUCCESS;

7767 7768 7769 7770
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

7771 7772 7773 7774
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
7775 7776 7777
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
7778 7779
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
7780
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
7781

7782 7783
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
7784
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
7785
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
7786 7787

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
7788
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
7789
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
7790 7791 7792
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
7793
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
7794
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
7795
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
7796
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
7797
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
7798
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
7799
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
7800

7801
  // query msg safety check
7802
  if (!validateQueryMsg(pQueryMsg)) {
7803 7804
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
7805 7806
  }

H
hjxilinx 已提交
7807 7808
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
7809 7810
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
7811
    pColInfo->colId = htons(pColInfo->colId);
7812
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
7813 7814
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
7815

7816 7817 7818 7819 7820
    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;
    }
7821

H
hjxilinx 已提交
7822
    int32_t numOfFilters = pColInfo->numOfFilters;
7823
    if (numOfFilters > 0) {
H
hjxilinx 已提交
7824
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
7825 7826 7827 7828
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
7829 7830 7831
    }

    for (int32_t f = 0; f < numOfFilters; ++f) {
7832
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pMsg;
7833

7834 7835
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
7836 7837 7838

      pMsg += sizeof(SColumnFilterInfo);

7839 7840
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
7841

7842
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
7843 7844 7845 7846 7847
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

7848
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
7849
        pMsg += (pColFilter->len + 1);
7850
      } else {
7851 7852
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
7853 7854
      }

7855 7856
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
7857 7858 7859
    }
  }

7860 7861
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
7862 7863 7864 7865
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

7866
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
7867

7868
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
7869
    param->pExprMsg[i] = pExprMsg;
7870

7871
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
7872
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
7873 7874 7875 7876
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
7877

7878
    pMsg += sizeof(SSqlFuncMsg);
7879 7880

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
7881
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
7882 7883 7884 7885
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
7886
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
7887 7888 7889 7890 7891
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
7892 7893
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
7894
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
7895 7896
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
7897 7898 7899
      }
    }

7900
    pExprMsg = (SSqlFuncMsg *)pMsg;
7901
  }
7902

H
Haojun Liao 已提交
7903 7904
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
7905
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
7906

H
Haojun Liao 已提交
7907
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
7908
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
      pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag);
      pExprMsg->functionId = htons(pExprMsg->functionId);
      pExprMsg->numOfParams = htons(pExprMsg->numOfParams);

      pMsg += sizeof(SSqlFuncMsg);

      for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
        pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
        pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

        if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
          pExprMsg->arg[j].argValue.pz = pMsg;
          pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
        } else {
          pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
        }
      }

      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;
        }
      }

      pExprMsg = (SSqlFuncMsg *)pMsg;
    }
  }

7942
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
7943

H
hjxilinx 已提交
7944
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
7945 7946
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
7947 7948 7949
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
7950 7951

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

7955 7956
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
7957

7958 7959
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
7960

7961 7962
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
7963
    }
7964

H
hjxilinx 已提交
7965 7966
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
7967 7968
  }

7969 7970
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
7971
    pQueryMsg->fillVal = (uint64_t)(pMsg);
7972 7973

    int64_t *v = (int64_t *)pMsg;
7974
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
7975 7976
      v[i] = htobe64(v[i]);
    }
7977

7978
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
7979
  }
7980

7981
  if (pQueryMsg->numOfTags > 0) {
7982 7983
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
7984 7985 7986 7987
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

7988 7989
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
7990

7991 7992 7993 7994
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
7995

7996
      param->pTagColumnInfo[i] = *pTagCol;
7997
      pMsg += sizeof(SColumnInfo);
7998
    }
H
hjxilinx 已提交
7999
  }
8000

8001 8002
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
8003 8004
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
8005 8006 8007
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
8008 8009

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
8010 8011
    pMsg += pQueryMsg->tagCondLen;
  }
8012

8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023
  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 已提交
8024
  if (pQueryMsg->tbnameCondLen > 0) {
8025 8026
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
8027 8028 8029 8030
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

8031
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
8032
    pMsg += pQueryMsg->tbnameCondLen;
8033 8034
  }

D
dapan1121 已提交
8035 8036 8037 8038 8039
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

8040
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
8041

8042
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
8043 8044
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
8045
  }
8046

8047
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
8048 8049
         "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,
8050
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
8051
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
8052

8053
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
8054
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
8055 8056

_cleanup:
8057
  freeParam(param);
8058
  return code;
8059 8060
}

H
Haojun Liao 已提交
8061 8062
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
8063 8064

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
8065
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
8066 8067 8068
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
8069
    qError("qmsg:%p failed to create arithmetic expression string from:%s, reason: %s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz, tstrerror(code));
weixin_48148422's avatar
weixin_48148422 已提交
8070 8071 8072
    return code;
  } END_TRY

H
hjxilinx 已提交
8073
  if (pExprNode == NULL) {
8074
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
8075
    return TSDB_CODE_QRY_APP_ERROR;
8076
  }
8077

8078
  pArithExprInfo->pExpr = pExprNode;
8079 8080 8081
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
8082
int32_t createQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, SSqlFuncMsg **pExprMsg,
8083 8084
    SColumnInfo* pTagCols) {
  *pExprInfo = NULL;
H
hjxilinx 已提交
8085
  int32_t code = TSDB_CODE_SUCCESS;
8086

H
Haojun Liao 已提交
8087
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
8088
  if (pExprs == NULL) {
8089
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
8090 8091 8092 8093 8094
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
8095
  for (int32_t i = 0; i < numOfOutput; ++i) {
8096
    pExprs[i].base = *pExprMsg[i];
8097
    pExprs[i].bytes = 0;
8098 8099 8100 8101

    int16_t type = 0;
    int16_t bytes = 0;

8102
    // parse the arithmetic expression
8103
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
8104
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
8105

8106
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
8107
        tfree(pExprs);
8108
        return code;
8109 8110
      }

8111
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
8112
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
8113
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
8114 8115 8116
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
8117 8118 8119 8120
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
8121 8122
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
8123 8124
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

8125 8126
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
8127 8128 8129 8130 8131

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
8132
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
8133
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
8134
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
8135 8136 8137 8138 8139 8140 8141
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      } else {
        if (j < PRIMARYKEY_TIMESTAMP_COL_INDEX || j >= pQueryMsg->numOfCols) {
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      }
H
Haojun Liao 已提交
8142

dengyihao's avatar
dengyihao 已提交
8143
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
8144 8145 8146 8147
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
8148
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
8149

8150 8151
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
8152
      }
8153 8154
    }

S
TD-1057  
Shengliang Guan 已提交
8155
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
8156
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
8157
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
8158
      tfree(pExprs);
8159
      return TSDB_CODE_QRY_INVALID_MSG;
8160 8161
    }

8162
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
8163
      tagLen += pExprs[i].bytes;
8164
    }
8165

8166
    assert(isValidDataType(pExprs[i].type));
8167 8168 8169
  }

  // TODO refactor
H
Haojun Liao 已提交
8170
  for (int32_t i = 0; i < numOfOutput; ++i) {
8171 8172
    pExprs[i].base = *pExprMsg[i];
    int16_t functId = pExprs[i].base.functionId;
8173

8174
    if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
8175
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
8176
      if (j < 0 || j >= pQueryMsg->numOfCols) {
H
Haojun Liao 已提交
8177
        return TSDB_CODE_QRY_INVALID_MSG;
8178 8179 8180 8181 8182 8183 8184
      } else {
        SColumnInfo *pCol = &pQueryMsg->colList[j];
        int32_t ret =
            getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64,
                              &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, isSuperTable);
        assert(ret == TSDB_CODE_SUCCESS);
      }
8185 8186 8187
    }
  }

8188
  *pExprInfo = pExprs;
8189 8190 8191
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
8192 8193 8194 8195 8196 8197 8198 8199 8200 8201
int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo,
    SSqlFuncMsg **pExprMsg, SExprInfo *prevExpr) {
  *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 已提交
8202
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225

  for (int32_t i = 0; i < numOfOutput; ++i) {
    pExprs[i].base = *pExprMsg[i];
    pExprs[i].bytes = 0;

    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 已提交
8226 8227
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262
    }

    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

    assert(isValidDataType(pExprs[i].type));
  }

//  // TODO refactor
//  for (int32_t i = 0; i < numOfOutput; ++i) {
//    pExprs[i].base = *pExprMsg[i];
//    int16_t functId = pExprs[i].base.functionId;
//
//    if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
//      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
//      if (j < 0 || j >= pQueryMsg->numOfCols) {
//        return TSDB_CODE_QRY_INVALID_MSG;
//      } else {
//        SColumnInfo *pCol = &pQueryMsg->colList[j];
//        int32_t ret =
//            getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64,
//                              &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, isSuperTable);
//        assert(ret == TSDB_CODE_SUCCESS);
//      }
//    }
//  }

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
8263
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
8264 8265 8266 8267 8268
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
8269
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
8270
  if (pGroupbyExpr == NULL) {
8271
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
8272 8273 8274 8275 8276 8277 8278
    return NULL;
  }

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

8279 8280 8281 8282
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
8283

8284 8285 8286
  return pGroupbyExpr;
}

8287
static int32_t createFilterInfo(void *pQInfo, SQuery *pQuery) {
8288
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
8289
    if (pQuery->colList[i].numOfFilters > 0) {
8290 8291 8292 8293 8294 8295 8296 8297 8298
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
8299 8300 8301
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
8302 8303

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
8304
    if (pQuery->colList[i].numOfFilters > 0) {
8305 8306
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
8307
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
8308
      pFilterInfo->info = pQuery->colList[i];
8309

8310
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
8311
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
8312 8313 8314
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
8315 8316 8317

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
8318
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
8319 8320 8321 8322

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
S
slguan 已提交
8323
          qError("QInfo:%p invalid filter info", pQInfo);
8324
          return TSDB_CODE_QRY_INVALID_MSG;
8325 8326
        }

8327 8328 8329
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
          qError("QInfo:%p invalid filter info", pQInfo);
8330
          return TSDB_CODE_QRY_INVALID_MSG;
8331 8332
        }

8333
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
8334 8335 8336 8337 8338 8339 8340 8341 8342
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

8343
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
8344
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
8345

8346
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
8347
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
8348
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
8349 8350
      continue;
    }
8351

8352
    // todo opt performance
H
Haojun Liao 已提交
8353
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
8354
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
8355 8356
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
8357 8358
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
8359 8360 8361
          break;
        }
      }
H
Haojun Liao 已提交
8362 8363

      assert(f < pQuery->numOfCols);
8364 8365
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
8366
    } else {
8367 8368
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
8369 8370
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
8371 8372
          break;
        }
8373
      }
8374

Y
yihaoDeng 已提交
8375
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
8376 8377 8378 8379
    }
  }
}

H
Haojun Liao 已提交
8380 8381 8382
static void calResultBufSize(SQuery* pQuery) {
  const int32_t RESULT_MSG_MIN_SIZE  = 1024 * (1024 + 512);  // bytes
  const int32_t RESULT_MSG_MIN_ROWS  = 8192;
S
TD-1057  
Shengliang Guan 已提交
8383
  const float RESULT_THRESHOLD_RATIO = 0.85f;
H
Haojun Liao 已提交
8384

8385
  if (isProjQuery(pQuery)) {
8386
    int32_t numOfRes = RESULT_MSG_MIN_SIZE / pQuery->resultRowSize;
8387 8388 8389
    if (numOfRes < RESULT_MSG_MIN_ROWS) {
      numOfRes = RESULT_MSG_MIN_ROWS;
    }
H
Haojun Liao 已提交
8390

8391
    pQuery->rec.capacity  = numOfRes;
S
TD-1057  
Shengliang Guan 已提交
8392
    pQuery->rec.threshold = (int32_t)(numOfRes * RESULT_THRESHOLD_RATIO);
8393 8394
  } else {  // in case of non-prj query, a smaller output buffer will be used.
    pQuery->rec.capacity = 4096;
S
TD-1057  
Shengliang Guan 已提交
8395
    pQuery->rec.threshold = (int32_t)(pQuery->rec.capacity * RESULT_THRESHOLD_RATIO);
8396
  }
H
Haojun Liao 已提交
8397 8398
}

H
Haojun Liao 已提交
8399
SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr, SExprInfo *pExprs,
8400
                               SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery, char* sql) {
B
Bomin Zhang 已提交
8401 8402 8403
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

8404 8405
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
8406
    goto _cleanup_qinfo;
8407
  }
8408

B
Bomin Zhang 已提交
8409 8410
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
8411
  SQuery* pQuery = &pQInfo->query;
8412 8413
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
8414
  pQuery->tableGroupInfo  = *pTableGroupInfo;
8415
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
8416
  pQuery->numOfOutput     = numOfOutput;
8417 8418 8419
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
8420
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
8421
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
8422 8423
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
8424
  pQuery->pGroupbyExpr    = pGroupbyExpr;
8425
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
8426
  pQuery->fillType        = pQueryMsg->fillType;
8427
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
8428
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
8429 8430
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
H
Haojun Liao 已提交
8431

8432
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
8433
  if (pQuery->colList == NULL) {
8434
    goto _cleanup;
8435
  }
8436

8437 8438
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
8439
  for (int16_t i = 0; i < numOfCols; ++i) {
8440
    pQuery->colList[i] = pQueryMsg->colList[i];
8441
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
8442 8443 8444 8445 8446

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
8447
  }
8448

8449
  // calculate the result row size
8450 8451
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
8452 8453 8454 8455 8456 8457
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
8458
  }
8459

8460
  doUpdateExprColumnIndex(pQuery);
8461
  int32_t ret = createFilterInfo(pQInfo, pQuery);
8462
  if (ret != TSDB_CODE_SUCCESS) {
8463
    goto _cleanup;
8464 8465 8466
  }

  // prepare the result buffer
8467
  pQuery->sdata = (tFilePage **)calloc(pQuery->numOfOutput, POINTER_BYTES);
8468
  if (pQuery->sdata == NULL) {
8469
    goto _cleanup;
8470 8471
  }

H
Haojun Liao 已提交
8472
  calResultBufSize(pQuery);
8473

8474
  for (int32_t col = 0; col < pQuery->numOfOutput; ++col) {
8475
    // allocate additional memory for interResults that are usually larger then final results
H
Haojun Liao 已提交
8476
    // TODO refactor
H
Haojun Liao 已提交
8477 8478 8479 8480 8481 8482 8483 8484
    int16_t bytes = 0;
    if (pQuery->pExpr2 == NULL || col > pQuery->numOfExpr2) {
      bytes = pExprs[col].bytes;
    } else {
      bytes = MAX(pQuery->pExpr2[col].bytes, pExprs[col].bytes);
    }

    size_t size = (size_t)((pQuery->rec.capacity + 1) * bytes + pExprs[col].interBytes + sizeof(tFilePage));
8485
    pQuery->sdata[col] = (tFilePage *)calloc(1, size);
8486
    if (pQuery->sdata[col] == NULL) {
8487
      goto _cleanup;
8488 8489 8490
    }
  }

8491
  if (pQuery->fillType != TSDB_FILL_NONE) {
8492 8493
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
8494
      goto _cleanup;
8495 8496 8497
    }

    // the first column is the timestamp
8498
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
8499 8500
  }

dengyihao's avatar
dengyihao 已提交
8501 8502 8503
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
8504
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
8505

8506 8507 8508
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
8509
  }
H
Haojun Liao 已提交
8510

H
Haojun Liao 已提交
8511
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
8512 8513 8514 8515
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

H
Haojun Liao 已提交
8516
  // NOTE: pTableCheckInfo need to update the query time range and the lastKey info
8517
  pQInfo->arrTableIdInfo = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
8518
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
8519
  pQInfo->rspContext = NULL;
8520
  pQInfo->sql = sql;
8521
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
8522
  tsem_init(&pQInfo->ready, 0, 0);
8523 8524 8525 8526 8527

  pQuery->pos = -1;
  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
8528 8529
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  pQuery->queryWindowIdentical = true;
8530 8531
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

8532
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
8533

H
Haojun Liao 已提交
8534
  int32_t index = 0;
H
hjxilinx 已提交
8535
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
8536
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
8537

H
Haojun Liao 已提交
8538
    size_t s = taosArrayGetSize(pa);
8539
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
8540 8541 8542
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
8543

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

H
hjxilinx 已提交
8546
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
8547
      STableKeyInfo* info = taosArrayGet(pa, j);
8548

8549
      window.skey = info->lastKey;
8550
      if (info->lastKey != pQuery->window.skey) {
H
Haojun Liao 已提交
8551
        pQInfo->query.queryWindowIdentical = false;
8552 8553 8554
      }

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
8555
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
8556 8557 8558
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
8559

8560
      item->groupIndex = i;
H
hjxilinx 已提交
8561
      taosArrayPush(p1, &item);
8562 8563

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
8564
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
8565
      index += 1;
H
hjxilinx 已提交
8566 8567
    }
  }
8568

8569
  colIdCheck(pQuery);
8570

8571
  // todo refactor
H
Haojun Liao 已提交
8572
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
Y
yihaoDeng 已提交
8573
   
8574
  qDebug("qmsg:%p QInfo:%p created", pQueryMsg, pQInfo);
8575 8576
  return pQInfo;

B
Bomin Zhang 已提交
8577
_cleanup_qinfo:
H
Haojun Liao 已提交
8578
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
8579

8580 8581 8582 8583
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
8584

S
TD-1848  
Shengliang Guan 已提交
8585
  tfree(pTagCols);
B
Bomin Zhang 已提交
8586 8587 8588
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
8589 8590
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
8591 8592
    }
  }
H
Haojun Liao 已提交
8593

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

8596
_cleanup:
dengyihao's avatar
dengyihao 已提交
8597
  freeQInfo(pQInfo);
8598 8599 8600
  return NULL;
}

H
Haojun Liao 已提交
8601
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
8602 8603 8604 8605
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
8606

H
hjxilinx 已提交
8607 8608 8609 8610
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
8611
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
8612 8613 8614
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
8615
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
8616
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
8617 8618

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
8619
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
8620

8621
  STSBuf *pTsBuf = NULL;
8622
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
8623
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
8624
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
8625

8626 8627
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
8628

dengyihao's avatar
dengyihao 已提交
8629
    UNUSED(ret);
H
hjxilinx 已提交
8630
  }
8631

8632 8633 8634 8635 8636
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
  }

Y
TD-1665  
yihaoDeng 已提交
8637
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
8638

8639 8640
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
8641
    qDebug("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey,
8642
           pQuery->window.ekey, pQuery->order.order);
8643
    setQueryStatus(pQuery, QUERY_COMPLETED);
H
Haojun Liao 已提交
8644
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
8645
    // todo free memory
8646 8647
    return TSDB_CODE_SUCCESS;
  }
8648

H
Haojun Liao 已提交
8649
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
8650
    qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo);
8651 8652 8653
    setQueryStatus(pQuery, QUERY_COMPLETED);
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
8654 8655

  // filter the qualified
8656
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
8657 8658
    goto _error;
  }
8659

H
hjxilinx 已提交
8660 8661 8662 8663
  return code;

_error:
  // table query ref will be decrease during error handling
8664
  freeQInfo(pQInfo);
H
hjxilinx 已提交
8665 8666 8667
  return code;
}

H
Haojun Liao 已提交
8668
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
8669
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
8670 8671
      return;
    }
H
Haojun Liao 已提交
8672

B
Bomin Zhang 已提交
8673 8674 8675 8676 8677
    for (int32_t i = 0; i < numOfFilters; i++) {
      if (pFilter[i].filterstr) {
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
8678

B
Bomin Zhang 已提交
8679 8680 8681
    free(pFilter);
}

H
Haojun Liao 已提交
8682 8683
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
8684
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705
    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 已提交
8706 8707 8708 8709 8710 8711 8712 8713
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 已提交
8714
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
8715 8716 8717 8718 8719 8720 8721
    }
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
8722
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
8723 8724 8725
  if (!isValidQInfo(pQInfo)) {
    return;
  }
8726

8727
  qDebug("QInfo:%p start to free QInfo", pQInfo);
8728

H
Haojun Liao 已提交
8729
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
8730
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
8731
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
8732

H
Haojun Liao 已提交
8733 8734 8735 8736
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->sdata != NULL) {
      for (int32_t col = 0; col < pQuery->numOfOutput; ++col) {
S
TD-1848  
Shengliang Guan 已提交
8737
        tfree(pQuery->sdata[col]);
H
Haojun Liao 已提交
8738
      }
S
TD-1848  
Shengliang Guan 已提交
8739
      tfree(pQuery->sdata);
H
hjxilinx 已提交
8740
    }
8741

H
Haojun Liao 已提交
8742
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
8743
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
8744
    }
8745

H
Haojun Liao 已提交
8746 8747 8748
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
8749
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
8750
      }
H
hjxilinx 已提交
8751
    }
8752

H
Haojun Liao 已提交
8753 8754
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
8755

S
TD-1848  
Shengliang Guan 已提交
8756 8757
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
8758 8759 8760 8761 8762 8763

    if (pQuery->colList != NULL) {
      for (int32_t i = 0; i < pQuery->numOfCols; i++) {
        SColumnInfo *column = pQuery->colList + i;
        freeColumnFilterInfo(column->filters, column->numOfFilters);
      }
S
TD-1848  
Shengliang Guan 已提交
8764
      tfree(pQuery->colList);
H
Haojun Liao 已提交
8765 8766
    }

H
Haojun Liao 已提交
8767 8768 8769 8770
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
8771
  }
8772

H
Haojun Liao 已提交
8773
  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
H
Haojun Liao 已提交
8774

S
TD-1848  
Shengliang Guan 已提交
8775
  tfree(pQInfo->pBuf);
8776 8777
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
8778
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
8779
  taosHashCleanup(pQInfo->arrTableIdInfo);
8780

H
Haojun Liao 已提交
8781
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
8782

8783
  pQInfo->signature = 0;
8784

8785
  qDebug("QInfo:%p QInfo is freed", pQInfo);
8786

S
TD-1848  
Shengliang Guan 已提交
8787
  tfree(pQInfo);
H
hjxilinx 已提交
8788 8789
}

H
Haojun Liao 已提交
8790
size_t getResultSize(SQInfo *pQInfo, int64_t *numOfRows) {
8791 8792
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
hjxilinx 已提交
8793 8794 8795 8796 8797
  /*
   * get the file size and set the numOfRows to be the file size, since for tsComp query,
   * the returned row size is equalled to 1
   * TODO handle the case that the file is too large to send back one time
   */
H
Haojun Liao 已提交
8798
  if (isTsCompQuery(pQuery) && (*numOfRows) > 0) {
D
fix bug  
dapan1121 已提交
8799
    struct stat fStat;
8800 8801
    FILE *f = *(FILE **)pQuery->sdata[0]->data;
    if ((f != NULL) && (fstat(fileno(f), &fStat) == 0)) {
D
fix bug  
dapan1121 已提交
8802 8803
      *numOfRows = fStat.st_size;
      return fStat.st_size;
H
hjxilinx 已提交
8804
    } else {
8805
      qError("QInfo:%p failed to get file info, file:%p, reason:%s", pQInfo, f, strerror(errno));
H
hjxilinx 已提交
8806 8807 8808
      return 0;
    }
  } else {
8809
    return (size_t)(pQuery->resultRowSize * (*numOfRows));
8810
  }
H
hjxilinx 已提交
8811
}
8812

H
Haojun Liao 已提交
8813
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
8814 8815
  // the remained number of retrieved rows, not the interpolated result
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
8816

H
hjxilinx 已提交
8817
  // load data from file to msg buffer
H
Haojun Liao 已提交
8818
  if (isTsCompQuery(pQuery)) {
D
fix bug  
dapan1121 已提交
8819

8820
    FILE *f = *(FILE **)pQuery->sdata[0]->data;  // TODO refactor
8821

H
hjxilinx 已提交
8822
    // make sure file exist
D
fix bug  
dapan1121 已提交
8823 8824
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
8825

D
fix bug  
dapan1121 已提交
8826
      qDebug("QInfo:%p ts comp data return, file:%p, size:%"PRId64, pQInfo, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
8827 8828
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
8829
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
8830
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
8831 8832
          assert(0);
        }
H
Haojun Liao 已提交
8833
      } else {
8834
        UNUSED(s);
D
dapan1121 已提交
8835 8836 8837 8838 8839 8840 8841 8842
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        
        assert(0);
dengyihao's avatar
dengyihao 已提交
8843
      }
H
Haojun Liao 已提交
8844

D
fix bug  
dapan1121 已提交
8845 8846
      fclose(f);
      *(FILE **)pQuery->sdata[0]->data = NULL;
H
hjxilinx 已提交
8847
    }
8848

H
hjxilinx 已提交
8849 8850 8851 8852
    // all data returned, set query over
    if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) {
      setQueryStatus(pQuery, QUERY_OVER);
    }
H
hjxilinx 已提交
8853
  } else {
S
TD-1057  
Shengliang Guan 已提交
8854
    doCopyQueryResultToMsg(pQInfo, (int32_t)pQuery->rec.rows, data);
8855
  }
8856

8857
  pQuery->rec.total += pQuery->rec.rows;
8858
  qDebug("QInfo:%p current numOfRes rows:%" PRId64 ", total:%" PRId64, pQInfo, pQuery->rec.rows, pQuery->rec.total);
8859

8860
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pQuery->rec.total) {
8861
    qDebug("QInfo:%p results limitation reached, limitation:%"PRId64, pQInfo, pQuery->limit.limit);
8862 8863
    setQueryStatus(pQuery, QUERY_OVER);
  }
8864

H
hjxilinx 已提交
8865
  return TSDB_CODE_SUCCESS;
8866 8867
}

H
Haojun Liao 已提交
8868
bool doBuildResCheck(SQInfo* pQInfo) {
8869 8870 8871 8872 8873
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
8874
  buildRes = needBuildResAfterQueryComplete(pQInfo);
8875

H
Haojun Liao 已提交
8876 8877
  // 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 已提交
8878
  assert(pQInfo->owner == taosGetSelfPthreadId());
8879
  pQInfo->owner = 0;
H
Haojun Liao 已提交
8880

H
Haojun Liao 已提交
8881
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
8882

8883
  // used in retrieve blocking model.
H
Haojun Liao 已提交
8884
  tsem_post(&pQInfo->ready);
8885 8886 8887
  return buildRes;
}

H
Haojun Liao 已提交
8888 8889 8890 8891
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
8892 8893
  }

8894
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
8895
    memcpy(output, val, varDataTLen(val));
8896
  } else {
H
Haojun Liao 已提交
8897
    memcpy(output, val, bytes);
8898 8899 8900
  }
}

H
Haojun Liao 已提交
8901
void buildTagQueryResult(SQInfo* pQInfo) {
H
hjxilinx 已提交
8902 8903
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *          pQuery = pRuntimeEnv->pQuery;
8904

H
Haojun Liao 已提交
8905
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
8906
  assert(numOfGroup == 0 || numOfGroup == 1);
8907

H
Haojun Liao 已提交
8908
  if (numOfGroup == 0) {
8909 8910
    return;
  }
8911

H
Haojun Liao 已提交
8912
  SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
8913

H
Haojun Liao 已提交
8914
  size_t num = taosArrayGetSize(pa);
H
Haojun Liao 已提交
8915
  assert(num == pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
8916

H
Haojun Liao 已提交
8917
  int32_t count = 0;
H
Haojun Liao 已提交
8918
  int32_t functionId = pQuery->pExpr1[0].base.functionId;
8919 8920
  if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id
    assert(pQuery->numOfOutput == 1);
8921

H
Haojun Liao 已提交
8922
    SExprInfo* pExprInfo = &pQuery->pExpr1[0];
8923
    int32_t rsize = pExprInfo->bytes;
H
Haojun Liao 已提交
8924
    count = 0;
8925

H
Haojun Liao 已提交
8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936
    int16_t bytes = pExprInfo->bytes;
    int16_t type = pExprInfo->type;

    for(int32_t i = 0; i < pQuery->numOfTags; ++i) {
      if (pQuery->tagColList[i].colId == pExprInfo->base.colInfo.colId) {
        bytes = pQuery->tagColList[i].bytes;
        type = pQuery->tagColList[i].type;
        break;
      }
    }

H
Haojun Liao 已提交
8937 8938
    while(pRuntimeEnv->tableIndex < num && count < pQuery->rec.capacity) {
      int32_t i = pRuntimeEnv->tableIndex++;
8939
      STableQueryInfo *item = taosArrayGetP(pa, i);
8940

8941
      char *output = pQuery->sdata[0]->data + count * rsize;
8942
      varDataSetLen(output, rsize - VARSTR_HEADER_SIZE);
8943

8944
      output = varDataVal(output);
H
Haojun Liao 已提交
8945
      STableId* id = TSDB_TABLEID(item->pTable);
8946

8947 8948 8949
      *(int16_t *)output = 0;
      output += sizeof(int16_t);

H
Haojun Liao 已提交
8950 8951
      *(int64_t *)output = id->uid;  // memory align problem, todo serialize
      output += sizeof(id->uid);
8952

H
Haojun Liao 已提交
8953 8954
      *(int32_t *)output = id->tid;
      output += sizeof(id->tid);
8955

H
Haojun Liao 已提交
8956 8957
      *(int32_t *)output = pQuery->vgId;
      output += sizeof(pQuery->vgId);
8958

8959
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
8960
        char* data = tsdbGetTableName(item->pTable);
8961
        memcpy(output, data, varDataTLen(data));
H
[td-90]  
Haojun Liao 已提交
8962
      } else {
8963 8964
        char* data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
        doSetTagValueToResultBuf(output, data, type, bytes);
H
[td-90]  
Haojun Liao 已提交
8965
      }
8966

H
Haojun Liao 已提交
8967
      count += 1;
8968
    }
8969

8970
    qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pQInfo, count);
8971

H
Haojun Liao 已提交
8972 8973 8974 8975
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    *(int64_t*) pQuery->sdata[0]->data = num;

    count = 1;
H
Haojun Liao 已提交
8976
    SET_STABLE_QUERY_OVER(pRuntimeEnv);
8977
    qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pQInfo, count);
8978
  } else {  // return only the tags|table name etc.
H
Haojun Liao 已提交
8979
    count = 0;
8980
    SSchema* tbnameSchema = tGetTbnameColumnSchema();
8981

S
TD-1057  
Shengliang Guan 已提交
8982
    int32_t maxNumOfTables = (int32_t)pQuery->rec.capacity;
8983
    if (pQuery->limit.limit >= 0 && pQuery->limit.limit < pQuery->rec.capacity) {
S
TD-1057  
Shengliang Guan 已提交
8984
      maxNumOfTables = (int32_t)pQuery->limit.limit;
8985 8986
    }

H
Haojun Liao 已提交
8987 8988
    while(pRuntimeEnv->tableIndex < num && count < maxNumOfTables) {
      int32_t i = pRuntimeEnv->tableIndex++;
8989

8990 8991 8992 8993 8994 8995
      // discard current result due to offset
      if (pQuery->limit.offset > 0) {
        pQuery->limit.offset -= 1;
        continue;
      }

H
Haojun Liao 已提交
8996
      SExprInfo* pExprInfo = pQuery->pExpr1;
8997
      STableQueryInfo* item = taosArrayGetP(pa, i);
8998

8999 9000
      char *data = NULL, *dst = NULL;
      int16_t type = 0, bytes = 0;
9001
      for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
9002
        // not assign value in case of user defined constant output column
Y
TD-1230  
yihaoDeng 已提交
9003
        if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) {
H
Haojun Liao 已提交
9004 9005
          continue;
        }
9006

9007
        if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
9008 9009
          bytes = tbnameSchema->bytes;
          type = tbnameSchema->type;
9010 9011

          data = tsdbGetTableName(item->pTable);
9012
          dst = pQuery->sdata[j]->data + count * tbnameSchema->bytes;
9013 9014 9015
        } else {
          type = pExprInfo[j].type;
          bytes = pExprInfo[j].bytes;
9016

9017 9018
          data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes);
          dst = pQuery->sdata[j]->data + count * pExprInfo[j].bytes;
9019

9020
        }
9021 9022

        doSetTagValueToResultBuf(dst, data, type, bytes);
H
hjxilinx 已提交
9023
      }
H
Haojun Liao 已提交
9024
      count += 1;
H
hjxilinx 已提交
9025
    }
9026

9027
    qDebug("QInfo:%p create tag values results completed, rows:%d", pQInfo, count);
H
hjxilinx 已提交
9028
  }
9029

H
Haojun Liao 已提交
9030
  pQuery->rec.rows = count;
H
hjxilinx 已提交
9031
  setQueryStatus(pQuery, QUERY_COMPLETED);
H
hjxilinx 已提交
9032 9033
}

H
Haojun Liao 已提交
9034
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
9035 9036 9037 9038
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
9039
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
9040 9041
}

H
Haojun Liao 已提交
9042
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
9043
  int64_t t = getQuerySupportBufSize(numOfTables);
9044
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
9045
    return TSDB_CODE_SUCCESS;
9046
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
9047 9048

    while(1) {
9049
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
9050 9051
      int64_t remain = s - t;
      if (remain >= 0) {
9052
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064
          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 已提交
9065
void releaseQueryBuf(size_t numOfTables) {
9066
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
9067 9068 9069 9070 9071 9072
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
9073
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
9074
}