qExecutor.c 236.2 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

30 31 32 33 34
/**
 * check if the primary column is load by default, otherwise, the program will
 * forced to load primary column explicitly.
 */

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

40
#define GET_COL_DATA_POS(query, index, step) ((query)->pos + (index) * (step))
41
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
42

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

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

50
enum {
51 52
  TS_JOIN_TS_EQUAL       = 0,
  TS_JOIN_TS_NOT_EQUALS  = 1,
53 54 55
  TS_JOIN_TAG_NOT_EQUALS = 2,
};

56
typedef struct {
57 58 59 60 61
  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;
62 63
} SQueryStatusInfo;

H
Haojun Liao 已提交
64
#if 0
H
Haojun Liao 已提交
65
static UNUSED_FUNC void *u_malloc (size_t __size) {
H
Haojun Liao 已提交
66
  uint32_t v = rand();
H
Haojun Liao 已提交
67 68

  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
69 70
    return NULL;
  } else {
H
Haojun Liao 已提交
71
    return malloc(__size);
H
Haojun Liao 已提交
72
  }
H
Haojun Liao 已提交
73 74
}

H
Haojun Liao 已提交
75 76
static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) {
  uint32_t v = rand();
H
Haojun Liao 已提交
77
  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
78 79 80 81 82 83
    return NULL;
  } else {
    return calloc(num, __size);
  }
}

H
Haojun Liao 已提交
84 85 86 87 88 89 90 91 92
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 已提交
93
#define calloc  u_calloc
H
Haojun Liao 已提交
94
#define malloc  u_malloc
H
Haojun Liao 已提交
95
#define realloc u_realloc
H
Haojun Liao 已提交
96
#endif
H
Haojun Liao 已提交
97

98
#define CLEAR_QUERY_STATUS(q, st)   ((q)->status &= (~(st)))
H
Haojun Liao 已提交
99
#define GET_NUM_OF_TABLEGROUP(q)    taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
100
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)
H
Haojun Liao 已提交
101

H
Haojun Liao 已提交
102
int32_t getMaximumIdleDurationSec() {
103 104
  return tsShellActivityTimer * 2;
}
105

106 107
static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) {
  int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
108 109 110
  if (pQuery->interval.intervalUnit != 'n' && pQuery->interval.intervalUnit != 'y') {
    tw->skey += pQuery->interval.sliding * factor;
    tw->ekey = tw->skey + pQuery->interval.interval - 1;
111 112 113
    return;
  }

114
  int64_t key = tw->skey / 1000, interval = pQuery->interval.interval;
115 116 117
  if (pQuery->precision == TSDB_TIME_PRECISION_MICRO) {
    key /= 1000;
  }
118
  if (pQuery->interval.intervalUnit == 'y') {
119 120
    interval *= 12;
  }
121 122 123 124 125

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

S
Shengliang Guan 已提交
126
  int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
127 128 129 130
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->skey = mktime(&tm) * 1000L;

S
Shengliang Guan 已提交
131
  mon = (int)(mon + interval);
132 133 134 135 136 137 138 139 140 141
  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;
}
142
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
143

H
Haojun Liao 已提交
144 145
static void setResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
    int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
146

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

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

H
Haojun Liao 已提交
152
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
153 154
static bool hasMainOutput(SQuery *pQuery);

155
//static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
156
static void releaseQueryBuf(size_t numOfTables);
157
static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order);
H
Haojun Liao 已提交
158
static STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win);
159
static STableIdInfo createTableIdInfo(SQuery* pQuery);
160

H
Haojun Liao 已提交
161 162
static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream);

H
Haojun Liao 已提交
163
static int32_t getNumOfScanTimes(SQuery* pQuery);
H
Haojun Liao 已提交
164 165
static bool isFixedOutputQuery(SQuery* pQuery);

H
Haojun Liao 已提交
166 167 168
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime);
static SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime);
static SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, bool loadExternalRows);
H
Haojun Liao 已提交
169

H
Haojun Liao 已提交
170
static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
171 172 173
static SOperatorInfo* createArithOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
static SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
static SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream);
H
Haojun Liao 已提交
174
static SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
175
static SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
176 177 178
static SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
static SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
static SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
179
static SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
180

H
Haojun Liao 已提交
181 182 183 184 185
static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput);
static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput);
static void destroyArithOperatorInfo(void* param, int32_t numOfOutput);

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

H
Haojun Liao 已提交
188
static int32_t getGroupbyColumnData_rv(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock);
H
Haojun Liao 已提交
189

H
Haojun Liao 已提交
190
static int32_t setGroupResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo,
H
Haojun Liao 已提交
191
                                          SQLFunctionCtx * pCtx, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex, int32_t* offset);
H
Haojun Liao 已提交
192 193 194
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 已提交
195
static bool isPointInterpoQuery(SQuery *pQuery);
H
Haojun Liao 已提交
196

H
Haojun Liao 已提交
197 198
// setup the output buffer for each operator
static SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows) {
H
Haojun Liao 已提交
199
  SSDataBlock *res = calloc(1, sizeof(SSDataBlock));
H
Haojun Liao 已提交
200
  res->info.numOfCols = numOfOutput;
H
Haojun Liao 已提交
201

H
Haojun Liao 已提交
202 203
  res->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
204
    SColumnInfoData idata = {0};
H
Haojun Liao 已提交
205 206 207
    idata.info.type = pExpr[i].type;
    idata.info.bytes = pExpr[i].bytes;
    idata.info.colId = pExpr[i].base.resColId;
H
Haojun Liao 已提交
208
    idata.pData = calloc(numOfRows, idata.info.bytes);
209

H
Haojun Liao 已提交
210 211
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
212 213

  return res;
H
Haojun Liao 已提交
214 215
}

H
Haojun Liao 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
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;
}

233
bool doFilterData(SQuery *pQuery, int32_t elemPos) {
234 235
  for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
    SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
236

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

239 240
    bool qualified = false;
    for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
241
      SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
242

H
Haojun Liao 已提交
243 244
      bool isnull = isNull(pElem, pFilterInfo->info.type);
      if (isnull) {
245
        if (pFilterElem->fp == isNullOperator) {
H
Haojun Liao 已提交
246 247 248 249 250 251
          qualified = true;
          break;
        } else {
          continue;
        }
      } else {
252
        if (pFilterElem->fp == notNullOperator) {
H
Haojun Liao 已提交
253 254
          qualified = true;
          break;
255
        } else if (pFilterElem->fp == isNullOperator) {
H
Haojun Liao 已提交
256 257 258 259
          continue;
        }
      }

260
      if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo->info.type)) {
261 262 263 264
        qualified = true;
        break;
      }
    }
265

266 267 268 269
    if (!qualified) {
      return false;
    }
  }
270

271 272 273
  return true;
}

H
Haojun Liao 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
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;
}

H
Haojun Liao 已提交
301 302 303 304 305 306 307
static void setNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t j = 0; j < numOfOutput; ++j) {
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    pResInfo->numOfRes = 0;
  }
}

308
bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) {
309 310 311
  if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) {
    return false;
  }
312

313
  for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) {
314
    SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i);
Y
TD-1230  
yihaoDeng 已提交
315
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
316
      //make sure the normal column locates at the second position if tbname exists in group by clause
317
      if (pGroupbyExpr->numOfGroupCols > 1) {
318
        assert(pColIndex->colIndex > 0);
319
      }
320

321 322 323
      return true;
    }
  }
324

325 326 327
  return false;
}

328 329 330 331 332 333 334 335 336 337 338
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;
}

339 340
int16_t getGroupbyColumnType(SQuery *pQuery, SSqlGroupbyExpr *pGroupbyExpr) {
  assert(pGroupbyExpr != NULL);
341

342 343
  int32_t colId = -2;
  int16_t type = TSDB_DATA_TYPE_NULL;
344

345
  for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) {
346
    SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i);
Y
TD-1230  
yihaoDeng 已提交
347
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
348 349 350 351
      colId = pColIndex->colId;
      break;
    }
  }
352

353
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
354 355
    if (colId == pQuery->colList[i].colId) {
      type = pQuery->colList[i].type;
356 357 358
      break;
    }
  }
359

360 361 362
  return type;
}

H
Haojun Liao 已提交
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
static bool isSelectivityWithTagsQuery(SQLFunctionCtx *pCtx, int32_t numOfOutput) {
  bool    hasTags = false;
  int32_t numOfSelectivity = 0;

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

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

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

H
Haojun Liao 已提交
382
static bool isProjQuery(SQuery *pQuery) {
383
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
384
    int32_t functId = pQuery->pExpr1[i].base.functionId;
385 386 387 388 389 390 391 392
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

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

395
static bool isTopBottomQuery(SQuery *pQuery) {
396
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
397
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
398 399 400
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
401

402 403 404 405
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      return true;
    }
  }
406

407 408 409
  return false;
}

410 411 412
static bool timeWindowInterpoRequired(SQuery *pQuery) {
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
413
    if (functionId == TSDB_FUNC_TWA || functionId == TSDB_FUNC_INTERP) {
414 415 416 417 418 419 420
      return true;
    }
  }

  return false;
}

H
Haojun Liao 已提交
421
static bool hasTagValOutput(SQuery* pQuery) {
H
Haojun Liao 已提交
422
  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
H
Haojun Liao 已提交
423 424 425 426
  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 已提交
427
      SExprInfo *pLocalExprInfo = &pQuery->pExpr1[idx];
H
Haojun Liao 已提交
428 429 430 431 432 433 434 435 436 437 438

      // 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 已提交
439 440 441 442 443 444 445 446 447 448 449 450
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;
}

H
Haojun Liao 已提交
451
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
452
                                             int16_t bytes, bool masterscan, uint64_t uid) {
453
  bool existed = false;
H
Haojun Liao 已提交
454
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

  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;
        }
      }
    }
474
  } else {
475 476
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
477
    }
478
  }
479

480
  if (!existed) {
H
Haojun Liao 已提交
481
    // TODO refactor
H
Haojun Liao 已提交
482
    // more than the capacity, reallocate the resources
H
Haojun Liao 已提交
483
    if (pResultRowInfo->size >= pResultRowInfo->capacity) {
H
Haojun Liao 已提交
484
      int64_t newCapacity = 0;
H
Haojun Liao 已提交
485 486
      if (pResultRowInfo->capacity > 10000) {
        newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25);
487
      } else {
H
Haojun Liao 已提交
488
        newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5);
489 490
      }

H
Haojun Liao 已提交
491
      char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES));
492 493
      if (t == NULL) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
494
      }
495

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

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

H
Haojun Liao 已提交
501
      pResultRowInfo->capacity = (int32_t)newCapacity;
502
    }
503

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

519
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
520
    pResultRowInfo->curIndex = pResultRowInfo->size++;
521
  }
522

523
  // too many time window in query
H
Haojun Liao 已提交
524
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
525 526 527
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
528
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
529 530 531
}

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

H
Haojun Liao 已提交
535 536
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
   if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
537 538 539 540 541 542
     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);
     }

H
Haojun Liao 已提交
543
     pResultRowInfo->prevSKey = w.skey;
H
Haojun Liao 已提交
544
   } else {
H
Haojun Liao 已提交
545
    w.skey = pResultRowInfo->prevSKey;
H
Haojun Liao 已提交
546 547
   }

548
    if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
549
      w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
550
    } else {
551
      w.ekey = w.skey + pQuery->interval.interval - 1;
552
    }
553
  } else {
H
Haojun Liao 已提交
554 555
    int32_t slot = curTimeWindowIndex(pResultRowInfo);
    SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot);
556
    w = pWindowRes->win;
557
  }
558

559
  if (w.skey > ts || w.ekey < ts) {
560 561 562
    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;
563 564
    } else {
      int64_t st = w.skey;
565

566
      if (st > ts) {
567
        st -= ((st - ts + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
568
      }
569

570
      int64_t et = st + pQuery->interval.interval - 1;
571
      if (et < ts) {
572
        st += ((ts - et + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
573
      }
574

575
      w.skey = st;
576
      w.ekey = w.skey + pQuery->interval.interval - 1;
577
    }
578
  }
579

580 581 582 583 584 585 586
  /*
   * 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;
  }
587

588 589 590
  return w;
}

H
Haojun Liao 已提交
591 592
// a new buffer page for each table. Needs to opt this design
static int32_t addNewWindowResultBuf(SResultRow *pWindowRes, SDiskbasedResultBuf *pResultBuf, int32_t tid, uint32_t size) {
593
  if (pWindowRes->pageId != -1) {
594 595
    return 0;
  }
596

597
  tFilePage *pData = NULL;
598

599 600
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
601
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
602

H
Haojun Liao 已提交
603
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
604
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
605
  } else {
H
Haojun Liao 已提交
606 607 608
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
609

H
Haojun Liao 已提交
610
    if (pData->num + size > pResultBuf->pageSize) {
H
Haojun Liao 已提交
611 612
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
613
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
614
      if (pData != NULL) {
615
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
616 617 618
      }
    }
  }
619

620 621 622
  if (pData == NULL) {
    return -1;
  }
623

624
  // set the number of rows in current disk page
625 626
  if (pWindowRes->pageId == -1) {  // not allocated yet, allocate new buffer
    pWindowRes->pageId = pageId;
H
Haojun Liao 已提交
627
    pWindowRes->offset = pData->num;
H
Haojun Liao 已提交
628

H
Haojun Liao 已提交
629
    pData->num += size;
630
    assert(pWindowRes->pageId >= 0);
631
  }
632

633 634 635
  return 0;
}

636
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
637
                                       bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
638
                                       int32_t numOfOutput, int32_t* rowCellInfoOffset) {
639 640
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
641

642
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
643
  if (pResultRow == NULL) {
644 645
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
646
  }
647

648
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
649
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
650 651

    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQuery->intermediateResultRowSize);
H
Haojun Liao 已提交
652
    if (ret != TSDB_CODE_SUCCESS) {
653 654 655
      return -1;
    }
  }
656

657
  // set time window for current result
H
Haojun Liao 已提交
658
  pResultRow->win = (*win);
659
  *pResult = pResultRow;
H
Haojun Liao 已提交
660
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
661

662 663 664
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
665
static UNUSED_FUNC bool getResultRowStatus(SResultRowInfo *pWindowResInfo, int32_t slot) {
666
  assert(slot >= 0 && slot < pWindowResInfo->size);
667
  return pWindowResInfo->pResult[slot]->closed;
668 669
}

670 671 672 673 674 675 676 677 678 679 680 681 682 683
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 已提交
684
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
685 686 687 688 689 690 691 692
  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 已提交
693
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
694 695
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
696

H
Haojun Liao 已提交
697 698 699 700
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
701

H
Haojun Liao 已提交
702 703 704 705 706 707 708 709 710 711 712 713
      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;
      }
714 715
    }
  }
716

H
Haojun Liao 已提交
717
  assert(forwardStep > 0);
718 719 720
  return forwardStep;
}

721
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
722
  int64_t skey = TSKEY_INITIAL_VAL;
723 724 725
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
726
    if (pResult->closed) {
727
      break;
H
Haojun Liao 已提交
728 729
    }

730
    // new closed result rows
731 732 733 734 735 736 737 738 739 740
    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 已提交
741
    } else {
742 743 744 745 746
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
747 748 749
    }
  }

750
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
751
  if (skey == TSKEY_INITIAL_VAL) {
752
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
753 754
  } else {

755 756 757 758 759
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
760
    }
761

D
fix bug  
dapan1121 已提交
762
    if (i == pResultRowInfo->size - 1) {
763
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
764 765 766 767
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

768
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
769
  }
770
}
771

H
Haojun Liao 已提交
772
static UNUSED_FUNC void updateResultRowIndex(SResultRowInfo* pResultRowInfo, STableQueryInfo* pTableQueryInfo, bool ascQuery, bool timeWindowInterpo) {
773
  if ((pTableQueryInfo->lastKey > pTableQueryInfo->win.ekey && ascQuery) || (pTableQueryInfo->lastKey < pTableQueryInfo->win.ekey && (!ascQuery))) {
774 775 776
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
777
    int32_t step = ascQuery? 1:-1;
778
    doUpdateResultRowIndex(pResultRowInfo, pTableQueryInfo->lastKey - step, ascQuery, timeWindowInterpo);
779
  }
780 781 782
}

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

H
Haojun Liao 已提交
786
  int32_t num   = -1;
787
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
788
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
789

H
hjxilinx 已提交
790
  STableQueryInfo* item = pQuery->current;
791

792 793
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (ekey < pDataBlockInfo->window.ekey) {
794
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
795 796
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
797 798
      }
    } else {
799
      num = pDataBlockInfo->rows - startPos;
800
      if (updateLastKey) {
H
hjxilinx 已提交
801
        item->lastKey = pDataBlockInfo->window.ekey + step;
802 803 804 805
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
806
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
807 808
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
809 810 811 812
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
813
        item->lastKey = pDataBlockInfo->window.skey + step;
814 815 816
      }
    }
  }
817

H
Haojun Liao 已提交
818
  assert(num > 0);
819 820 821
  return num;
}

H
Haojun Liao 已提交
822 823
static void doBlockwiseApplyFunctions_rv(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, STimeWindow *pWin,
    int32_t offset, int32_t forwardStep, TSKEY *tsCol, int32_t numOfTotal, int32_t numOfOutput) {
824
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
825 826
  bool hasPrev = pCtx[0].preAggVals.isSet;

827
  for (int32_t k = 0; k < numOfOutput; ++k) {
828
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
829
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
830

831
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
832 833

    int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1);
834 835
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
836 837 838 839 840
    }

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

H
Haojun Liao 已提交
842
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
843

844 845 846 847 848
    // 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 已提交
849

850 851
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
852
    }
853 854 855

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
856
    pCtx[k].pInput = start;
857 858 859 860
  }
}


H
Haojun Liao 已提交
861
static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
862
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
863
  getNextTimeWindow(pQuery, pNext);
864

H
Haojun Liao 已提交
865
  // next time window is not in current block
H
Haojun Liao 已提交
866 867
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
868 869
    return -1;
  }
870

H
Haojun Liao 已提交
871 872
  TSKEY startKey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
873
    startKey = pNext->skey;
H
Haojun Liao 已提交
874 875
    if (startKey < pQuery->window.skey) {
      startKey = pQuery->window.skey;
876
    }
H
Haojun Liao 已提交
877
  } else {
H
Haojun Liao 已提交
878
    startKey = pNext->ekey;
H
Haojun Liao 已提交
879 880
    if (startKey > pQuery->window.skey) {
      startKey = pQuery->window.skey;
881
    }
H
Haojun Liao 已提交
882
  }
883

H
Haojun Liao 已提交
884
  int32_t startPos = 0;
H
Haojun Liao 已提交
885

H
Haojun Liao 已提交
886
  // tumbling time window query, a special case of sliding time window query
887
  if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) {
H
Haojun Liao 已提交
888 889 890
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
891
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
892
      startPos = 0;
H
Haojun Liao 已提交
893
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
894 895 896 897
      startPos = pDataBlockInfo->rows - 1;
    } else {
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order);
    }
H
Haojun Liao 已提交
898
  }
899

H
Haojun Liao 已提交
900 901 902 903
  /*
   * 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 已提交
904 905 906
  if (primaryKeys == NULL) {
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
907
    } else {
H
Haojun Liao 已提交
908
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
909
    }
H
Haojun Liao 已提交
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
  } 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;
      }
929
    }
930
  }
931

H
Haojun Liao 已提交
932
  return startPos;
933 934
}

H
Haojun Liao 已提交
935
static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
936 937 938 939 940 941 942 943 944 945 946 947
  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;
    }
  }
948

949 950 951
  return ekey;
}

H
Haojun Liao 已提交
952 953 954 955 956 957 958 959 960 961 962 963
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;
    }
  }
}

964
// window start key interpolation
H
Haojun Liao 已提交
965

966

H
Haojun Liao 已提交
967
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
968
    int32_t rowIndex) {
969 970 971 972 973 974 975
  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 已提交
976
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
977 978 979
  }
}

H
Haojun Liao 已提交
980
static TSKEY getStartTsKey(SQuery* pQuery, STimeWindow* win, const TSKEY* tsCols, int32_t rows) {
981 982
  TSKEY ts = TSKEY_INITIAL_VAL;

H
Haojun Liao 已提交
983
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
984
  if (tsCols == NULL) {
H
Haojun Liao 已提交
985
    ts = ascQuery? win->skey : win->ekey;
986
  } else {
H
Haojun Liao 已提交
987
    int32_t offset = ascQuery? 0:rows-1;
988 989 990 991 992 993
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
static void setArithParams(SArithmeticSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
  sas->numOfCols = (int32_t) pSDataBlock->info.numOfCols;
  sas->pArithExpr = pExprInfo;

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

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

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

static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order);
static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
    pCtx[i].order = order;
H
Haojun Liao 已提交
1017
    pCtx[i].size  = pBlock->info.rows;
H
Haojun Liao 已提交
1018
    pCtx[i].currentStage = pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
1019

H
Haojun Liao 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
    setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);
  }
}

static void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
  if (pCtx[0].functionId == TSDB_FUNC_ARITHM) {
    SArithmeticSupport* pSupport = (SArithmeticSupport*) pCtx[0].param[1].pz;
    if (pSupport->colList == NULL) {
      doSetInputDataBlock(pOperator, pCtx, pBlock, order);
    } else {
      doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
    }
  } else {
    if (pCtx[0].pInput == NULL && pBlock->pDataBlock != NULL) {
      doSetInputDataBlock(pOperator, pCtx, pBlock, order);
    } else {
      doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
    }
  }
}

static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
    pCtx[i].order = order;
H
Haojun Liao 已提交
1044
    pCtx[i].size  = pBlock->info.rows;
H
Haojun Liao 已提交
1045
    pCtx[i].currentStage = pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
1046 1047 1048 1049 1050 1051 1052

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

    if (pCtx[i].functionId == TSDB_FUNC_ARITHM) {
      setArithParams((SArithmeticSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock);
    } else {
      SColIndex* pCol = &pOperator->pExpr[i].base.colInfo;
H
Haojun Liao 已提交
1053
      if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) {
H
Haojun Liao 已提交
1054 1055
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
H
Haojun Liao 已提交
1056

H
Haojun Liao 已提交
1057 1058
        pCtx[i].pInput = p->pData;
        assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type && pCtx[i].inputBytes == p->info.bytes);
H
Haojun Liao 已提交
1059

H
Haojun Liao 已提交
1060
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
1061
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
1062 1063
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
          pCtx[i].ptsList = tsInfo->pData;
H
Haojun Liao 已提交
1064
        }
H
Haojun Liao 已提交
1065 1066 1067 1068 1069
      }
    }
  }
}

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

H
Haojun Liao 已提交
1073
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1074
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1075
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
1076
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
1077 1078 1079 1080 1081
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

H
Haojun Liao 已提交
1082
static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
1083
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1084

H
Haojun Liao 已提交
1085
  for (int32_t k = 0; k < numOfOutput; ++k) {
1086 1087
    pCtx[k].startTs = pQuery->window.skey;
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
1088 1089 1090
  }
}

H
Haojun Liao 已提交
1091 1092
void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, SArray* pDataBlock, TSKEY prevTs,
                               int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type) {
H
Haojun Liao 已提交
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
  SExprInfo* pExpr = pOperator->pExpr;

  SQLFunctionCtx* pCtx = pInfo->pCtx;

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

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

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

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

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

H
Haojun Liao 已提交
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
    if (functionId == TSDB_FUNC_INTERP) {
      if (type == RESULT_ROW_START_INTERP) {
        pCtx[k].start.key = prevTs;
        pCtx[k].start.val = v1;

        pCtx[k].end.key = curTs;
        pCtx[k].end.val = v2;
      }
    } else if (functionId == TSDB_FUNC_TWA) {
      SPoint point1 = (SPoint){.key = prevTs,    .val = &v1};
      SPoint point2 = (SPoint){.key = curTs,     .val = &v2};
      SPoint point  = (SPoint){.key = windowKey, .val = &v };
H
Haojun Liao 已提交
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145

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

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

H
Haojun Liao 已提交
1146 1147
static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, int32_t pos,
                                              int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols, STimeWindow* win) {
H
Haojun Liao 已提交
1148 1149 1150
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
1151 1152
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

H
Haojun Liao 已提交
1153 1154 1155 1156 1157
  TSKEY curTs  = tsCols[pos];
  TSKEY lastTs = *(TSKEY *) pRuntimeEnv->prevRow[0];

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

H
Haojun Liao 已提交
1164
  if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
H
Haojun Liao 已提交
1165 1166 1167 1168 1169
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

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

H
Haojun Liao 已提交
1172 1173
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1174 1175 1176 1177
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1178
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
  SQueryRuntimeEnv *pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t numOfOutput = pOperatorInfo->numOfOutput;

  TSKEY   actualEndKey = tsCols[endRowIndex];

  TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? win->ekey:win->skey;

  // 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))) {
    setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP);
    return false;
  }

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

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

  TSKEY nextKey = tsCols[nextRowIndex];
H
Haojun Liao 已提交
1204 1205
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
  return true;
}

static void doWindowBorderInterpolation(SOperatorInfo* pOperatorInfo, SSDataBlock* pBlock, SQLFunctionCtx* pCtx,
    SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  SQuery* pQuery = pRuntimeEnv->pQuery;
  if (!pQuery->timeWindowInterpo) {
    return;
  }

  assert(pBlock != NULL);
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);

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

  TSKEY  *tsCols = (TSKEY *)(pColInfo->pData);
  bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
  if (!done) { // it is not interpolated, now start to generated the interpolated value
    int32_t startRowIndex = startPos;
    bool interp = setTimeWindowInterpolationStartTs(pOperatorInfo, pCtx, startRowIndex, pBlock->info.rows, pBlock->pDataBlock,
H
Haojun Liao 已提交
1227
        tsCols, win);
H
Haojun Liao 已提交
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    }
  } else {
    setNotInterpoWindowKey(pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
  }

  // 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
  done = resultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
  if (!done) {
    int32_t endRowIndex = startPos + (forwardStep - 1) * step;

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

H
Haojun Liao 已提交
1255
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
H
Haojun Liao 已提交
1256
                            STableIntervalOperatorInfo* pInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
H
Haojun Liao 已提交
1257 1258 1259
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
  SQuery*           pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1260 1261

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

H
Haojun Liao 已提交
1264 1265 1266 1267
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
    tsCols = pColDataInfo->pData;
H
Haojun Liao 已提交
1268 1269
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1270 1271
  }

H
Haojun Liao 已提交
1272 1273
  int32_t startPos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : (pSDataBlock->info.rows - 1);
  TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1274 1275

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

H
Haojun Liao 已提交
1278 1279 1280
  SResultRow* pResult = NULL;
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                        numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1281 1282 1283 1284 1285
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
    //      goto _end;
  }

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1286 1287
  TSKEY   ekey = reviseWindowEkey(pQuery, &win);
  forwardStep =
H
Haojun Liao 已提交
1288
      getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1289 1290

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1291
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1292 1293
  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 已提交
1294
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1295
      if (pRes->closed) {
H
Haojun Liao 已提交
1296 1297
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1298
        continue;
H
Haojun Liao 已提交
1299
      }
H
Haojun Liao 已提交
1300 1301

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1302 1303
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1304 1305
      assert(ret == TSDB_CODE_SUCCESS && !resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));

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

H
Haojun Liao 已提交
1309
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1310
      setNotInterpoWindowKey(pInfo->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1311

H
Haojun Liao 已提交
1312
      doBlockwiseApplyFunctions_rv(pRuntimeEnv, pInfo->pCtx, &w, startPos, 0, tsCols, pSDataBlock->info.rows,
H
Haojun Liao 已提交
1313
                                   numOfOutput);
H
Haojun Liao 已提交
1314 1315
    }

H
Haojun Liao 已提交
1316
    // restore current time window
H
Haojun Liao 已提交
1317 1318
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1319 1320 1321 1322
    assert(ret == TSDB_CODE_SUCCESS);
  }

  // window start key interpolation
H
Haojun Liao 已提交
1323
  doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
H
Haojun Liao 已提交
1324
  doBlockwiseApplyFunctions_rv(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows,
H
Haojun Liao 已提交
1325
                               numOfOutput);
H
Haojun Liao 已提交
1326 1327 1328 1329

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1330
    startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1331 1332
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1333 1334
    }

H
Haojun Liao 已提交
1335
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1336 1337
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1338 1339
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
      break;
H
Haojun Liao 已提交
1340 1341
    }

H
Haojun Liao 已提交
1342
    ekey = reviseWindowEkey(pQuery, &nextWin);
H
Haojun Liao 已提交
1343 1344
    forwardStep =
        getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1345 1346

    // window start(end) key interpolation
H
Haojun Liao 已提交
1347
    doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &nextWin, startPos, forwardStep);
H
Haojun Liao 已提交
1348 1349
    doBlockwiseApplyFunctions_rv(pRuntimeEnv, pInfo->pCtx, &nextWin, startPos, forwardStep, tsCols,
                                 pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1350
  }
H
Haojun Liao 已提交
1351 1352 1353 1354 1355

  if (pQuery->timeWindowInterpo) {
    int32_t rowIndex = QUERY_IS_ASC_QUERY(pQuery)? pSDataBlock->info.rows-1:0;
    saveDataBlockLastRow(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, rowIndex);
  }
H
Haojun Liao 已提交
1356 1357
}

H
Haojun Liao 已提交
1358
static void hashGroupbyAgg(SQueryRuntimeEnv *pRuntimeEnv, SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo,
H
Haojun Liao 已提交
1359
                           SSDataBlock *pSDataBlock) {
H
Haojun Liao 已提交
1360 1361 1362 1363
  SQuery *pQuery = pRuntimeEnv->pQuery;

  STableQueryInfo* item = pQuery->current;

H
Haojun Liao 已提交
1364
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1365 1366
  int16_t bytes = pColInfoData->info.bytes;
  int16_t type  = pColInfoData->info.type;
H
Haojun Liao 已提交
1367

H
Haojun Liao 已提交
1368
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
H
Haojun Liao 已提交
1369
    char *val = pColInfoData->pData + bytes * j;
H
Haojun Liao 已提交
1370 1371 1372 1373
    if (isNull(val, type)) {  // ignore the null value
      continue;
    }

H
Haojun Liao 已提交
1374
    // TODO compare with the previous value to speedup the query processing
H
Haojun Liao 已提交
1375
    int32_t ret = setGroupResultOutputBuf_rv(pRuntimeEnv, &pInfo->binfo.resultRowInfo, pInfo->binfo.pCtx, pOperator->numOfOutput, val, type, bytes, item->groupIndex, pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
1376 1377 1378 1379
    if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
    }

H
Haojun Liao 已提交
1380
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1381 1382 1383
      pInfo->binfo.pCtx[k].size = 1;  // TODO refactor: extract from here
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1384
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1385 1386 1387 1388 1389
      }
    }
  }
}

H
Haojun Liao 已提交
1390
static int32_t setGroupResultOutputBuf_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo* pResultRowInfo,
H
Haojun Liao 已提交
1391
    SQLFunctionCtx * pCtx, int32_t numOfCols, char *pData, int16_t type, int16_t bytes, int32_t groupIndex, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
1392 1393 1394 1395 1396 1397 1398 1399 1400
  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) {
H
Haojun Liao 已提交
1401
    SQInfo* pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
    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) {
H
Haojun Liao 已提交
1424
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
H
Haojun Liao 已提交
1425 1426 1427 1428 1429
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1430
  setResultOutputBuf_rv(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
H
Haojun Liao 已提交
1431 1432 1433
  initCtxOutputBuf_rv(pCtx, numOfCols);
  return TSDB_CODE_SUCCESS;
}
1434

H
Haojun Liao 已提交
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
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);
}

1455
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1456
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
hjxilinx 已提交
1457
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1458 1459 1460 1461 1462

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

1464 1465 1466
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1467

1468
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
hjxilinx 已提交
1469 1470
    return QUERY_IS_ASC_QUERY(pQuery);
  }
1471

H
Haojun Liao 已提交
1472
  // denote the order type
1473
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
1474
    return pCtx->param[0].i64 == pQuery->order.order;
1475 1476
  }

1477 1478 1479
  // in the reverse table scan, only the following functions need to be executed
  if (IS_REVERSE_SCAN(pRuntimeEnv) ||
      (pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != TSDB_FUNC_STDDEV && functionId != TSDB_FUNC_PERCT)) {
1480 1481
    return false;
  }
1482

1483 1484 1485
  return true;
}

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

H
Haojun Liao 已提交
1489 1490 1491 1492
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1493 1494 1495 1496 1497 1498
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1499
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1500

1501
#if 0
H
Haojun Liao 已提交
1502
  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1503 1504 1505 1506 1507
  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;
  }
1508
#endif
H
Haojun Liao 已提交
1509 1510
}

H
Haojun Liao 已提交
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
// set the output buffer for the selectivity + tag query
static int32_t setCtxTagColumnInfo(SQLFunctionCtx *pCtx, int32_t numOfOutput) {
  if (!isSelectivityWithTagsQuery(pCtx, numOfOutput)) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t num = 0;
  int16_t tagLen = 0;

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

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

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

  return TSDB_CODE_SUCCESS;
}
1552

H
Haojun Liao 已提交
1553
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1554
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1555 1556
  SQuery* pQuery = pRuntimeEnv->pQuery;

1557 1558
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1559
    return NULL;
1560 1561
  }

H
Haojun Liao 已提交
1562
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1563 1564 1565 1566
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1567

H
Haojun Liao 已提交
1568 1569
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base;
1570
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1571

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

Y
TD-1230  
yihaoDeng 已提交
1574
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1575 1576
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1577
    } else {
1578 1579
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1580

H
Haojun Liao 已提交
1581 1582
    pCtx->inputBytes = pSqlFuncMsg->colBytes;
    pCtx->inputType  = pSqlFuncMsg->colType;
H
Haojun Liao 已提交
1583

1584
    pCtx->ptsOutputBuf = NULL;
1585

H
Haojun Liao 已提交
1586 1587
    pCtx->outputBytes  = pExpr[i].bytes;
    pCtx->outputType   = pExpr[i].type;
1588

1589
    pCtx->order        = pQuery->order.order;
H
Haojun Liao 已提交
1590
    pCtx->functionId   = pSqlFuncMsg->functionId;
H
Haojun Liao 已提交
1591
    pCtx->stableQuery  = pQuery->stableQuery;
H
Haojun Liao 已提交
1592
    pCtx->interBufBytes = pExpr[i].interBytes;
1593 1594
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1595

H
Haojun Liao 已提交
1596
    pCtx->numOfParams  = pSqlFuncMsg->numOfParams;
1597 1598 1599
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
      int16_t type = pSqlFuncMsg->arg[j].argType;
      int16_t bytes = pSqlFuncMsg->arg[j].argBytes;
1600 1601 1602 1603
      if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) {
        continue;
      }

1604
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
1605
        tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type);
1606 1607 1608 1609
      } else {
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type);
      }
    }
1610

1611 1612
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1613

1614
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1615
      int32_t f = pExpr[0].base.functionId;
1616
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1617

H
Haojun Liao 已提交
1618
      pCtx->param[2].i64 = pQuery->order.order;
1619
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1620
      pCtx->param[3].i64 = functionId;
1621
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1622

1623
      pCtx->param[1].i64 = pQuery->order.orderColId;
H
Haojun Liao 已提交
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
    } 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) {
1636
      pCtx->param[0].i64 = pQuery->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1637 1638 1639 1640 1641 1642 1643 1644
      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) {
      pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i];
1645
    }
1646

1647
    if (i > 0) {
H
Haojun Liao 已提交
1648
      (*rowCellInfoOffset)[i] = (*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) + pExpr[i - 1].interBytes;
1649 1650
    }
  }
1651

H
Haojun Liao 已提交
1652 1653
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1654
  return pFuncCtx;
H
Haojun Liao 已提交
1655 1656
}

H
Haojun Liao 已提交
1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674
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 已提交
1675 1676
static void calResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo);

H
Haojun Liao 已提交
1677
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables) {
H
Haojun Liao 已提交
1678
  qDebug("QInfo:%p setup runtime env", pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
1679 1680 1681 1682 1683 1684 1685
  SQuery *pQuery = pRuntimeEnv->pQuery;

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

  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);

H
Haojun Liao 已提交
1686 1687
  calResultBufSize(pQuery, &pRuntimeEnv->resultInfo);

H
Haojun Liao 已提交
1688 1689 1690 1691 1692
  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);
H
Haojun Liao 已提交
1693 1694
  pRuntimeEnv->currentOffset = pQuery->limit.offset;

H
Haojun Liao 已提交
1695 1696
  pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport));

H
Haojun Liao 已提交
1697 1698
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1699 1700 1701
    goto _clean;
  }

H
Haojun Liao 已提交
1702 1703 1704 1705 1706 1707
  if (pQuery->numOfCols) {
    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;
    }
H
Haojun Liao 已提交
1708

H
Haojun Liao 已提交
1709 1710
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1711

H
Haojun Liao 已提交
1712
  qDebug("QInfo:%p init runtime completed", pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
1713 1714

  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
1715 1716 1717
  // interval (down sampling operation)
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    if (pQuery->stableQuery) {
H
Haojun Liao 已提交
1718
      pRuntimeEnv->proot = createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1719
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1720
    } else {
H
Haojun Liao 已提交
1721
      pRuntimeEnv->proot = createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1722
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1723

H
Haojun Liao 已提交
1724 1725 1726
      if (pQuery->pExpr2 != NULL) {
        pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
      }
H
Haojun Liao 已提交
1727

H
Haojun Liao 已提交
1728
      if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
1729 1730
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
H
Haojun Liao 已提交
1731
      }
H
Haojun Liao 已提交
1732
    }
H
Haojun Liao 已提交
1733 1734

    } else if (pQuery->groupbyColumn) {
H
Haojun Liao 已提交
1735
      pRuntimeEnv->proot = createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1736
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1737

H
Haojun Liao 已提交
1738
      if (pQuery->pExpr2 != NULL) {
H
Haojun Liao 已提交
1739
        pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1740
      }
H
Haojun Liao 已提交
1741
    } else if (isFixedOutputQuery(pQuery)) {
H
Haojun Liao 已提交
1742
      if (pQuery->stableQuery && !isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
1743
        pRuntimeEnv->proot = createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
1744
      } else {
H
Haojun Liao 已提交
1745
        pRuntimeEnv->proot = createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
1746 1747
      }

H
Haojun Liao 已提交
1748
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1749 1750

      if (pQuery->pExpr2 != NULL) {
H
Haojun Liao 已提交
1751
        pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1752
      }
H
Haojun Liao 已提交
1753 1754
    } else {  // diff/add/multiply/subtract/division
      assert(pQuery->checkResultBuf == 1);
H
Haojun Liao 已提交
1755
      if (!onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
1756 1757
        pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
1758
      }
H
Haojun Liao 已提交
1759 1760
    }

H
Haojun Liao 已提交
1761 1762 1763
    if (pQuery->limit.offset > 0) {
      pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
    }
H
Haojun Liao 已提交
1764

H
Haojun Liao 已提交
1765 1766
    if (pQuery->limit.limit > 0) {
      pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1767 1768
    }

1769
    return TSDB_CODE_SUCCESS;
1770

1771
_clean:
1772
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1773 1774 1775 1776
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1777

1778
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1779 1780
}

H
Haojun Liao 已提交
1781
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1782
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1783 1784 1785 1786

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

H
Haojun Liao 已提交
1787
  SMemRef* pMemRef = &pQuery->memRef;
H
Haojun Liao 已提交
1788 1789 1790
  assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL);
}

H
Haojun Liao 已提交
1791
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
1792
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1793
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1794

1795
  qDebug("QInfo:%p teardown runtime env", pQInfo);
1796

1797 1798 1799
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1800
      tfree(pRuntimeEnv->sasArray[i].colList);
1801 1802 1803 1804 1805
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1806
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1807
  doFreeQueryHandle(pRuntimeEnv);
1808

H
Haojun Liao 已提交
1809
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1810

S
TD-1848  
Shengliang Guan 已提交
1811
  tfree(pRuntimeEnv->keyBuf);
1812
  tfree(pRuntimeEnv->prevRow);
1813 1814
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1815 1816
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1817

H
Haojun Liao 已提交
1818
  pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool);
1819 1820
  taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult);
  pRuntimeEnv->prevResult = NULL;
H
Haojun Liao 已提交
1821 1822

  destroyOperatorInfo(pRuntimeEnv->proot);
1823 1824
}

1825 1826 1827 1828
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1829
bool isQueryKilled(SQInfo *pQInfo) {
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
  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 已提交
1848
void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED;}
H
hjxilinx 已提交
1849

H
Haojun Liao 已提交
1850
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
1851
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
1852 1853
    return false;
  }
1854

1855
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1856
  if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) {
1857 1858
    return true;
  }
1859

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

1863 1864
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
1865
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
1866 1867
      continue;
    }
1868

1869 1870 1871
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
1872

H
Haojun Liao 已提交
1873
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
1874 1875 1876
      return true;
    }
  }
1877

1878 1879 1880
  return false;
}

1881
// todo refactor with isLastRowQuery
1882
bool isPointInterpoQuery(SQuery *pQuery) {
1883
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1884 1885
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
1886 1887 1888
      return true;
    }
  }
1889

1890 1891 1892 1893
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
1894
static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) {
1895
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1896
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1897 1898 1899
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
1900

1901 1902 1903 1904 1905
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
1906

1907 1908 1909
  return false;
}

H
hjxilinx 已提交
1910
static bool isFirstLastRowQuery(SQuery *pQuery) {
1911
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1912
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
1913 1914 1915 1916
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
1917

1918 1919 1920
  return false;
}

H
hjxilinx 已提交
1921
static bool needReverseScan(SQuery *pQuery) {
1922
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1923
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1924 1925 1926
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
1927

1928
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
1929 1930
      return true;
    }
1931 1932

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
1933
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
1934
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
1935 1936 1937
      if (order != pQuery->order.order) {
        return true;
      }
1938
    }
1939
  }
1940

1941 1942
  return false;
}
H
hjxilinx 已提交
1943

H
Haojun Liao 已提交
1944 1945 1946 1947
/**
 * 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 已提交
1948
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
1949
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1950
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
1951 1952

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
1953 1954 1955 1956

    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 已提交
1957
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
1958 1959 1960
      return false;
    }
  }
1961

H
hjxilinx 已提交
1962 1963 1964
  return true;
}

1965 1966
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
1967
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
1968 1969
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
1970 1971

  /*
1972
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
1973 1974
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
1975 1976
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
1977
    win->ekey = INT64_MAX;
1978 1979
  } 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 已提交
1980
  } else {
1981
    win->ekey = win->skey + pQuery->interval.interval - 1;
1982 1983 1984 1985 1986
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
1987
    pQuery->checkResultBuf = 0;
1988
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
1989
    pQuery->checkResultBuf = 0;
1990 1991
  } else {
    bool hasMultioutput = false;
1992
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1993
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
1994 1995 1996
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
1997

H
Haojun Liao 已提交
1998
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
1999 2000 2001 2002
      if (!hasMultioutput) {
        break;
      }
    }
2003

H
Haojun Liao 已提交
2004
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
2005 2006 2007 2008 2009 2010
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2011
bool colIdCheck(SQuery *pQuery, void* qinfo) {
2012 2013
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
2014
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
H
Haojun Liao 已提交
2015
      qError("QInfo:%p invalid data load column for query", qinfo);
2016 2017 2018
      return false;
    }
  }
2019

2020 2021 2022 2023 2024 2025
  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) {
2026
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2027
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2028

2029 2030 2031 2032
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2033

2034 2035 2036 2037
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2038

2039 2040 2041 2042 2043 2044 2045
  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); }

2046
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2047 2048
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2049
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2050
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2051 2052 2053

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

2056 2057 2058 2059
      // 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 已提交
2060 2061 2062 2063
    }
  }
}

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

2067 2068 2069
  // 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;
2070

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

H
Haojun Liao 已提交
2076
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2077 2078 2079
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2080

2081 2082
    return;
  }
2083

2084
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2085
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2086 2087 2088
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2089

2090
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2091 2092 2093
    return;
  }

2094
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2095
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2096
      qDebug(msg, pQInfo, "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);
H
Haojun Liao 已提交
2097 2098
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2099

2100
    pQuery->order.order = TSDB_ORDER_ASC;
2101 2102
    return;
  }
2103

2104
  if (pQuery->interval.interval == 0) {
2105 2106
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2107
        qDebug(msg, pQInfo, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2108 2109
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2110
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2111
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2112
      }
2113

2114
      pQuery->order.order = TSDB_ORDER_ASC;
2115 2116
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2117
        qDebug(msg, pQInfo, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2118 2119
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2120
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2121
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2122
      }
2123

2124
      pQuery->order.order = TSDB_ORDER_DESC;
2125
    }
2126

2127
  } else {  // interval query
2128
    if (stableQuery) {
2129 2130
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2131
          qDebug(msg, pQInfo, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2132 2133
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2134
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2135
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2136
        }
2137

2138
        pQuery->order.order = TSDB_ORDER_ASC;
2139 2140
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2141
          qDebug(msg, pQInfo, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2142 2143
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2144
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2145
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2146
        }
2147

2148
        pQuery->order.order = TSDB_ORDER_DESC;
2149 2150 2151 2152 2153
      }
    }
  }
}

2154 2155
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2156
  int32_t MIN_ROWS_PER_PAGE = 4;
2157

H
Haojun Liao 已提交
2158
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2159 2160 2161 2162
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2167 2168
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2169 2170
}

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

H
Haojun Liao 已提交
2173
static bool doFilterOnBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) {
H
Haojun Liao 已提交
2174
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2175

H
Haojun Liao 已提交
2176
  if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) {
2177 2178 2179 2180 2181
    return true;
  }

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

H
Haojun Liao 已提交
2183 2184 2185 2186 2187 2188 2189 2190
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2191
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2192
    if (index == -1) {
H
Haojun Liao 已提交
2193
      return true;
2194
    }
2195

2196
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2197
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2198
      return true;
2199
    }
2200

2201
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2202
    if (pDataStatis[index].numOfNull == numOfRows) {
2203 2204 2205 2206

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2207
        if (pFilterElem->fp == isNullOperator) {
2208 2209 2210 2211
          return true;
        }
      }

2212 2213
      continue;
    }
2214

H
Haojun Liao 已提交
2215 2216 2217
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2221
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2222
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2223 2224 2225 2226 2227
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2228
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2229 2230 2231 2232 2233
          return true;
        }
      }
    }
  }
2234

H
Haojun Liao 已提交
2235
  return false;
2236 2237
}

H
Haojun Liao 已提交
2238 2239 2240 2241 2242 2243 2244 2245
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 已提交
2246
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2247

H
Haojun Liao 已提交
2248
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2249 2250 2251 2252
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2253
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2254
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2255 2256 2257
        break;
      }

H
Haojun Liao 已提交
2258 2259
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2260 2261 2262 2263 2264
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2265 2266 2267
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2268 2269 2270 2271
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2272
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2273 2274 2275 2276
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2277 2278
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2279 2280 2281 2282 2283 2284 2285 2286
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311
static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key, bool ascQuery) {
  STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf);

#if defined(_DEBUG_VIEW)
  printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n",
         elem.ts, key, elem.tag.i64, pQuery->order.order, pRuntimeEnv->pTsBuf->tsOrder,
         pRuntimeEnv->pTsBuf->cur.order, pRuntimeEnv->pTsBuf->cur.tsIndex);
#endif

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

  return TS_JOIN_TS_EQUAL;
}
2312

H
Haojun Liao 已提交
2313 2314
void filterDataBlock_rv(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
                        SSDataBlock* pBlock, STSBuf* pTsBuf, bool ascQuery) {
H
Haojun Liao 已提交
2315 2316 2317 2318 2319
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343
  if (pTsBuf != NULL) {
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

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

      if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) {
        break;
      }
    }
  } else {
    for (int32_t i = 0; i < numOfRows; ++i) {
      bool qualified = false;
H
Haojun Liao 已提交
2344

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

H
Haojun Liao 已提交
2348 2349 2350
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2351

H
Haojun Liao 已提交
2352 2353 2354 2355 2356 2357 2358 2359
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2360
          } else {
H
Haojun Liao 已提交
2361 2362 2363 2364 2365 2366
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2367
          }
H
Haojun Liao 已提交
2368 2369

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2370 2371 2372 2373 2374
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2375
        if (!qualified) {
H
Haojun Liao 已提交
2376 2377 2378 2379
          break;
        }
      }

H
Haojun Liao 已提交
2380
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2381
      if (!qualified) {
H
Haojun Liao 已提交
2382
        all = false;
H
Haojun Liao 已提交
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403
      }
    }
  }

  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;
2404
          len = 0;
H
Haojun Liao 已提交
2405 2406 2407 2408
        }
      }
    }

2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
    if (len > 0) {
      int32_t cstart = numOfRows - len;
      for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
        SColumnInfoData *pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i);

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

      start += len;
      len = 0;
    }

H
Haojun Liao 已提交
2422 2423 2424 2425
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

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

H
Haojun Liao 已提交
2430 2431
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
H
Haojun Liao 已提交
2432 2433 2434 2435 2436 2437
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2438 2439 2440 2441
static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId);
static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes);

//TODO refactor
H
Haojun Liao 已提交
2442 2443
int32_t loadDataBlockOnDemand_rv(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                                 uint32_t* status) {
H
Haojun Liao 已提交
2444
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2445
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2446
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2447

H
Haojun Liao 已提交
2448
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2449
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
2450

H
Haojun Liao 已提交
2451
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2452 2453
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472
  if (pRuntimeEnv->pTsBuf != NULL && pQuery->stableQuery) {
    SExprInfo*   pExprInfo = &pTableScanInfo->pExpr[0];
    int16_t      tagId = (int16_t)pExprInfo->base.arg->argValue.i64;
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagId);

    // compare tag first
    tVariant t = {0};
    doSetTagValueInParam(pQuery->current->pTable, tagId, &t, pColInfo->type, pColInfo->bytes);

    STSElem elem = tsBufGetElem(pRuntimeEnv->pTsBuf);
    if (tsBufIsValidElem(&elem) && tVariantCompare(&t, elem.tag) == 0) {
      *status = BLK_DATA_ALL_NEEDED;
    } else {
      (*status) = BLK_DATA_DISCARD;
      return TSDB_CODE_SUCCESS;
    }
  }

  if (pQuery->numOfFilterCols > 0) {
H
Haojun Liao 已提交
2473
    *status = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2474
  } else {  // check if this data block is required to load
H
Haojun Liao 已提交
2475 2476
    // 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 已提交
2477
    if (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info)) {
H
Haojun Liao 已提交
2478
      *status = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2479
    }
H
Haojun Liao 已提交
2480 2481 2482 2483

    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 已提交
2484 2485 2486
      if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
        SResultRow* pResult = NULL;

H
Haojun Liao 已提交
2487 2488
        bool        masterScan = IS_MASTER_SCAN(pRuntimeEnv);
        TSKEY       k = QUERY_IS_ASC_QUERY(pQuery) ? pBlock->info.window.skey : pBlock->info.window.ekey;
H
Haojun Liao 已提交
2489
        STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQuery);
H
Haojun Liao 已提交
2490 2491 2492
        if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                    pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                    pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2493 2494 2495 2496
          // todo handle error in set result for timewindow
        }
      }

H
Haojun Liao 已提交
2497
      int32_t         numOfOutput = pTableScanInfo->numOfOutput;
H
Haojun Liao 已提交
2498
      SQLFunctionCtx* pCtx = pTableScanInfo->pCtx;
H
Haojun Liao 已提交
2499

H
Haojun Liao 已提交
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
      if (pQuery->groupbyColumn) {
        (*status) = BLK_DATA_ALL_NEEDED;
      } else {
        for (int32_t i = 0; i < numOfOutput; ++i) {
          int32_t functionId = pCtx[i].functionId;
          int32_t colId = pTableScanInfo->pExpr[i].base.colInfo.colId;

          // group by + first/last should not apply the first/last block filter
          if (functionId != TSDB_FUNC_FIRST_DST && functionId != TSDB_FUNC_LAST_DST) {
            (*status) |= aAggs[functionId].dataReqFunc(&pTableScanInfo->pCtx[i], &pBlock->info.window, colId);
            if (((*status) & BLK_DATA_ALL_NEEDED) == BLK_DATA_ALL_NEEDED) {
              break;
            }
          } else {
            (*status) |= BLK_DATA_ALL_NEEDED;
2515 2516
            break;
          }
H
Haojun Liao 已提交
2517 2518
        }
      }
H
Haojun Liao 已提交
2519 2520 2521
    }
  }

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

H
Haojun Liao 已提交
2524
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
2525
    qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2526
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2527 2528 2529 2530
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2531
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2532

H
Haojun Liao 已提交
2533
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2534
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2535
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2536 2537 2538 2539 2540 2541
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2544 2545 2546
    if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) {
      bool load = false;
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2547
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2548
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2549 2550
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2551 2552 2553
          if (!load) {
            // current block has been discard due to filter applied
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2554 2555
            qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo,
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2556 2557 2558 2559 2560 2561 2562 2563
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2564
    if (!doFilterOnBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2565
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2566 2567
      qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey,
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2568
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2569
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2570 2571 2572 2573
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2574
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2575
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2576 2577
      return terrno;
    }
H
Haojun Liao 已提交
2578

H
Haojun Liao 已提交
2579
    if (pQuery->numOfFilterCols > 0 && pQuery->pFilterInfo[0].pData == NULL) {
H
Haojun Liao 已提交
2580
      // set the initial static data value filter expression
H
Haojun Liao 已提交
2581 2582 2583
      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);
H
Haojun Liao 已提交
2584

H
Haojun Liao 已提交
2585 2586 2587
          if (pQuery->pFilterInfo[i].info.colId == pColInfo->info.colId) {
            pQuery->pFilterInfo[i].pData = pColInfo->pData;
            break;
H
Haojun Liao 已提交
2588 2589 2590
          }
        }
      }
H
Haojun Liao 已提交
2591
    }
H
Haojun Liao 已提交
2592

H
Haojun Liao 已提交
2593 2594 2595
    if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
      filterDataBlock_rv(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, pRuntimeEnv->pTsBuf,
                         QUERY_IS_ASC_QUERY(pQuery));
H
Haojun Liao 已提交
2596
    }
H
Haojun Liao 已提交
2597 2598 2599 2600 2601
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2602
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2603
  int32_t midPos = -1;
H
Haojun Liao 已提交
2604
  int32_t numOfRows;
2605

2606 2607 2608
  if (num <= 0) {
    return -1;
  }
2609

2610
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2611 2612

  TSKEY * keyList = (TSKEY *)pValue;
2613
  int32_t firstPos = 0;
2614
  int32_t lastPos = num - 1;
2615

2616
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2617 2618 2619 2620 2621
    // 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;
2622

H
Haojun Liao 已提交
2623 2624
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2625

H
hjxilinx 已提交
2626 2627 2628 2629 2630 2631 2632 2633
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2634

H
hjxilinx 已提交
2635 2636 2637 2638 2639
  } 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;
2640

H
hjxilinx 已提交
2641 2642 2643 2644 2645 2646 2647
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2648

H
Haojun Liao 已提交
2649
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2650
      midPos = (numOfRows >> 1u) + firstPos;
2651

H
hjxilinx 已提交
2652 2653 2654 2655 2656 2657 2658 2659 2660
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2661

H
hjxilinx 已提交
2662 2663 2664
  return midPos;
}

H
Haojun Liao 已提交
2665 2666 2667 2668 2669 2670
/*
 * set tag value in SQLFunctionCtx
 * e.g.,tag information into input buffer
 */
static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes) {
  tVariantDestroy(tag);
2671

H
Haojun Liao 已提交
2672 2673 2674
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
    char* val = tsdbGetTableName(pTable);
    assert(val != NULL);
H
Haojun Liao 已提交
2675

H
Haojun Liao 已提交
2676 2677 2678 2679 2680 2681
    tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), TSDB_DATA_TYPE_BINARY);
  } else {
    char* val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
    if (val == NULL) {
      tag->nType = TSDB_DATA_TYPE_NULL;
      return;
H
[td-90]  
Haojun Liao 已提交
2682
    }
2683

H
hjxilinx 已提交
2684
    if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Hongze Cheng 已提交
2685
      if (isNull(val, type)) {
H
Haojun Liao 已提交
2686 2687 2688 2689
        tag->nType = TSDB_DATA_TYPE_NULL;
        return;
      }

H
[td-90]  
Haojun Liao 已提交
2690
      tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
H
hjxilinx 已提交
2691
    } else {
H
Haojun Liao 已提交
2692 2693 2694 2695 2696
      if (isNull(val, type)) {
        tag->nType = TSDB_DATA_TYPE_NULL;
        return;
      }

H
[td-90]  
Haojun Liao 已提交
2697
      tVariantCreateFromBinary(tag, val, bytes, type);
H
hjxilinx 已提交
2698
    }
2699
  }
2700 2701
}

2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId) {
  assert(pTagColList != NULL && numOfTags > 0);

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

  return NULL;
}

H
Haojun Liao 已提交
2714

H
Haojun Liao 已提交
2715 2716
void setTagVal_rv(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2717

H
Haojun Liao 已提交
2718 2719 2720 2721
  SExprInfo *pExpr  = pOperatorInfo->pExpr;
  SQuery    *pQuery = pRuntimeEnv->pQuery;

  SExprInfo* pExprInfo = &pExpr[0];
H
Haojun Liao 已提交
2722 2723 2724
  if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQuery->stableQuery) {
    assert(pExprInfo->base.numOfParams == 1);

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

2728
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2729 2730 2731 2732
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
H
Haojun Liao 已提交
2733

H
Haojun Liao 已提交
2734 2735 2736 2737 2738 2739 2740 2741 2742
    for (int32_t idx = 0; idx < numOfOutput; ++idx) {
      SExprInfo* pLocalExprInfo = &pExpr[idx];

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

      // todo use tag column index to optimize performance
H
Haojun Liao 已提交
2743 2744
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type,
                           pLocalExprInfo->bytes);
H
Haojun Liao 已提交
2745 2746 2747 2748

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
2749
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2750 2751 2752 2753 2754
      }

      offset += pLocalExprInfo->bytes;
    }

H
Haojun Liao 已提交
2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
    if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
      //todo : use index to avoid iterator all possible output columns
      for(int32_t i = 0; i < numOfOutput; ++i) {
        if(pExpr[i].base.functionId != TSDB_FUNC_STDDEV_DST) {
          continue;
        }

        SSqlFuncMsg* pFuncMsg = &pExpr[i].base;

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

        // TODO use hash to speedup this loop
        int32_t numOfGroup = (int32_t) taosArrayGetSize(pRuntimeEnv->prevResult);
        for(int32_t j = 0; j < numOfGroup; ++j) {
          SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, j);
          if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
            int32_t numOfCols = (int32_t) taosArrayGetSize(p->pResult);
            for(int32_t k = 0; k < numOfCols; ++k) {
              SStddevInterResult* pres = taosArrayGet(p->pResult, k);
              if (pres->colId == pFuncMsg->colInfo.colId) {
                pCtx[i].param[0].arr = pres->pResult;
                break;
              }
            }
          }
        }
      }
    }

H
Haojun Liao 已提交
2785
    // set the join tag for first column
H
Haojun Liao 已提交
2786
    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;
H
Haojun Liao 已提交
2787 2788 2789 2790
    if (pQuery->stableQuery &&
       (pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) &&
       (pRuntimeEnv->pTsBuf != NULL) &&
        pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
2791 2792 2793
      assert(pFuncMsg->numOfParams == 1);

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

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

2798
      int16_t tagType = pCtx[0].tag.nType;
H
Haojun Liao 已提交
2799
      if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
2800
        qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%s", pRuntimeEnv->qinfo,
2801
               pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz);
H
Haojun Liao 已提交
2802
      } else {
H
Haojun Liao 已提交
2803
        qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pRuntimeEnv->qinfo,
2804
               pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64);
H
Haojun Liao 已提交
2805 2806 2807 2808
      }
    }
  }
}
2809

2810
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878
  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);
  }
}

2879
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
2880
  SQuery* pQuery = pRuntimeEnv->pQuery;
2881
  int32_t numOfCols = pQuery->numOfOutput;
2882
  printf("super table query intermediate result, total:%d\n", numOfRows);
2883

2884 2885
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2886

H
Haojun Liao 已提交
2887
      switch (pQuery->pExpr1[i].type) {
2888
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2889 2890
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
2891 2892 2893 2894 2895
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2896
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2897 2898
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2899
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2900 2901
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2902
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2903 2904
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2905
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2906 2907 2908 2909 2910 2911 2912
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2913
void copyResToQueryResultBuf_rv(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2914
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2915
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2916 2917

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2918
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2919 2920 2921
    // 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 已提交
2922
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2923 2924 2925 2926 2927 2928 2929
        return;
      }
    }

    doCopyToSData_rv(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2930
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2931 2932
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2933
        break;
H
Haojun Liao 已提交
2934 2935 2936
      }
    }

H
Haojun Liao 已提交
2937 2938 2939 2940
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2941
    }
H
Haojun Liao 已提交
2942

H
Haojun Liao 已提交
2943 2944
}

2945 2946 2947 2948
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
2949

2950 2951
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
2952

2953 2954
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
2955 2956

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

H
Haojun Liao 已提交
2960 2961
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2962
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
2963

H
Haojun Liao 已提交
2964 2965 2966
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2967

H
Haojun Liao 已提交
2968 2969 2970 2971
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
2972

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

H
Haojun Liao 已提交
2978
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
2979
    }
H
Haojun Liao 已提交
2980 2981
  }
}
H
Haojun Liao 已提交
2982

H
Haojun Liao 已提交
2983 2984 2985
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
2986 2987 2988
  }
}

H
Haojun Liao 已提交
2989 2990 2991 2992 2993 2994
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
2995

H
Haojun Liao 已提交
2996 2997 2998 2999 3000 3001
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid) {
  SQLFunctionCtx* pCtx           = pInfo->pCtx;
  SSDataBlock* pDataBlock        = pInfo->pRes;
  int32_t* rowCellInfoOffset     = pInfo->rowCellInfoOffset;
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;

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

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

H
Haojun Liao 已提交
3008 3009 3010 3011 3012 3013 3014 3015 3016 3017
    /*
     * set the output buffer information and intermediate buffer
     * not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc.
     */
    SResultRowCellInfo* pCellInfo = getResultCell(pRow, i, rowCellInfoOffset);
    RESET_RESULT_INFO(pCellInfo);

    pCtx[i].resultInfo = pCellInfo;
    pCtx[i].pOutput = pData->pData;
    assert(pCtx[i].pOutput != NULL);
3018

H
Haojun Liao 已提交
3019 3020 3021 3022 3023
    // set the timestamp output buffer for top/bottom/diff query
    int32_t functionId = pCtx[i].functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
    }
3024
  }
3025

H
Haojun Liao 已提交
3026 3027
  initCtxOutputBuf_rv(pCtx, pDataBlock->info.numOfCols);
}
3028

H
Haojun Liao 已提交
3029 3030 3031
void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) {
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
  SSDataBlock* pDataBlock = pBInfo->pRes;
3032

H
Haojun Liao 已提交
3033 3034 3035 3036 3037 3038 3039
  int32_t newSize = pDataBlock->info.rows + numOfInputRows;
  if (pInfo->bufCapacity < newSize) {
    for(int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
      char* p = realloc(pColInfo->pData, newSize * pColInfo->info.bytes);
      if (p != NULL) {
        pColInfo->pData = p;
3040

H
Haojun Liao 已提交
3041 3042 3043 3044 3045
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        pInfo->bufCapacity = newSize;
      } else {
        // longjmp
3046 3047
      }
    }
H
Haojun Liao 已提交
3048
  }
3049

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

H
Haojun Liao 已提交
3054 3055 3056 3057
    // re-estabilish output buffer pointer.
    int32_t functionId = pBInfo->pCtx[i].functionId;
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
      pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[0].pOutput;
B
Bomin Zhang 已提交
3058
    }
H
Haojun Liao 已提交
3059 3060
  }
}
3061

H
Haojun Liao 已提交
3062 3063 3064 3065 3066
void initCtxOutputBuf_rv(SQLFunctionCtx* pCtx, int32_t size) {
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3067 3068
    }

H
Haojun Liao 已提交
3069
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3070
  }
H
Haojun Liao 已提交
3071
}
3072

H
Haojun Liao 已提交
3073
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3074
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3075
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3076 3077
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3078 3079
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3080 3081
  }
}
3082

H
Haojun Liao 已提交
3083 3084
static void setEnvBeforeReverseScan_rv(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  SQuery *pQuery = pRuntimeEnv->pQuery;
3085

H
Haojun Liao 已提交
3086 3087 3088 3089
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3090
  }
3091

H
Haojun Liao 已提交
3092 3093 3094 3095 3096
  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
  SWITCH_ORDER(pQuery->order.order);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3097
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3098 3099 3100 3101
  switchCtxOrder(pCtx, numOfOutput);

//  disableFuncInReverseScan(pRuntimeEnv, pResultRowInfo, pCtx, numOfOutput);
  setupQueryRangeForReverseScan(pRuntimeEnv);
3102 3103
}

H
Haojun Liao 已提交
3104 3105
void finalizeQueryResult_rv(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3106
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3107 3108

  int32_t numOfOutput = pOperator->numOfOutput;
H
Haojun Liao 已提交
3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
  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;
      }

H
Haojun Liao 已提交
3121
      setResultOutputBuf_rv(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3122 3123 3124 3125 3126 3127 3128 3129 3130

      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
       */
3131
      buf->numOfRows = (uint16_t)getNumOfResult_rv(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3132 3133 3134 3135 3136 3137 3138 3139 3140
    }

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

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

3145 3146 3147 3148
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3149

3150 3151 3152
  return false;
}

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

H
hjxilinx 已提交
3156 3157
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3158

3159
  pTableQueryInfo->pTable = pTable;
3160
  pTableQueryInfo->cur.vgroupIndex = -1;
3161

H
Haojun Liao 已提交
3162
  // set more initial size of interval/groupby query
3163
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
3164
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3165
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3166 3167 3168
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3169
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3170 3171
  }

3172 3173 3174
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3175
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3176 3177 3178
  if (pTableQueryInfo == NULL) {
    return;
  }
3179

H
Haojun Liao 已提交
3180
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3181
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3182 3183
}

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

H
Haojun Liao 已提交
3189
  int16_t offset = 0;
3190
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3191
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
H
Haojun Liao 已提交
3192
    if (pCtx->resultInfo->initialized && pCtx->resultInfo->complete) {
H
Haojun Liao 已提交
3193
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3194 3195
      continue;
    }
3196

H
Haojun Liao 已提交
3197 3198
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, bufPage, pResult->offset, offset);
    offset += pCtx[i].outputBytes;
3199

3200
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3201
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3202
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3203
    }
3204

3205 3206
    if (!pCtx[i].resultInfo->initialized) {
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3207 3208 3209 3210
    }
  }
}

H
Haojun Liao 已提交
3211
void setExecutionContext_rv(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int32_t numOfOutput,
H
Haojun Liao 已提交
3212
    int32_t groupIndex, TSKEY nextKey) {
3213
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->pQuery->current;
3214

3215 3216 3217 3218 3219
  // lastKey needs to be updated
  pTableQueryInfo->lastKey = nextKey;
  if (pRuntimeEnv->prevGroupId != INT32_MIN && pRuntimeEnv->prevGroupId == groupIndex) {
    return;
  }
H
Haojun Liao 已提交
3220

3221
  int64_t uid = 0;
H
Haojun Liao 已提交
3222
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, &pInfo->resultRowInfo, (char *)&groupIndex,
3223 3224
      sizeof(groupIndex), true, uid);
  assert (pResultRow != NULL);
3225

3226 3227 3228 3229 3230
  /*
   * not assign result buffer yet, add new result buffer
   * all group belong to one result set, and each group result has different group id so set the id to be one
   */
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
3231
    if (addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize) !=
3232 3233
        TSDB_CODE_SUCCESS) {
      return;
3234 3235 3236
    }
  }

3237 3238
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
H
Haojun Liao 已提交
3239 3240
  setResultOutputBuf_rv(pRuntimeEnv, pResultRow, pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
  initCtxOutputBuf_rv(pInfo->pCtx, numOfOutput);
3241 3242
}

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

H
Haojun Liao 已提交
3248
  int16_t offset = 0;
3249
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3250 3251
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, page, pResult->offset, offset);
    offset += pCtx[i].outputBytes;
3252

3253 3254 3255
    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;
3256 3257
    }

3258 3259 3260 3261
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3262
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3263 3264 3265
  }
}

3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310
//int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, STableQueryInfo *pTableQueryInfo) {
//  SQuery* pQuery = pRuntimeEnv->pQuery;
//
//  assert(pRuntimeEnv->pTsBuf != NULL);
//
//  // both the master and supplement scan needs to set the correct ts comp start position
//  tVariant* pTag = &pRuntimeEnv->pCtx[0].tag;
//
//  if (pTableQueryInfo->cur.vgroupIndex == -1) {
//    tVariantAssign(&pTableQueryInfo->tag, pTag);
//
//    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, &pTableQueryInfo->tag);
//
//    // failed to find data with the specified tag value and vnodeId
//    if (!tsBufIsValidElem(&elem)) {
//      if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
//        qError("QInfo:%p failed to find tag:%s in ts_comp", pRuntimeEnv->qinfo, pTag->pz);
//      } else {
//        qError("QInfo:%p failed to find tag:%" PRId64 " in ts_comp", pRuntimeEnv->qinfo, pTag->i64);
//      }
//
//      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) {
//      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);
//    } else {
//      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);
//    }
//
//  } else {
//    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
//
//    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", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
//    } else {
//      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);
//    }
//  }
//
//  return 0;
//}

H
Haojun Liao 已提交
3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349
int32_t setParamValue(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput,
    SExprInfo* pExpr) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

  if (pRuntimeEnv->prevResult == NULL || pQuery->groupbyColumn) {
    return TSDB_CODE_SUCCESS;
  }

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

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

    // TODO use hash to speedup this loop
    int32_t numOfGroup = (int32_t) taosArrayGetSize(pRuntimeEnv->prevResult);
    for(int32_t j = 0; j < numOfGroup; ++j) {
      SInterResult *p = taosArrayGet(pRuntimeEnv->prevResult, j);
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
        int32_t numOfCols = (int32_t) taosArrayGetSize(p->pResult);
        for(int32_t k = 0; k < numOfCols; ++k) {
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

  return 0;
}
3350

3351 3352 3353 3354 3355 3356 3357 3358 3359
/*
 * 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 已提交
3360
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3361 3362 3363
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3364

H
Haojun Liao 已提交
3365 3366 3367
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3368

H
Haojun Liao 已提交
3369 3370
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
3371

H
Haojun Liao 已提交
3372 3373 3374 3375 3376 3377
  /**
   * 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 已提交
3378
  STimeWindow w = TSWINDOW_INITIALIZER;
3379

H
Haojun Liao 已提交
3380 3381 3382
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
3383

H
Haojun Liao 已提交
3384 3385 3386
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
3387
    }
H
Haojun Liao 已提交
3388

H
Haojun Liao 已提交
3389
    pWindowResInfo->prevSKey = w.skey;
3390
  }
H
Haojun Liao 已提交
3391 3392

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3393 3394 3395
}

bool requireTimestamp(SQuery *pQuery) {
3396
  for (int32_t i = 0; i < pQuery->numOfOutput; i++) {
H
Haojun Liao 已提交
3397
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
H
Haojun Liao 已提交
3398
    if ((aAggs[functionId].status & TSDB_FUNCSTATE_NEED_TS) != 0) {
3399 3400 3401 3402 3403 3404
      return true;
    }
  }
  return false;
}

3405
//static int32_t doCopyToSData(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType) {
H
Haojun Liao 已提交
3406
//  void* qinfo = pRuntimeEnv->qinfo;
3407 3408 3409
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//
//  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3410
//  int32_t numOfResult = pRuntimeEnv->resultInfo.rows; // there are already exists result rows
3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433
//
//  int32_t start = 0;
//  int32_t step = -1;
//
//  qDebug("QInfo:%p start to copy data from windowResInfo to output buf", 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
H
Haojun Liao 已提交
3434 3435
//    if (numOfRowsToCopy > (pRuntimeEnv->resultInfo.capacity - numOfResult)) {
//      int32_t newSize = pRuntimeEnv->resultInfo.capacity + (numOfRowsToCopy - numOfResult);
H
Haojun Liao 已提交
3436
//      expandBuffer(pRuntimeEnv, newSize, pRuntimeEnv->qinfo);
3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450
//    }
//
//    pGroupResInfo->index += 1;
//
//    tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pRow->pageId);
//    for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
//      int32_t size = pRuntimeEnv->pCtx[j].outputBytes;
//
//      char *out = pQuery->sdata[j]->data + numOfResult * size;
//      char *in  = getPosInResultPage(pRuntimeEnv, j, pRow, page);
//      memcpy(out, in, size * numOfRowsToCopy);
//    }
//
//    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3451
//    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
3452 3453 3454 3455 3456 3457 3458
//      break;
//    }
//  }
//
//  qDebug("QInfo:%p copy data to query buf completed", qinfo);
//  return numOfResult;
//}
3459 3460

/**
H
Haojun Liao 已提交
3461
 * copyToOutputBuf support copy data in ascending/descending order
3462 3463 3464 3465 3466 3467 3468
 * 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 已提交
3469 3470 3471 3472 3473

static int32_t doCopyToSData_rv(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3474
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499

  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;

    pGroupResInfo->index += 1;

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

    int16_t offset = 0;
H
Haojun Liao 已提交
3502 3503 3504 3505 3506
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, j);
      int32_t bytes = pColInfoData->info.bytes;

      char *out = pColInfoData->pData + numOfResult * bytes;
H
Haojun Liao 已提交
3507
      char *in  = getPosInResultPage(pQuery, page, pRow->offset, offset);
H
Haojun Liao 已提交
3508
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3509 3510

      offset += bytes;
H
Haojun Liao 已提交
3511 3512 3513
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3514
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525
      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 已提交
3526

H
Haojun Liao 已提交
3527
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3528
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3529 3530 3531 3532 3533 3534
    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 已提交
3535 3536 3537

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

H
Haojun Liao 已提交
3538 3539 3540 3541 3542
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
    w->ekey = *(int64_t*)(pInfoData->pData + TSDB_KEYSIZE * (pBlock->info.rows - 1));
  }
3543 3544
}

3545
static void updateWindowResNumOfRes_rv(SQueryRuntimeEnv *pRuntimeEnv,
H
Haojun Liao 已提交
3546
    SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
3547
  SQuery *pQuery = pRuntimeEnv->pQuery;
3548

3549
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3550 3551 3552
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
3553

3554 3555
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3556

3557 3558
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3559 3560
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3561
      }
H
Haojun Liao 已提交
3562

H
Haojun Liao 已提交
3563
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3564
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3565 3566 3567 3568
    }
  }
}

H
Haojun Liao 已提交
3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606
//bool hasNotReturnedResults(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
////  SFillInfo *pFillInfo = pRuntimeEnv->pFillInfo;
//
//  if (!Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
//      return false;
//  }
//
//  if (pQuery->limit.limit > 0 && pRuntimeEnv->resultInfo.total >= pQuery->limit.limit) {
//    return false;
//  }
//
//  if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
//    // There are results not returned to client yet, so filling applied to the remain result is required firstly.
//    if (taosFillHasMoreResults(pFillInfo)) {
//      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.
//     */
//    int32_t numOfTotal = (int32_t)getNumOfResultsAfterFillGap(pFillInfo, pQuery->window.ekey, (int32_t)pRuntimeEnv->resultInfo.capacity);
//    return numOfTotal > 0;
//  } else { // there are results waiting for returned to client.
//    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && hasRemainDataInCurrentGroup(pGroupResInfo) &&
//        (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery))) {
//      return true;
//    }
//  }
//
//  return false;
//}
H
Haojun Liao 已提交
3607

3608
static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) {
H
Haojun Liao 已提交
3609 3610
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3611

H
Haojun Liao 已提交
3612
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3613

H
Haojun Liao 已提交
3614
  if (pQuery->pExpr2 == NULL) {
H
Haojun Liao 已提交
3615 3616 3617 3618
    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 已提交
3619 3620 3621
    }
  } else {
    for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3622 3623 3624
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3625
    }
3626
  }
3627

H
Haojun Liao 已提交
3628
  int32_t numOfTables = (int32_t) taosHashGetSize(pQInfo->arrTableIdInfo);
weixin_48148422's avatar
weixin_48148422 已提交
3629 3630
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3631

3632
  int32_t total = 0;
3633
  STableIdInfo* item = taosHashIterate(pQInfo->arrTableIdInfo, NULL);
3634

3635
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3636
    STableIdInfo* pDst = (STableIdInfo*)data;
3637 3638 3639 3640
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3641
    data += sizeof(STableIdInfo);
3642 3643 3644
    total++;

    qDebug("QInfo:%p set subscribe info, tid:%d, uid:%"PRIu64", skey:%"PRId64, pQInfo, item->tid, item->uid, item->key);
3645
    item = taosHashIterate(pQInfo->arrTableIdInfo, item);
weixin_48148422's avatar
weixin_48148422 已提交
3646 3647
  }

3648
  qDebug("QInfo:%p set %d subscribe info", pQInfo, total);
H
Haojun Liao 已提交
3649
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3650 3651
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3652
  }
3653 3654
}

H
Haojun Liao 已提交
3655
int32_t doFillGapsInResults_rv(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3656 3657 3658 3659 3660 3661
  void** p = calloc(pFillInfo->numOfCols, POINTER_BYTES);
  for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
    SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i);
    p[i] = pColInfoData->pData;
  }

H
Haojun Liao 已提交
3662
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3663
  tfree(p);
H
Haojun Liao 已提交
3664 3665
  return pOutput->info.rows;
}
3666

H
Haojun Liao 已提交
3667
void queryCostStatis(SQInfo *pQInfo) {
3668
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3669
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3670

H
Haojun Liao 已提交
3671
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3672
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3673 3674
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3675 3676 3677
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3678
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3679 3680 3681 3682 3683 3684 3685
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3686

H
Haojun Liao 已提交
3687 3688 3689
  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 已提交
3690
         pSummary->loadBlocks, pSummary->totalRows, pSummary->totalCheckedRows);
3691

3692
  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 已提交
3693
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
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
//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//  STableQueryInfo* pTableQueryInfo = pQuery->current;
//
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
//
//  if (pQuery->limit.offset == pBlockInfo->rows) {  // current block will ignore completed
//    pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step;
//    pQuery->limit.offset = 0;
//    return;
//  }
//
//  if (QUERY_IS_ASC_QUERY(pQuery)) {
//    pQuery->pos = (int32_t)pQuery->limit.offset;
//  } else {
//    pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1;
//  }
//
//  assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1);
//
//  SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//  SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//  // update the pQuery->limit.offset value, and pQuery->pos value
//  TSKEY *keys = (TSKEY *) pColInfoData->pData;
//
//  // update the offset value
//  pTableQueryInfo->lastKey = keys[pQuery->pos];
//  pQuery->limit.offset = 0;
//
//  int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//
H
Haojun Liao 已提交
3728
//  qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, pRuntimeEnv->qinfo,
3729 3730
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3731

Y
yihaoDeng 已提交
3732 3733 3734 3735 3736 3737
static void freeTableBlockDist(STableBlockDist *pTableBlockDist) {
  if (pTableBlockDist != NULL) {
    taosArrayDestroy(pTableBlockDist->dataBlockInfos); 
    free(pTableBlockDist);
  }
}
H
Haojun Liao 已提交
3738

Y
yihaoDeng 已提交
3739
static int32_t getPercentileFromSortedArray(const SArray* pArray, double rate) {
Y
yihaoDeng 已提交
3740
  int32_t len = (int32_t)taosArrayGetSize(pArray);
Y
yihaoDeng 已提交
3741
  if (len <= 0) {
Y
yihaoDeng 已提交
3742 3743 3744 3745 3746 3747
    return 0;
  }
  assert(rate >= 0 && rate <= 1.0);
  int idx = (int32_t)((len - 1) * rate);
  return ((SDataBlockInfo *)(taosArrayGet(pArray, idx)))->rows;
}
H
Haojun Liao 已提交
3748

Y
yihaoDeng 已提交
3749
static int compareBlockInfo(const void *pLeft, const void *pRight) {
Y
yihaoDeng 已提交
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760
  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;
  }
H
Haojun Liao 已提交
3761
#if 0
Y
yihaoDeng 已提交
3762 3763 3764 3765
  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++) {
H
Haojun Liao 已提交
3766 3767
    SFileBlockInfo *blockInfo = taosArrayGet(blockInfos, i);
    int64_t rows = blockInfo->numOfRows;
Y
yihaoDeng 已提交
3768 3769 3770 3771
    min = MIN(min, rows);       
    max = MAX(max, rows);
    totalRows += rows;  
  }
Y
yihaoDeng 已提交
3772
  avg = totalBlocks > 0 ? (int64_t)(totalRows/totalBlocks) : 0;
Y
yihaoDeng 已提交
3773 3774

  taosArraySort(blockInfos, compareBlockInfo);
H
Haojun Liao 已提交
3775 3776 3777 3778 3779 3780 3781 3782 3783 3784
#endif
//  int sz = sprintf(pTableBlockDist->result,
//          "summary: \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"]",
//          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);
}
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799
//void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//
//  if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0) {
//    return;
//  }
//
//  pQuery->pos = 0;
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
//
//  STableQueryInfo* pTableQueryInfo = pQuery->current;
//  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pQueryHandle)) {
H
Haojun Liao 已提交
3800
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
//      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//    }
//
//    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
//
//    if (pQuery->limit.offset > blockInfo.rows) {
//      pQuery->limit.offset -= blockInfo.rows;
//      pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.window.ekey : blockInfo.window.skey;
//      pTableQueryInfo->lastKey += step;
//
H
Haojun Liao 已提交
3811
//      qDebug("QInfo:%p skip rows:%d, offset:%" PRId64, pRuntimeEnv->qinfo, blockInfo.rows,
3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822
//             pQuery->limit.offset);
//    } else {  // find the appropriated start position in current block
//      updateOffsetVal(pRuntimeEnv, &blockInfo);
//      break;
//    }
//  }
//
//  if (terrno != TSDB_CODE_SUCCESS) {
//    longjmp(pRuntimeEnv->env, terrno);
//  }
//}
H
Haojun Liao 已提交
3823

3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
//  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 =
//        getNextQualifiedWindow(pQuery, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
//    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;
//    int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
//
//    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//    pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
//
//    qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
H
Haojun Liao 已提交
3860
//           pRuntimeEnv->qinfo, pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 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 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983
//           pQuery->current->lastKey);
//
//    return key;
//  } else {  // do nothing
//    pQuery->window.skey      = tw.skey;
//    pWindowResInfo->prevSKey = tw.skey;
//    pTableQueryInfo->lastKey = tw.skey;
//
//    return tw.skey;
//  }
//
//  return true;
//}

//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//  if (QUERY_IS_ASC_QUERY(pQuery)) {
//    assert(*start <= pQuery->current->lastKey);
//  } else {
//    assert(*start >= pQuery->current->lastKey);
//  }
//
//  // if queried with value filter, do NOT forward query start position
//  if (pQuery->limit.offset <= 0 || pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
//    return true;
//  }
//
//  /*
//   * 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
//   *    not valid. otherwise, we only forward pQuery->limit.offset number of points
//   */
//  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
//
//  STimeWindow w = TSWINDOW_INITIALIZER;
//  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
//
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//  STableQueryInfo *pTableQueryInfo = pQuery->current;
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
//    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
//
//    if (QUERY_IS_ASC_QUERY(pQuery)) {
//      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
//        getAlignQueryTimeWindow(pQuery, blockInfo.window.skey, blockInfo.window.skey, pQuery->window.ekey, &w);
//        pWindowResInfo->prevSKey = w.skey;
//      }
//    } else {
//      getAlignQueryTimeWindow(pQuery, blockInfo.window.ekey, pQuery->window.ekey, blockInfo.window.ekey, &w);
//      pWindowResInfo->prevSKey = w.skey;
//    }
//
//    // the first time window
//    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQuery);
//
//    while (pQuery->limit.offset > 0) {
//      STimeWindow tw = win;
//
//      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
//        pQuery->limit.offset -= 1;
//        pWindowResInfo->prevSKey = win.skey;
//
//        // current time window is aligned with blockInfo.window.ekey
//        // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL;
//        if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) {
//          pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
//        }
//      }
//
//      if (pQuery->limit.offset == 0) {
//        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//        return true;
//      }
//
//      // current window does not ended in current data block, try next data block
//      getNextTimeWindow(pQuery, &tw);
//
//      /*
//       * If the next time window still starts from current data block,
//       * load the primary timestamp column first, and then find the start position for the next queried time window.
//       * Note that only the primary timestamp column is required.
//       * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required
//       * time window resides in current data block.
//       */
//      if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) {
//
//        SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//        SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//        if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
//          pQuery->limit.offset -= 1;
//        }
//
//        if (pQuery->limit.offset == 0) {
//          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//          return true;
//        } else {
//          tw = win;
//          int32_t startPos =
//              getNextQualifiedWindow(pQuery, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
//          assert(startPos >= 0);
//
//          // set the abort info
//          pQuery->pos = startPos;
//          pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos];
//          pWindowResInfo->prevSKey = tw.skey;
//          win = tw;
//        }
//      } else {
//        break;  // offset is not 0, and next time window begins or ends in the next block.
//      }
//    }
//  }
//
//  // check for error
//  if (terrno != TSDB_CODE_SUCCESS) {
//    longjmp(pRuntimeEnv->env, terrno);
//  }
//
//  return true;
//}
3984

H
Haojun Liao 已提交
3985 3986
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

H
Haojun Liao 已提交
3987 3988 3989
static void setTableQueryHandle(SQueryRuntimeEnv* pRuntimeEnv, int32_t tableIndex) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000
  int32_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);

  STableQueryInfo* pCheckInfo = NULL;
  if (numOfGroup == 1) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, 0);
    pCheckInfo = taosArrayGetP(group, tableIndex);
  } else {
    assert(numOfGroup == pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, tableIndex);
    pCheckInfo = taosArrayGetP(group, 0);
  }
H
Haojun Liao 已提交
4001

H
Haojun Liao 已提交
4002
  // handle the first table
H
Haojun Liao 已提交
4003 4004 4005 4006 4007
  STsdbQueryCond cond = {
      .twindow   = {pCheckInfo->lastKey, pCheckInfo->win.ekey},
      .order     = pQuery->order.order,
      .colList   = pQuery->colList,
      .numOfCols = pQuery->numOfCols,
H
Haojun Liao 已提交
4008
      .loadExternalRows = isPointInterpoQuery(pQuery),
H
Haojun Liao 已提交
4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029
  };

  SArray *g1 = taosArrayInit(1, POINTER_BYTES);
  SArray *tx = taosArrayInit(1, sizeof(STableKeyInfo));

  STableKeyInfo info = {.pTable = pCheckInfo->pTable, .lastKey = pCheckInfo->lastKey};
  taosArrayPush(tx, &info);

  taosArrayPush(g1, &tx);
  STableGroupInfo gp = {.numOfTables = 1, .pGroupList = g1};

  if (pRuntimeEnv->pQueryHandle == NULL) {
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQuery->tsdb, &cond, &gp, pRuntimeEnv->qinfo, &pQuery->memRef);
  } else {
    tsdbResetQueryHandleForNewTable(pRuntimeEnv->pQueryHandle, &cond, &gp);
  }

  taosArrayDestroy(tx);
  taosArrayDestroy(g1);
}

B
Bomin Zhang 已提交
4030
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
4031
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
4032 4033
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
Haojun Liao 已提交
4034
  // TODO set the tags scan handle
B
Bomin Zhang 已提交
4035
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
4036
    return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
4037 4038 4039
  } else if (isTsCompQuery(pQuery)) {
    setTableQueryHandle(pRuntimeEnv, 0);
    return terrno;
B
Bomin Zhang 已提交
4040 4041
  }

H
Haojun Liao 已提交
4042
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
S
TD-1057  
Shengliang Guan 已提交
4043

B
Bomin Zhang 已提交
4044
  if (!isSTableQuery
H
Haojun Liao 已提交
4045
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
4046
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
4047
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
4048
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
4049
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
4050
  ) {
H
Haojun Liao 已提交
4051
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
4052 4053
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
4054
  }
B
Bomin Zhang 已提交
4055

B
Bomin Zhang 已提交
4056
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
4057
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
4058
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
4059

H
Haojun Liao 已提交
4060 4061
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
4062
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
4063
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
4064
    } else {
H
Haojun Liao 已提交
4065
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
4066
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
4067
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
4068

H
Haojun Liao 已提交
4069 4070 4071
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
4072

H
Haojun Liao 已提交
4073 4074 4075
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
4076 4077
      }
    }
4078
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4079
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
4080
  } else {
H
Haojun Liao 已提交
4081
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
4082
  }
4083

B
Bomin Zhang 已提交
4084
  return terrno;
B
Bomin Zhang 已提交
4085 4086
}

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

H
Haojun Liao 已提交
4090
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
4091 4092 4093 4094
  if (pFillCol == NULL) {
    return NULL;
  }

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

4098
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
4099
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
4100
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
4101
    pFillCol[i].tagIndex   = -2;
4102 4103
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
4104
    pFillCol[i].fillVal.i  = fillVal[i];
4105

4106 4107
    offset += pExprInfo->bytes;
  }
4108

4109 4110 4111
  return pFillCol;
}

4112
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *tsdb, int32_t vgId, bool isSTableQuery) {
4113 4114 4115
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
H
Haojun Liao 已提交
4116
  pQuery->tsdb  = tsdb;
H
Haojun Liao 已提交
4117

H
Haojun Liao 已提交
4118 4119
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
4120
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
H
Haojun Liao 已提交
4121
  pQuery->stabledev = isStabledev(pQuery);
H
Haojun Liao 已提交
4122

4123
  pRuntimeEnv->prevResult = prevResult;
H
Haojun Liao 已提交
4124
  pRuntimeEnv->qinfo = pQInfo;
4125

4126
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
4127

H
Haojun Liao 已提交
4128
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
4129 4130 4131
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
4132

H
Haojun Liao 已提交
4133
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
4134
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
4135 4136 4137
  pQuery->stableQuery = isSTableQuery;
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);

H
Haojun Liao 已提交
4138
  pRuntimeEnv->groupResInfo.totalGroup = isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0;
4139 4140

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
4141
  pRuntimeEnv->pTsBuf = pTsBuf;
4142
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4143

4144
  if (onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
4145
    // TODO refactor.
H
Haojun Liao 已提交
4146
    pRuntimeEnv->resultInfo.capacity = 4096;
H
Haojun Liao 已提交
4147
    pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
4148
  } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4149
    pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, isPointInterpoQuery(pQuery));
4150
  } else if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
4151
    pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
4152
  } else {
H
Haojun Liao 已提交
4153
    pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
4154 4155
  }

H
Haojun Liao 已提交
4156
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4157 4158
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4159 4160
  }

4161 4162
  int32_t ps = DEFAULT_PAGE_SIZE;
  int32_t rowsize = 0;
H
Haojun Liao 已提交
4163
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize);
H
Haojun Liao 已提交
4164
  int32_t TENMB = 1024*1024*10;
4165

H
Haojun Liao 已提交
4166
  if (isSTableQuery && !onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
4167
    code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo);
4168 4169 4170
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
H
Haojun Liao 已提交
4171
  } else if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || (!isSTableQuery)) {
4172
    getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize);
H
Haojun Liao 已提交
4173
    code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo);
4174 4175 4176 4177 4178
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
  }

H
Haojun Liao 已提交
4179
  // create runtime environment
H
Haojun Liao 已提交
4180
  int32_t numOfTables = pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4181
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4182
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables);
H
Haojun Liao 已提交
4183 4184 4185 4186
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4187
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4188
  return TSDB_CODE_SUCCESS;
4189 4190
}

H
Haojun Liao 已提交
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204
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 已提交
4205
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
4206 4207 4208 4209
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
4210
      .loadExternalRows = false,
4211 4212
  };

H
Haojun Liao 已提交
4213
  TIME_WINDOW_COPY(cond.twindow, *win);
4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229
  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;
}

4230
static UNUSED_FUNC void updateTableIdInfo(SQuery* pQuery, SHashObj* pTableIdInfo) {
4231 4232 4233 4234 4235 4236 4237 4238 4239 4240
  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));
  }
}

H
Haojun Liao 已提交
4241 4242 4243 4244
static void doCloseAllTimeWindow(SQueryRuntimeEnv* pRuntimeEnv) {
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  for (int32_t i = 0; i < numOfGroup; ++i) {
    SArray* group = GET_TABLEGROUP(pRuntimeEnv, i);
4245

H
Haojun Liao 已提交
4246 4247 4248 4249
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4250 4251
    }
  }
4252 4253
}

H
Haojun Liao 已提交
4254
static SSDataBlock* doTableScanImpl(STableScanInfo *pTableScanInfo) {
H
Haojun Liao 已提交
4255 4256
  SSDataBlock*     pBlock = &pTableScanInfo->block;
  SQuery*          pQuery = pTableScanInfo->pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4257
  STableGroupInfo* pTableGroupInfo = &pTableScanInfo->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4258

H
Haojun Liao 已提交
4259 4260
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4261

H
Haojun Liao 已提交
4262 4263
    // todo check for query cancel
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4264

H
Haojun Liao 已提交
4265
    if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4266 4267
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4268 4269 4270 4271 4272 4273 4274 4275
      if (pTableQueryInfo == NULL) {
        break;
      }

      pQuery->current = *pTableQueryInfo;
      doTableQueryInfoTimeWindowCheck(pQuery, *pTableQueryInfo);
    }

H
Haojun Liao 已提交
4276
    // this function never returns error?
H
Haojun Liao 已提交
4277
    uint32_t status;
H
Haojun Liao 已提交
4278
    int32_t  code = loadDataBlockOnDemand_rv(pTableScanInfo->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4279 4280 4281
    if (code != TSDB_CODE_SUCCESS) {
      longjmp(pTableScanInfo->pRuntimeEnv->env, code);
    }
H
Haojun Liao 已提交
4282

H
Haojun Liao 已提交
4283
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4284
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4285
      continue;
H
Haojun Liao 已提交
4286 4287
    }

H
Haojun Liao 已提交
4288 4289 4290 4291
    if (pTableScanInfo->loadExternalRows) {
       pTableScanInfo->externalLoaded = true;
    }

H
Haojun Liao 已提交
4292 4293
    return pBlock;
  }
H
Haojun Liao 已提交
4294

H
Haojun Liao 已提交
4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308
  if (pTableScanInfo->loadExternalRows && (!pTableScanInfo->externalLoaded)) {
    pBlock->pDataBlock = tsdbGetExternalRow(pTableScanInfo->pQueryHandle, &pBlock->info);
    pTableScanInfo->externalLoaded = true;

    if (pBlock->pDataBlock != NULL) {
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
      assert(*pTableQueryInfo != NULL);
      pQuery->current = *pTableQueryInfo;
    }

    return (pBlock->pDataBlock != NULL)? pBlock:NULL;
  }

H
Haojun Liao 已提交
4309
  return NULL;
H
Haojun Liao 已提交
4310 4311 4312
}

static SSDataBlock* doTableScan(void* param) {
H
Haojun Liao 已提交
4313 4314
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4315
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4316
  SQueryRuntimeEnv *pRuntimeEnv = pTableScanInfo->pRuntimeEnv;
H
Haojun Liao 已提交
4317
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4318

H
Haojun Liao 已提交
4319 4320
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;

H
Haojun Liao 已提交
4321
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4322
    SSDataBlock* p = doTableScanImpl(pTableScanInfo);
H
Haojun Liao 已提交
4323 4324
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4325 4326
    }

H
Haojun Liao 已提交
4327
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4328 4329 4330 4331 4332
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4333
    }
H
Haojun Liao 已提交
4334

H
Haojun Liao 已提交
4335
    // do prepare for the next round table scan operation
H
Haojun Liao 已提交
4336
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4337
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4338

H
Haojun Liao 已提交
4339
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4340
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4341

H
Haojun Liao 已提交
4342 4343 4344 4345 4346
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

H
Haojun Liao 已提交
4347 4348 4349
    pResultRowInfo->curIndex = 0;
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;

H
Haojun Liao 已提交
4350
    qDebug("QInfo:%p start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
4351
           pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4352 4353
  }

H
Haojun Liao 已提交
4354
  if (pTableScanInfo->reverseTimes > 0) {
4355
    setEnvBeforeReverseScan_rv(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4356

H
Haojun Liao 已提交
4357
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4358
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4359

H
Haojun Liao 已提交
4360
    qDebug("QInfo:%p start to reverse scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
4361
           pRuntimeEnv->qinfo, cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4362

H
Haojun Liao 已提交
4363 4364
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4365 4366
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4367 4368
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4369

H
Haojun Liao 已提交
4370 4371 4372 4373
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4374

H
Haojun Liao 已提交
4375
    SSDataBlock* p = doTableScanImpl(pTableScanInfo);
H
Haojun Liao 已提交
4376 4377
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4378 4379
    }
  }
H
Haojun Liao 已提交
4380

H
Haojun Liao 已提交
4381 4382 4383
  return NULL;
}

H
Haojun Liao 已提交
4384
static SSDataBlock* doSeqTableBlocksScan(void* param) {
H
Haojun Liao 已提交
4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404
  SOperatorInfo* pOperator = (SOperatorInfo*)param;

  STableScanInfo   *pTableScanInfo = pOperator->info;
  SQueryRuntimeEnv *pRuntimeEnv = pTableScanInfo->pRuntimeEnv;

  int32_t totalTables = pRuntimeEnv->tableqinfoGroupInfo.numOfTables;

  while (1) {
    SSDataBlock* p = doTableScanImpl(pTableScanInfo);
    if (p != NULL) {
      return p;
    }

    // try the next table
    if (++pTableScanInfo->tableIndex >= totalTables) {
      return NULL;
    }

    setTableQueryHandle(pRuntimeEnv, pTableScanInfo->tableIndex);
    pTableScanInfo->pQueryHandle = pRuntimeEnv->pQueryHandle;
H
Haojun Liao 已提交
4405
    pTableScanInfo->externalLoaded = false;
H
Haojun Liao 已提交
4406
  }
H
Haojun Liao 已提交
4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426
}

static SSDataBlock* doBlockInfoScan(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo*)param;

  STableScanInfo *pTableScanInfo = pOperator->info;

  STableBlockDist tableBlockDist = {0};
  tableBlockDist.dataBlockInfos  = taosArrayInit(512, sizeof(SFileBlockInfo));

  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, tableBlockDist.dataBlockInfos);
  tableBlockDist.numOfRowsInMemTable = tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);

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




H
Haojun Liao 已提交
4427 4428
}

H
Haojun Liao 已提交
4429
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4430 4431
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4432 4433
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4434
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4435
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4436 4437 4438
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->current      = 0;
  pInfo->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4439

H
Haojun Liao 已提交
4440
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4441
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4442
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4443 4444
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4445
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4446
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4447 4448 4449 4450

  return pOperator;
}

H
Haojun Liao 已提交
4451
SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, bool loadExternalRows) {
H
Haojun Liao 已提交
4452 4453
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));

H
Haojun Liao 已提交
4454 4455 4456 4457 4458 4459
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
  pInfo->order            = pRuntimeEnv->pQuery->order.order;
  pInfo->current          = 0;
  pInfo->pRuntimeEnv      = pRuntimeEnv;
H
Haojun Liao 已提交
4460
  pInfo->loadExternalRows = loadExternalRows;
H
Haojun Liao 已提交
4461 4462

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4463 4464
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4465 4466 4467 4468
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4469
  pOperator->exec         = doSeqTableBlocksScan;
H
Haojun Liao 已提交
4470

H
Haojun Liao 已提交
4471 4472 4473 4474 4475 4476
  return pOperator;
}

void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4477 4478 4479
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4480
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4481
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4482

H
Haojun Liao 已提交
4483 4484 4485
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4486
  } else if (pDownstream->operatorType == OP_TimeInterval) {
H
Haojun Liao 已提交
4487
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4488 4489 4490

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

H
Haojun Liao 已提交
4493
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4494
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4495

H
Haojun Liao 已提交
4496 4497 4498
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4499

H
Haojun Liao 已提交
4500
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4501
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4502

4503 4504
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4505 4506
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4507
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4508
    SArithOperatorInfo *pInfo = pDownstream->info;
4509

H
Haojun Liao 已提交
4510 4511 4512
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4513 4514 4515
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4516 4517
}

H
Haojun Liao 已提交
4518
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4519 4520 4521 4522
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4523
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4524
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4525 4526 4527
  pInfo->current      = 0;
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4528 4529

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4530 4531 4532 4533 4534
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4535 4536

  return pOptr;
H
Haojun Liao 已提交
4537 4538
}

H
Haojun Liao 已提交
4539
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4540 4541 4542
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4543
// this is a blocking operator
H
Haojun Liao 已提交
4544
static SSDataBlock* doAggregate(void* param) {
H
Haojun Liao 已提交
4545
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4546
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4547 4548
    return NULL;
  }
H
Haojun Liao 已提交
4549

H
Haojun Liao 已提交
4550
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4551 4552
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4553
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4554

H
Haojun Liao 已提交
4555
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4556
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
4557

H
Haojun Liao 已提交
4558
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4559

H
Haojun Liao 已提交
4560
  while(1) {
H
Haojun Liao 已提交
4561
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4562 4563 4564 4565
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4566
    setTagVal_rv(pOperator, pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
4567

H
Haojun Liao 已提交
4568
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4569
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4570 4571 4572
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4573
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4574 4575
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4576 4577
  }

H
Haojun Liao 已提交
4578
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4579
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4580

H
Haojun Liao 已提交
4581 4582
  finalizeQueryResult_rv(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset);
  pInfo->pRes->info.rows = getNumOfResult_rv(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4583

H
Haojun Liao 已提交
4584
  return pInfo->pRes;
H
Haojun Liao 已提交
4585 4586
}

H
Haojun Liao 已提交
4587
static SSDataBlock* doSTableAggregate(void* param) {
H
Haojun Liao 已提交
4588
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4589
  if (pOperator->status == OP_EXEC_DONE) {
4590 4591
    return NULL;
  }
H
Haojun Liao 已提交
4592

H
Haojun Liao 已提交
4593
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4594 4595
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4596
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4597

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

H
Haojun Liao 已提交
4601 4602
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4603 4604
    }

H
Haojun Liao 已提交
4605
    return pInfo->pRes;
4606
  }
H
Haojun Liao 已提交
4607

H
Haojun Liao 已提交
4608
  SQuery* pQuery = pRuntimeEnv->pQuery;
4609 4610 4611 4612 4613 4614 4615 4616 4617 4618
  int32_t order = pQuery->order.order;

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
    SSDataBlock* pBlock = upstream->exec(upstream);
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4619
    setTagVal_rv(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
4620

H
Haojun Liao 已提交
4621
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4622
      STableScanInfo* pScanInfo = upstream->info;
4623 4624 4625 4626
      order = getTableScanOrder(pScanInfo);
    }

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

    TSKEY k = (pQuery->order.order == TSDB_ORDER_ASC)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
H
Haojun Liao 已提交
4630 4631
    setExecutionContext_rv(pRuntimeEnv, pInfo, pOperator->numOfOutput, pQuery->current->groupIndex, k);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
4632
  }
H
Haojun Liao 已提交
4633

H
Haojun Liao 已提交
4634 4635
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4636

H
Haojun Liao 已提交
4637 4638 4639 4640
  if (isTsCompQuery(pQuery)) {
    finalizeQueryResult_rv(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset);
  }

H
Haojun Liao 已提交
4641 4642
  updateWindowResNumOfRes_rv(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4643

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

H
Haojun Liao 已提交
4646 4647 4648
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4649 4650
  }

H
Haojun Liao 已提交
4651
  return pInfo->pRes;
4652 4653 4654 4655 4656
}

static SSDataBlock* doArithmeticOperation(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4657 4658
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4659 4660 4661
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
  
  pInfo->pRes->info.rows = 0;
H
Haojun Liao 已提交
4662

H
Haojun Liao 已提交
4663
  while(1) {
H
Haojun Liao 已提交
4664
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4665
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4666
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4667
      break;
H
Haojun Liao 已提交
4668 4669
    }

H
Haojun Liao 已提交
4670
    setTagVal_rv(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4671

H
Haojun Liao 已提交
4672
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4673
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
4674
    updateOutputBuf(pArithInfo, pBlock->info.rows);
H
Haojun Liao 已提交
4675
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
4676

H
Haojun Liao 已提交
4677 4678
    pInfo->pRes->info.rows = getNumOfResult_rv(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pInfo->pRes->info.rows >= 4096) {
H
Haojun Liao 已提交
4679 4680 4681 4682
      break;
    }
  }

H
Haojun Liao 已提交
4683 4684
  setNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4685 4686 4687 4688
}

static SSDataBlock* doLimit(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4689
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4690
    return NULL;
H
Haojun Liao 已提交
4691 4692
  }

H
Haojun Liao 已提交
4693
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4694

H
Haojun Liao 已提交
4695
  SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4696
  if (pBlock == NULL) {
H
Haojun Liao 已提交
4697
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4698
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4699 4700 4701 4702 4703 4704
    return NULL;
  }

  if (pInfo->total + pBlock->info.rows >= pInfo->limit) {
    pBlock->info.rows = (pInfo->limit - pInfo->total);

H
Haojun Liao 已提交
4705 4706
    pInfo->total = pInfo->limit;

H
Haojun Liao 已提交
4707
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4708
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4709 4710
  } else {
    pInfo->total += pBlock->info.rows;
H
Haojun Liao 已提交
4711 4712 4713 4714 4715
  }

  return pBlock;
}

H
Haojun Liao 已提交
4716
// TODO add log
H
Haojun Liao 已提交
4717 4718
static SSDataBlock* doOffset(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
H
Haojun Liao 已提交
4719
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4720 4721
    return NULL;
  }
H
Haojun Liao 已提交
4722

H
Haojun Liao 已提交
4723
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4724 4725

  while (1) {
H
Haojun Liao 已提交
4726
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4727
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4728
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4729
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4730 4731 4732
      return NULL;
    }

H
Haojun Liao 已提交
4733
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4734
      return pBlock;
H
Haojun Liao 已提交
4735 4736
    } else if (pRuntimeEnv->currentOffset > pBlock->info.rows) {
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4737
    } else {
H
Haojun Liao 已提交
4738
      int32_t remain = pBlock->info.rows - pRuntimeEnv->currentOffset;
H
Haojun Liao 已提交
4739 4740 4741 4742 4743 4744
      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;
H
Haojun Liao 已提交
4745
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4746 4747
      }

H
Haojun Liao 已提交
4748
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4749 4750 4751 4752 4753
      return pBlock;
    }
  }
}

H
Haojun Liao 已提交
4754
static SSDataBlock* doIntervalAgg(void* param) {
H
Haojun Liao 已提交
4755
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4756
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4757 4758 4759
    return NULL;
  }

H
Haojun Liao 已提交
4760
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4761

H
Haojun Liao 已提交
4762
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4763
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4764 4765
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4766
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4767
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4768 4769 4770 4771
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4774
  int32_t order = pQuery->order.order;
4775
  STimeWindow win = pQuery->window;
H
Haojun Liao 已提交
4776

H
Haojun Liao 已提交
4777
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4778 4779 4780 4781 4782 4783 4784 4785

  while(1) {
    SSDataBlock* pBlock = upstream->exec(upstream);
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4786
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
H
Haojun Liao 已提交
4787
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pIntervalInfo, pBlock, 0);
H
Haojun Liao 已提交
4788 4789
  }

4790 4791 4792 4793
  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

H
Haojun Liao 已提交
4794
  pOperator->status = OP_RES_TO_RETURN;
4795
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4796
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4797
  finalizeQueryResult_rv(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4798

H
Haojun Liao 已提交
4799
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4800
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4801

H
Haojun Liao 已提交
4802
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4803
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4804 4805
  }

H
Haojun Liao 已提交
4806
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4807 4808
}

H
Haojun Liao 已提交
4809
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
4810
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4811
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4812 4813 4814
    return NULL;
  }

H
Haojun Liao 已提交
4815
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4816
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4817

H
Haojun Liao 已提交
4818
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4819
    copyResToQueryResultBuf_rv(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4820
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4821
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4822 4823 4824 4825 4826
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
4827 4828 4829
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
4830
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4831 4832

  while(1) {
H
Haojun Liao 已提交
4833
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4834
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4835
      break;
H
Haojun Liao 已提交
4836 4837
    }

H
Haojun Liao 已提交
4838
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4839 4840 4841
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current;

    setTagVal_rv(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4842
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
4843
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
4844

H
Haojun Liao 已提交
4845
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pIntervalInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
4846
  }
H
Haojun Liao 已提交
4847

H
Haojun Liao 已提交
4848
  pOperator->status = OP_RES_TO_RETURN;
4849 4850
  pQuery->order.order = order;   // TODO : restore the order
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
4851
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4852

H
Haojun Liao 已提交
4853
  copyResToQueryResultBuf_rv(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4854
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4855
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4856 4857 4858 4859
  }

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

H
Haojun Liao 已提交
4861 4862
static SSDataBlock* doHashGroupbyAgg(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4863
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4864 4865 4866
    return NULL;
  }

H
Haojun Liao 已提交
4867
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
4868

H
Haojun Liao 已提交
4869
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4870
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4871
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4872 4873

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

H
Haojun Liao 已提交
4877
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888
  }

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
    SSDataBlock* pBlock = upstream->exec(upstream);
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4889
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
H
Haojun Liao 已提交
4890
    setTagVal_rv(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4891 4892 4893 4894
    if (pInfo->colIndex == -1) {
      pInfo->colIndex = getGroupbyColumnData_rv(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
    }

H
Haojun Liao 已提交
4895
    hashGroupbyAgg(pRuntimeEnv, pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
4896 4897
  }

H
Haojun Liao 已提交
4898
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
4899
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4900
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
4901 4902

  if (!pRuntimeEnv->pQuery->stableQuery) {
H
Haojun Liao 已提交
4903
    finalizeQueryResult_rv(pOperator, pInfo->binfo.pCtx, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
4904 4905
  }

H
Haojun Liao 已提交
4906
  updateWindowResNumOfRes_rv(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
4907

H
Haojun Liao 已提交
4908
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4909
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4910

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

H
Haojun Liao 已提交
4915
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4916 4917
}

H
Haojun Liao 已提交
4918 4919
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4920
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4921 4922 4923
    return NULL;
  }

H
Haojun Liao 已提交
4924 4925
  SFillOperatorInfo *pInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4926

H
Haojun Liao 已提交
4927 4928
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
    doFillGapsInResults_rv(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4929 4930 4931 4932 4933 4934
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4935
      if (pInfo->totalInputRows == 0) {
H
Haojun Liao 已提交
4936
        pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4937 4938 4939
        return NULL;
      }

H
Haojun Liao 已提交
4940
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
H
Haojun Liao 已提交
4941
    } else {
H
Haojun Liao 已提交
4942 4943
      pInfo->totalInputRows += pBlock->info.rows;

H
Haojun Liao 已提交
4944
      int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQuery->window.ekey:pBlock->info.window.ekey;
H
Haojun Liao 已提交
4945

H
Haojun Liao 已提交
4946 4947
      taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
H
Haojun Liao 已提交
4948 4949
    }

H
Haojun Liao 已提交
4950
    doFillGapsInResults_rv(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4951
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4952 4953
  }
}
H
Haojun Liao 已提交
4954

H
Haojun Liao 已提交
4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966
// 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 已提交
4967 4968 4969 4970 4971
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
4972
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
4973
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
4974 4975
  }

H
Haojun Liao 已提交
4976
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
4977
  tfree(pOperator->info);
H
Haojun Liao 已提交
4978 4979 4980
  tfree(pOperator);
}

H
Haojun Liao 已提交
4981
static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
4982 4983
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
4984 4985 4986 4987
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));

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

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

H
Haojun Liao 已提交
4992
  pInfo->seed = rand();
H
Haojun Liao 已提交
4993
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed);
H
Haojun Liao 已提交
4994

H
Haojun Liao 已提交
4995
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4996
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
4997
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
4998
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4999
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5000
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5001
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5002 5003 5004
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5005

H
Haojun Liao 已提交
5006 5007
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5008 5009 5010
  return pOperator;
}

H
Haojun Liao 已提交
5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027
static void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) {
  assert(pInfo != NULL);

  destroySQLFunctionCtx(pInfo->pCtx, numOfOutput);
  tfree(pInfo->rowCellInfoOffset);

  cleanupResultRowInfo(&pInfo->resultRowInfo);
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) {
  SOptrBasicInfo* pInfo = (SOptrBasicInfo*) param;
  doDestroyBasicInfo(pInfo, numOfOutput);
}

static void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
  SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param;
H
Haojun Liao 已提交
5028
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5029 5030 5031 5032
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5033
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5034 5035 5036 5037 5038 5039 5040 5041
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}

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

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

H
Haojun Liao 已提交
5045 5046
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) tableGroup);
H
Haojun Liao 已提交
5047
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5048
  initResultRowInfo(&pInfo->binfo.resultRowInfo, tableGroup, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5049

5050
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5051 5052
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5053
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5054
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5055
  pOperator->info         = pInfo;
5056
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5057 5058 5059
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5060

H
Haojun Liao 已提交
5061 5062 5063
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5064
  return pOperator;
H
Haojun Liao 已提交
5065 5066
}

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

H
Haojun Liao 已提交
5070
  pInfo->seed = rand();
H
Haojun Liao 已提交
5071
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5072

H
Haojun Liao 已提交
5073
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5074
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5075 5076 5077
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5078
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed);
H
Haojun Liao 已提交
5079 5080

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5081 5082
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5083
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5084
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5085
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5086
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5087 5088 5089
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5090

H
Haojun Liao 已提交
5091 5092 5093
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5094 5095 5096
  return pOperator;
}

H
Haojun Liao 已提交
5097
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5098 5099 5100 5101 5102
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;

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

H
Haojun Liao 已提交
5103 5104
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5105
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5106
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5107
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5108
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5109 5110
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5111 5112 5113 5114

  return pOperator;
}

H
Haojun Liao 已提交
5115
SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5116 5117 5118 5119 5120
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

  pInfo->offset = pRuntimeEnv->pQuery->limit.offset;
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

H
Haojun Liao 已提交
5121 5122
  pOperator->name         = "OffsetOperator";
  pOperator->operatorType = OP_Offset;
H
Haojun Liao 已提交
5123
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5124
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5125
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5126
  pOperator->exec         = doOffset;
H
Haojun Liao 已提交
5127 5128
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5129 5130 5131 5132

  return pOperator;
}

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

H
Haojun Liao 已提交
5136
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5137
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5138
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5139 5140 5141

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

H
Haojun Liao 已提交
5142 5143
  pOperator->name         = "TimeIntervalAggOperator";
  pOperator->operatorType = OP_TimeInterval;
H
Haojun Liao 已提交
5144
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5145
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5146
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5147 5148 5149 5150
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5151
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5152 5153
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5154 5155 5156
  return pOperator;
}

H
Haojun Liao 已提交
5157
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5158
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5159

H
Haojun Liao 已提交
5160
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5161
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5162
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5163 5164

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5165 5166
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5167
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5168
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5169
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5170 5171
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5172 5173
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5174

H
Haojun Liao 已提交
5175 5176 5177
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5178 5179 5180
  return pOperator;
}

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

H
Haojun Liao 已提交
5185
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5186
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5187
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5188 5189

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5190
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5191
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5192 5193
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5194
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5195 5196 5197 5198
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5199 5200 5201
  pOperator->exec         = doHashGroupbyAgg;
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5202 5203
  return pOperator;
}
H
Haojun Liao 已提交
5204

H
Haojun Liao 已提交
5205
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
H
Haojun Liao 已提交
5206
    int32_t numOfOutput) {
H
Haojun Liao 已提交
5207
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);

  {
    SQuery* pQuery = pRuntimeEnv->pQuery;
    SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQuery->fillVal);
    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);

    pInfo->pFillInfo = taosCreateFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput,
                                                pQuery->interval.sliding, pQuery->interval.slidingUnit, (int8_t)pQuery->precision,
                                                pQuery->fillType, pColInfo, pRuntimeEnv->qinfo);
  }
H
Haojun Liao 已提交
5223 5224 5225

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

H
Haojun Liao 已提交
5226
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5227
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5228 5229 5230
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5231
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5232 5233 5234 5235
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5236

H
Haojun Liao 已提交
5237 5238 5239
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5240 5241 5242
  return pOperator;
}

5243 5244
static SSDataBlock* doTagScan(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5245
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5246 5247
    return NULL;
  }
5248

H
Haojun Liao 已提交
5249
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5250

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

H
Haojun Liao 已提交
5253 5254
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
5255 5256

  int32_t count = 0;
H
Haojun Liao 已提交
5257 5258 5259 5260 5261
  SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);

  int32_t functionId = pOperator->pExpr[0].base.functionId;
  if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id
    SQuery* pQuery = pRuntimeEnv->pQuery;
5262 5263 5264 5265
    assert(pQuery->numOfOutput == 1);

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
    int32_t rsize = pExprInfo->bytes;
H
Haojun Liao 已提交
5266

5267 5268 5269
    count = 0;

    int16_t bytes = pExprInfo->bytes;
H
Haojun Liao 已提交
5270
    int16_t type  = pExprInfo->type;
5271 5272 5273 5274 5275 5276 5277 5278 5279

    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 已提交
5280 5281 5282 5283
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5286
      char *output = pColInfo->pData + count * rsize;
5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303
      varDataSetLen(output, rsize - VARSTR_HEADER_SIZE);

      output = varDataVal(output);
      STableId* id = TSDB_TABLEID(item->pTable);

      *(int16_t *)output = 0;
      output += sizeof(int16_t);

      *(int64_t *)output = id->uid;  // memory align problem, todo serialize
      output += sizeof(id->uid);

      *(int32_t *)output = id->tid;
      output += sizeof(id->tid);

      *(int32_t *)output = pQuery->vgId;
      output += sizeof(pQuery->vgId);

H
Haojun Liao 已提交
5304
      char* data = NULL;
5305
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5306
        data = tsdbGetTableName(item->pTable);
5307
      } else {
H
Haojun Liao 已提交
5308
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5309 5310
      }

H
Haojun Liao 已提交
5311
      doSetTagValueToResultBuf(output, data, type, bytes);
5312 5313 5314 5315
      count += 1;
    }

    qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pRuntimeEnv->qinfo, count);
H
Haojun Liao 已提交
5316
  } /*else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
5317 5318 5319 5320 5321
    *(int64_t*) pQuery->sdata[0]->data = num;

    count = 1;
    SET_STABLE_QUERY_OVER(pRuntimeEnv);
    qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pRuntimeEnv->qinfo, count);
H
Haojun Liao 已提交
5322 5323
  }*/ else {  // return only the tags|table name etc.
    SExprInfo* pExprInfo = pOperator->pExpr;  // todo use the column list instead of exprinfo
5324

H
Haojun Liao 已提交
5325 5326 5327
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338

      STableQueryInfo* item = taosArrayGetP(pa, i);

      char *data = NULL, *dst = NULL;
      int16_t type = 0, bytes = 0;
      for(int32_t j = 0; j < pOperator->numOfOutput; ++j) {
        // not assign value in case of user defined constant output column
        if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) {
          continue;
        }

H
Haojun Liao 已提交
5339
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5340 5341
        type  = pExprInfo[j].type;
        bytes = pExprInfo[j].bytes;
5342 5343 5344 5345 5346 5347 5348

        if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
          data = tsdbGetTableName(item->pTable);
        } else {
          data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes);
        }

H
Haojun Liao 已提交
5349
        dst  = pColInfo->pData + count * pExprInfo[j].bytes;
5350 5351
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5352

5353 5354 5355 5356 5357 5358
      count += 1;
    }

    qDebug("QInfo:%p create tag values results completed, rows:%d", pRuntimeEnv->qinfo, count);
  }

H
Haojun Liao 已提交
5359
  pRes->info.rows = count;
H
Haojun Liao 已提交
5360
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5361 5362
}

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

H
Haojun Liao 已提交
5367 5368 5369 5370 5371 5372
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5373
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5374
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5375
  pOperator->operatorType = OP_TagScan;
5376
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5377
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5378 5379
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5380 5381
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5382
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5383

5384 5385
  return pOperator;
}
H
Haojun Liao 已提交
5386

H
Haojun Liao 已提交
5387
void tableQueryImpl(SQInfo *pQInfo) {
5388 5389 5390
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *          pQuery = pRuntimeEnv->pQuery;

H
hjxilinx 已提交
5391
  // number of points returned during this query
5392
  int64_t st = taosGetTimestampUs();
5393

H
Haojun Liao 已提交
5394
  assert(pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1);
H
Haojun Liao 已提交
5395

H
Haojun Liao 已提交
5396 5397
  SArray* g = GET_TABLEGROUP(pRuntimeEnv, 0);
  pQuery->current = taosArrayGetP(g, 0);
5398

5399
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
5400

5401
  // record the total elapsed time
H
Haojun Liao 已提交
5402
  pQInfo->summary.elapsedTime += (taosGetTimestampUs() - st);
5403
}
H
Haojun Liao 已提交
5404

H
Haojun Liao 已提交
5405 5406


H
Haojun Liao 已提交
5407
void buildTableBlockDistResult(SQInfo *pQInfo) {
Y
yihaoDeng 已提交
5408 5409 5410
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
  SQuery *pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
5411 5412
  STableBlockDist *pTableBlockDist = calloc(1, sizeof(STableBlockDist));
  pTableBlockDist->dataBlockInfos  = taosArrayInit(512, sizeof(SFileBlockInfo));
Y
yihaoDeng 已提交
5413 5414 5415 5416

  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
  SSchema blockDistSchema = tGetBlockDistColumnSchema();

H
Haojun Liao 已提交
5417 5418 5419
//  int64_t startTime = taosGetTimestampUs();
  tsdbGetFileBlocksDistInfo(pQueryHandle, pTableBlockDist->dataBlockInfos);
  pTableBlockDist->numOfRowsInMemTable = tsdbGetNumOfRowsInMemTable(pQueryHandle);
Y
yihaoDeng 已提交
5420
  
H
Haojun Liao 已提交
5421
//  generateBlockDistResult(pTableBlockDist);
Y
yihaoDeng 已提交
5422 5423 5424 5425 5426 5427 5428 5429

  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;
    }
H
Haojun Liao 已提交
5430

Y
yihaoDeng 已提交
5431
    assert(type == TSDB_DATA_TYPE_BINARY);
H
Haojun Liao 已提交
5432
//    STR_WITH_SIZE_TO_VARSTR(pQuery->sdata[j]->data, pTableBlockDist->result, (VarDataLenT)strlen(pTableBlockDist->result));
Y
yihaoDeng 已提交
5433 5434 5435 5436
  }

  freeTableBlockDist(pTableBlockDist);

H
Haojun Liao 已提交
5437
//  pRuntimeEnv->resultInfo.rows = 1;
H
Haojun Liao 已提交
5438
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
Y
yihaoDeng 已提交
5439
}
5440

H
Haojun Liao 已提交
5441
void stableQueryImpl(SQInfo *pQInfo) {
H
Haojun Liao 已提交
5442
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
5443

5444
  int64_t st = taosGetTimestampUs();
H
Haojun Liao 已提交
5445
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);
5446

H
hjxilinx 已提交
5447
  // record the total elapsed time
H
Haojun Liao 已提交
5448
  pQInfo->summary.elapsedTime += (taosGetTimestampUs() - st);
H
hjxilinx 已提交
5449 5450
}

5451
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
5452
  int32_t j = 0;
5453

5454
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
5455
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5456
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
5457 5458
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5459
    }
Y
yihaoDeng 已提交
5460
    
H
Haojun Liao 已提交
5461

5462 5463 5464 5465
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
5466

5467 5468
      j += 1;
    }
5469

Y
TD-1230  
yihaoDeng 已提交
5470
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5471
    return TSDB_UD_COLUMN_INDEX;
5472 5473 5474 5475 5476
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
5477

5478
      j += 1;
5479 5480
    }
  }
5481 5482

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5483 5484
}

5485 5486
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
5487
  return j != INT32_MIN;
5488 5489
}

5490
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5491 5492
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5493
    return false;
5494 5495
  }

H
hjxilinx 已提交
5496
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5497
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5498
    return false;
5499 5500
  }

H
hjxilinx 已提交
5501
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5502
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5503
    return false;
5504 5505
  }

5506 5507
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5508
    return false;
5509 5510
  }

5511 5512 5513
  return true;
}

5514
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5515 5516 5517 5518
  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;
5519 5520 5521
  }

  if (numOfTotal == 0) {
5522
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
5523 5524 5525 5526 5527
      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)) {
5528
        continue;
5529
      }
5530

5531
      return false;
5532 5533
    }
  }
5534

5535 5536 5537 5538 5539 5540
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5541
  return true;
5542 5543
}

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

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

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

5552
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5553 5554
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5555

H
hjxilinx 已提交
5556 5557 5558
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5559

H
hjxilinx 已提交
5560 5561
  return pMsg;
}
5562

5563
/**
H
hjxilinx 已提交
5564
 * pQueryMsg->head has been converted before this function is called.
5565
 *
H
hjxilinx 已提交
5566
 * @param pQueryMsg
5567 5568 5569 5570
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5571
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5572 5573
  int32_t code = TSDB_CODE_SUCCESS;

5574 5575 5576 5577
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5578 5579 5580 5581
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5582 5583 5584
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5585 5586
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5587
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5588

5589 5590
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5591
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5592
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5593 5594

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5595
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5596
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5597 5598 5599
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
5600
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
5601
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
5602
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5603
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5604
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5605
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5606
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5607

5608
  // query msg safety check
5609
  if (!validateQueryMsg(pQueryMsg)) {
5610 5611
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5612 5613
  }

H
hjxilinx 已提交
5614 5615
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
5616 5617
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
5618
    pColInfo->colId = htons(pColInfo->colId);
5619
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
5620 5621
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
5622

5623 5624 5625 5626 5627
    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;
    }
5628

H
hjxilinx 已提交
5629
    int32_t numOfFilters = pColInfo->numOfFilters;
5630
    if (numOfFilters > 0) {
H
hjxilinx 已提交
5631
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
5632 5633 5634 5635
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
5636 5637 5638
    }

    for (int32_t f = 0; f < numOfFilters; ++f) {
5639
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pMsg;
5640

5641 5642
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
5643 5644 5645

      pMsg += sizeof(SColumnFilterInfo);

5646 5647
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
5648

5649
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
5650 5651 5652 5653 5654
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

5655
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
5656
        pMsg += (pColFilter->len + 1);
5657
      } else {
5658 5659
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
5660 5661
      }

5662 5663
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
5664 5665 5666
    }
  }

5667 5668
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
5669 5670 5671 5672
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

5673
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
5674

5675
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5676
    param->pExprMsg[i] = pExprMsg;
5677

5678
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
5679
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5680
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5681 5682 5683
    pExprMsg->colType       = htons(pExprMsg->colType);
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5684 5685 5686
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
5687

5688
    pMsg += sizeof(SSqlFuncMsg);
5689 5690

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
5691
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
5692 5693 5694 5695
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
5696
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
5697 5698 5699 5700 5701
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
5702 5703
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
5704
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
5705 5706
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
5707 5708 5709
      }
    }

5710
    pExprMsg = (SSqlFuncMsg *)pMsg;
5711
  }
5712

H
Haojun Liao 已提交
5713 5714
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
5715
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
5716

H
Haojun Liao 已提交
5717
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
5718
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
5719 5720 5721

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5722
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5723 5724 5725
      pExprMsg->colType       = htons(pExprMsg->colType);
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754
      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;
    }
  }

5755
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
5756

H
hjxilinx 已提交
5757
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
5758 5759
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
5760 5761 5762
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5763 5764

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

5768 5769
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
5770

5771 5772
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
5773

5774 5775
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
5776
    }
5777

H
hjxilinx 已提交
5778 5779
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
5780 5781
  }

5782 5783
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
5784
    pQueryMsg->fillVal = (uint64_t)(pMsg);
5785 5786

    int64_t *v = (int64_t *)pMsg;
5787
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5788 5789
      v[i] = htobe64(v[i]);
    }
5790

5791
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
5792
  }
5793

5794
  if (pQueryMsg->numOfTags > 0) {
5795 5796
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
5797 5798 5799 5800
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5801 5802
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
5803

5804 5805 5806 5807
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
5808

5809
      param->pTagColumnInfo[i] = *pTagCol;
5810
      pMsg += sizeof(SColumnInfo);
5811
    }
H
hjxilinx 已提交
5812
  }
5813

5814 5815
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
5816 5817
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
5818 5819 5820
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5821 5822

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
5823 5824
    pMsg += pQueryMsg->tagCondLen;
  }
5825

5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836
  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 已提交
5837
  if (pQueryMsg->tbnameCondLen > 0) {
5838 5839
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
5840 5841 5842 5843
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5844
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5845
    pMsg += pQueryMsg->tbnameCondLen;
5846 5847
  }

D
dapan1121 已提交
5848 5849 5850 5851 5852
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

5853
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
5854

5855
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
5856 5857
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
5858
  }
5859

5860
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
5861 5862
         "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,
5863
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
5864
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
5865

5866
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
5867
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
5868 5869

_cleanup:
5870
  freeParam(param);
5871
  return code;
5872 5873
}

H
Haojun Liao 已提交
5874 5875
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
5876 5877

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
5878
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
5879 5880 5881
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
5882
    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 已提交
5883 5884 5885
    return code;
  } END_TRY

H
hjxilinx 已提交
5886
  if (pExprNode == NULL) {
5887
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
5888
    return TSDB_CODE_QRY_APP_ERROR;
5889
  }
5890

5891
  pArithExprInfo->pExpr = pExprNode;
5892 5893 5894
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917
static UNUSED_FUNC int32_t ddx(SQueryTableMsg* pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols, SExprInfo* pExprs,
    int32_t numOfOutput, int32_t tagLen, bool superTable) {
  for (int32_t i = 0; i < numOfOutput; ++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, superTable);
        assert(ret == TSDB_CODE_SUCCESS);
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                   SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5918
  *pExprInfo = NULL;
H
hjxilinx 已提交
5919
  int32_t code = TSDB_CODE_SUCCESS;
5920

H
Haojun Liao 已提交
5921
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
5922
  if (pExprs == NULL) {
5923
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
5924 5925 5926 5927 5928
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
5929
  for (int32_t i = 0; i < numOfOutput; ++i) {
5930
    pExprs[i].base = *pExprMsg[i];
5931
    pExprs[i].bytes = 0;
5932 5933 5934 5935

    int16_t type = 0;
    int16_t bytes = 0;

5936
    // parse the arithmetic expression
5937
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
5938
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
5939

5940
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5941
        tfree(pExprs);
5942
        return code;
5943 5944
      }

5945
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
5946
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
5947
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
5948 5949 5950
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
5951 5952 5953 5954
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
5955 5956
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
5957 5958
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

5959 5960
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
5961 5962 5963 5964 5965

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
5966
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
5967
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
5968
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
5969 5970 5971 5972 5973 5974 5975
          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 已提交
5976

dengyihao's avatar
dengyihao 已提交
5977
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
5978 5979 5980 5981
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
5982
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
5983

5984 5985
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
5986
      }
5987 5988
    }

S
TD-1057  
Shengliang Guan 已提交
5989
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
H
Haojun Liao 已提交
5990 5991 5992 5993 5994
    if (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes) {
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

5995
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
5996
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5997
      tfree(pExprs);
5998
      return TSDB_CODE_QRY_INVALID_MSG;
5999 6000
    }

6001
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
6002
      tagLen += pExprs[i].bytes;
6003
    }
6004

6005
    assert(isValidDataType(pExprs[i].type));
6006 6007
  }

H
Haojun Liao 已提交
6008
//  ddx(pQueryMsg, pExprMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6009

6010
  *pExprInfo = pExprs;
6011 6012 6013
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6014 6015 6016 6017 6018 6019 6020 6021 6022 6023
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 已提交
6024
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047

  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 已提交
6048 6049
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065
    }

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

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6066
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6067 6068 6069 6070 6071
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6072
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6073
  if (pGroupbyExpr == NULL) {
6074
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6075 6076 6077 6078 6079 6080 6081
    return NULL;
  }

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

6082 6083 6084 6085
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6086

6087 6088 6089
  return pGroupbyExpr;
}

6090
static int32_t createFilterInfo(void *pQInfo, SQuery *pQuery) {
6091
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
6092
    if (pQuery->colList[i].numOfFilters > 0) {
6093 6094 6095 6096 6097 6098 6099 6100 6101
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
6102 6103 6104
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6105 6106

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
6107
    if (pQuery->colList[i].numOfFilters > 0) {
6108 6109
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
6110
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
6111
      pFilterInfo->info = pQuery->colList[i];
6112

6113
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
6114
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
6115 6116 6117
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6118 6119 6120

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
6121
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
6122 6123 6124 6125

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
S
slguan 已提交
6126
          qError("QInfo:%p invalid filter info", pQInfo);
6127
          return TSDB_CODE_QRY_INVALID_MSG;
6128 6129
        }

6130 6131 6132
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
          qError("QInfo:%p invalid filter info", pQInfo);
6133
          return TSDB_CODE_QRY_INVALID_MSG;
6134 6135
        }

6136
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
6137 6138 6139 6140 6141 6142 6143 6144 6145
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6146
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
6147
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
6148

6149
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
6150
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
6151
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6152 6153
      continue;
    }
6154

6155
    // todo opt performance
H
Haojun Liao 已提交
6156
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6157
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6158 6159
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
6160 6161
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
6162 6163 6164
          break;
        }
      }
H
Haojun Liao 已提交
6165 6166

      assert(f < pQuery->numOfCols);
6167 6168
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
6169
    } else {
6170 6171
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
6172 6173
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
6174 6175
          break;
        }
6176
      }
6177

Y
yihaoDeng 已提交
6178
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6179 6180 6181 6182
    }
  }
}

H
Haojun Liao 已提交
6183
static void calResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo) {
H
Haojun Liao 已提交
6184 6185
  const int32_t RESULT_MSG_MIN_SIZE  = 1024 * (1024 + 512);  // bytes
  const int32_t RESULT_MSG_MIN_ROWS  = 8192;
S
TD-1057  
Shengliang Guan 已提交
6186
  const float RESULT_THRESHOLD_RATIO = 0.85f;
H
Haojun Liao 已提交
6187

6188
  if (isProjQuery(pQuery)) {
6189
    int32_t numOfRes = RESULT_MSG_MIN_SIZE / pQuery->resultRowSize;
6190 6191 6192
    if (numOfRes < RESULT_MSG_MIN_ROWS) {
      numOfRes = RESULT_MSG_MIN_ROWS;
    }
H
Haojun Liao 已提交
6193

H
Haojun Liao 已提交
6194 6195
    pResultInfo->capacity  = numOfRes;
    pResultInfo->threshold = (int32_t)(numOfRes * RESULT_THRESHOLD_RATIO);
6196
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6197 6198
    pResultInfo->capacity = 4096;
    pResultInfo->threshold = (int32_t)(pResultInfo->capacity * RESULT_THRESHOLD_RATIO);
6199
  }
H
Haojun Liao 已提交
6200 6201
}

H
Haojun Liao 已提交
6202 6203 6204
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery,
                        char* sql) {
B
Bomin Zhang 已提交
6205 6206 6207
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6208 6209
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6210
    goto _cleanup_qinfo;
6211
  }
6212

B
Bomin Zhang 已提交
6213 6214
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6215
  SQuery* pQuery = &pQInfo->query;
6216 6217
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
6218
  pQuery->tableGroupInfo  = *pTableGroupInfo;
6219
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
6220
  pQuery->numOfOutput     = numOfOutput;
6221 6222 6223
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
6224
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
6225
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
6226 6227
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
6228
  pQuery->pGroupbyExpr    = pGroupbyExpr;
6229
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
6230
  pQuery->fillType        = pQueryMsg->fillType;
6231
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
6232
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
6233 6234
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
H
Haojun Liao 已提交
6235

6236
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
6237
  if (pQuery->colList == NULL) {
6238
    goto _cleanup;
6239
  }
6240

6241 6242
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
6243
  for (int16_t i = 0; i < numOfCols; ++i) {
6244
    pQuery->colList[i] = pQueryMsg->colList[i];
6245
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
6246 6247 6248 6249 6250

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
6251
  }
6252

6253
  // calculate the result row size
6254 6255
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
6256 6257 6258 6259 6260 6261
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
6262
  }
6263

6264
  doUpdateExprColumnIndex(pQuery);
6265
  int32_t ret = createFilterInfo(pQInfo, pQuery);
6266
  if (ret != TSDB_CODE_SUCCESS) {
6267
    goto _cleanup;
6268 6269
  }

6270
  if (pQuery->fillType != TSDB_FILL_NONE) {
6271 6272
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
6273
      goto _cleanup;
6274 6275 6276
    }

    // the first column is the timestamp
6277
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
6278 6279
  }

dengyihao's avatar
dengyihao 已提交
6280 6281 6282
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6283
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6284

6285 6286 6287
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6288
  }
H
Haojun Liao 已提交
6289

H
Haojun Liao 已提交
6290
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6291 6292 6293 6294
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

H
Haojun Liao 已提交
6295
  // NOTE: pTableCheckInfo need to update the query time range and the lastKey info
6296
  pQInfo->arrTableIdInfo = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
6297
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6298
  pQInfo->rspContext = NULL;
6299
  pQInfo->sql = sql;
6300
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6301
  tsem_init(&pQInfo->ready, 0, 0);
6302 6303 6304 6305

  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
6306 6307
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  pQuery->queryWindowIdentical = true;
6308 6309
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

6310
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
6311

H
Haojun Liao 已提交
6312
  int32_t index = 0;
H
hjxilinx 已提交
6313
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6314
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
6315

H
Haojun Liao 已提交
6316
    size_t s = taosArrayGetSize(pa);
6317
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6318 6319 6320
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6321

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

H
hjxilinx 已提交
6324
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6325
      STableKeyInfo* info = taosArrayGet(pa, j);
6326

6327
      window.skey = info->lastKey;
6328
      if (info->lastKey != pQuery->window.skey) {
H
Haojun Liao 已提交
6329
        pQInfo->query.queryWindowIdentical = false;
6330 6331 6332
      }

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
6333
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
6334 6335 6336
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6337

6338
      item->groupIndex = i;
H
hjxilinx 已提交
6339
      taosArrayPush(p1, &item);
6340 6341

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6342
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6343
      index += 1;
H
hjxilinx 已提交
6344 6345
    }
  }
6346

H
Haojun Liao 已提交
6347
  colIdCheck(pQuery, pQInfo);
6348

6349
  // todo refactor
H
Haojun Liao 已提交
6350
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
Y
yihaoDeng 已提交
6351
   
6352
  qDebug("qmsg:%p QInfo:%p created", pQueryMsg, pQInfo);
6353 6354
  return pQInfo;

B
Bomin Zhang 已提交
6355
_cleanup_qinfo:
H
Haojun Liao 已提交
6356
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6357

6358 6359 6360 6361
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6362

S
TD-1848  
Shengliang Guan 已提交
6363
  tfree(pTagCols);
B
Bomin Zhang 已提交
6364 6365 6366
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6367 6368
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6369 6370
    }
  }
H
Haojun Liao 已提交
6371

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

6374
_cleanup:
dengyihao's avatar
dengyihao 已提交
6375
  freeQInfo(pQInfo);
6376 6377 6378
  return NULL;
}

H
Haojun Liao 已提交
6379
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6380 6381 6382 6383
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6384

H
hjxilinx 已提交
6385 6386 6387 6388
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6389
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6390 6391 6392
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6393
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
6394
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6395 6396

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6397
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6398

6399
  STSBuf *pTsBuf = NULL;
6400
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
6401
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
6402
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
6403

6404 6405
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
6406

dengyihao's avatar
dengyihao 已提交
6407
    UNUSED(ret);
H
hjxilinx 已提交
6408
  }
6409

6410 6411 6412 6413 6414
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
  }

Y
TD-1665  
yihaoDeng 已提交
6415
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
6416

6417 6418
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
6419
    qDebug("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey,
6420
           pQuery->window.ekey, pQuery->order.order);
H
Haojun Liao 已提交
6421
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6422
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6423
    // todo free memory
6424 6425
    return TSDB_CODE_SUCCESS;
  }
6426

H
Haojun Liao 已提交
6427
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
6428
    qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo);
H
Haojun Liao 已提交
6429
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6430 6431
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6432 6433

  // filter the qualified
6434
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6435 6436
    goto _error;
  }
6437

H
hjxilinx 已提交
6438 6439 6440 6441
  return code;

_error:
  // table query ref will be decrease during error handling
6442
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6443 6444 6445
  return code;
}

H
Haojun Liao 已提交
6446
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6447
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6448 6449
      return;
    }
H
Haojun Liao 已提交
6450

B
Bomin Zhang 已提交
6451 6452 6453 6454 6455
    for (int32_t i = 0; i < numOfFilters; i++) {
      if (pFilter[i].filterstr) {
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6456

B
Bomin Zhang 已提交
6457 6458 6459
    free(pFilter);
}

H
Haojun Liao 已提交
6460 6461
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6462
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483
    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 已提交
6484 6485 6486 6487 6488 6489 6490 6491
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 已提交
6492
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6493 6494 6495 6496 6497 6498 6499
    }
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6500
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6501 6502 6503
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6504

6505
  qDebug("QInfo:%p start to free QInfo", pQInfo);
6506

H
Haojun Liao 已提交
6507
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6508
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
6509
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6510

H
Haojun Liao 已提交
6511 6512 6513
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
6514
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
6515
    }
6516

H
Haojun Liao 已提交
6517 6518 6519
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
6520
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
6521
      }
H
hjxilinx 已提交
6522
    }
6523

H
Haojun Liao 已提交
6524 6525
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
6526

S
TD-1848  
Shengliang Guan 已提交
6527 6528
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
6529 6530 6531 6532 6533 6534

    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 已提交
6535
      tfree(pQuery->colList);
H
Haojun Liao 已提交
6536 6537
    }

H
Haojun Liao 已提交
6538 6539 6540 6541
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
6542
  }
6543

H
Haojun Liao 已提交
6544
  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
H
Haojun Liao 已提交
6545

S
TD-1848  
Shengliang Guan 已提交
6546
  tfree(pQInfo->pBuf);
6547 6548
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
6549
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
6550
  taosHashCleanup(pQInfo->arrTableIdInfo);
6551

H
Haojun Liao 已提交
6552
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
6553

6554
  pQInfo->signature = 0;
6555

6556
  qDebug("QInfo:%p QInfo is freed", pQInfo);
6557

S
TD-1848  
Shengliang Guan 已提交
6558
  tfree(pQInfo);
H
hjxilinx 已提交
6559 6560
}

H
Haojun Liao 已提交
6561
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
6562
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
6563
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
hjxilinx 已提交
6564
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6565

H
hjxilinx 已提交
6566
  // load data from file to msg buffer
H
Haojun Liao 已提交
6567
  if (isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
6568 6569
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
6570

H
hjxilinx 已提交
6571
    // make sure file exist
D
fix bug  
dapan1121 已提交
6572 6573
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
6574
      assert(s == pRuntimeEnv->outputBuf->info.rows);
6575

D
fix bug  
dapan1121 已提交
6576
      qDebug("QInfo:%p ts comp data return, file:%p, size:%"PRId64, pQInfo, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
6577 6578
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
6579
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
6580
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
6581 6582
          assert(0);
        }
H
Haojun Liao 已提交
6583
      } else {
6584
        UNUSED(s);
D
dapan1121 已提交
6585 6586 6587 6588
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
6589
      // dump error info
D
dapan1121 已提交
6590 6591 6592
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
6593
      }
H
Haojun Liao 已提交
6594

D
fix bug  
dapan1121 已提交
6595
      fclose(f);
H
hjxilinx 已提交
6596
    }
6597

H
hjxilinx 已提交
6598
    // all data returned, set query over
H
Haojun Liao 已提交
6599 6600
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
6601
    }
H
hjxilinx 已提交
6602
  } else {
H
Haojun Liao 已提交
6603
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
6604
  }
6605

H
Haojun Liao 已提交
6606 6607 6608
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
  qDebug("QInfo:%p current numOfRes rows:%d, total:%" PRId64, pQInfo,
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
6609

H
Haojun Liao 已提交
6610
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) {
6611
    qDebug("QInfo:%p results limitation reached, limitation:%"PRId64, pQInfo, pQuery->limit.limit);
H
Haojun Liao 已提交
6612
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
6613
  }
6614

H
hjxilinx 已提交
6615
  return TSDB_CODE_SUCCESS;
6616 6617
}

H
Haojun Liao 已提交
6618
bool doBuildResCheck(SQInfo* pQInfo) {
6619 6620 6621 6622 6623
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
6624
  buildRes = needBuildResAfterQueryComplete(pQInfo);
6625

H
Haojun Liao 已提交
6626 6627
  // 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 已提交
6628
  assert(pQInfo->owner == taosGetSelfPthreadId());
6629
  pQInfo->owner = 0;
H
Haojun Liao 已提交
6630

H
Haojun Liao 已提交
6631
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
6632

6633
  // used in retrieve blocking model.
H
Haojun Liao 已提交
6634
  tsem_post(&pQInfo->ready);
6635 6636 6637
  return buildRes;
}

H
Haojun Liao 已提交
6638 6639 6640 6641
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
6642 6643
  }

6644
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
6645
    memcpy(output, val, varDataTLen(val));
6646
  } else {
H
Haojun Liao 已提交
6647
    memcpy(output, val, bytes);
6648 6649 6650
  }
}

H
Haojun Liao 已提交
6651
void buildTagQueryResult(SQInfo* pQInfo) {
H
hjxilinx 已提交
6652
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
6653

H
Haojun Liao 已提交
6654
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
6655
  assert(numOfGroup == 0 || numOfGroup == 1);
6656

H
Haojun Liao 已提交
6657
  if (numOfGroup == 0) {
6658 6659
    return;
  }
6660

6661 6662
  pRuntimeEnv->outputBuf = pRuntimeEnv->proot->exec(pRuntimeEnv->proot);

H
Haojun Liao 已提交
6663
#if 0
H
Haojun Liao 已提交
6664
  SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
6665

H
Haojun Liao 已提交
6666
  size_t num = taosArrayGetSize(pa);
H
Haojun Liao 已提交
6667
  assert(num == pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
6668

H
Haojun Liao 已提交
6669
  int32_t count = 0;
H
Haojun Liao 已提交
6670
  int32_t functionId = pQuery->pExpr1[0].base.functionId;
6671 6672
  if (functionId == TSDB_FUNC_TID_TAG) { // return the tags & table Id
    assert(pQuery->numOfOutput == 1);
6673

H
Haojun Liao 已提交
6674
    SExprInfo* pExprInfo = &pQuery->pExpr1[0];
6675
    int32_t rsize = pExprInfo->bytes;
H
Haojun Liao 已提交
6676
    count = 0;
6677

H
Haojun Liao 已提交
6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688
    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 已提交
6689
    while(pRuntimeEnv->tableIndex < num && count < pRuntimeEnv->resultInfo.capacity) {
H
Haojun Liao 已提交
6690
      int32_t i = pRuntimeEnv->tableIndex++;
6691
      STableQueryInfo *item = taosArrayGetP(pa, i);
6692

H
Haojun Liao 已提交
6693
      char *output = NULL;//pQuery->sdata[0]->data + count * rsize;
6694
      varDataSetLen(output, rsize - VARSTR_HEADER_SIZE);
6695

6696
      output = varDataVal(output);
H
Haojun Liao 已提交
6697
      STableId* id = TSDB_TABLEID(item->pTable);
6698

6699 6700 6701
      *(int16_t *)output = 0;
      output += sizeof(int16_t);

H
Haojun Liao 已提交
6702 6703
      *(int64_t *)output = id->uid;  // memory align problem, todo serialize
      output += sizeof(id->uid);
6704

H
Haojun Liao 已提交
6705 6706
      *(int32_t *)output = id->tid;
      output += sizeof(id->tid);
6707

H
Haojun Liao 已提交
6708 6709
      *(int32_t *)output = pQuery->vgId;
      output += sizeof(pQuery->vgId);
6710

6711
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
6712
        char* data = tsdbGetTableName(item->pTable);
6713
        memcpy(output, data, varDataTLen(data));
H
[td-90]  
Haojun Liao 已提交
6714
      } else {
6715 6716
        char* data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
        doSetTagValueToResultBuf(output, data, type, bytes);
H
[td-90]  
Haojun Liao 已提交
6717
      }
6718

H
Haojun Liao 已提交
6719
      count += 1;
6720
    }
6721

6722
    qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pQInfo, count);
6723

H
Haojun Liao 已提交
6724
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
H
Haojun Liao 已提交
6725
//    *(int64_t*) pQuery->sdata[0]->data = num;
H
Haojun Liao 已提交
6726 6727

    count = 1;
H
Haojun Liao 已提交
6728
    SET_STABLE_QUERY_OVER(pRuntimeEnv);
6729
    qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pQInfo, count);
6730
  } else {  // return only the tags|table name etc.
H
Haojun Liao 已提交
6731
    count = 0;
6732
    SSchema* tbnameSchema = tGetTbnameColumnSchema();
6733

H
Haojun Liao 已提交
6734 6735
    int32_t maxNumOfTables = (int32_t)pRuntimeEnv->resultInfo.capacity;
    if (pQuery->limit.limit >= 0 && pQuery->limit.limit < pRuntimeEnv->resultInfo.capacity) {
S
TD-1057  
Shengliang Guan 已提交
6736
      maxNumOfTables = (int32_t)pQuery->limit.limit;
6737 6738
    }

H
Haojun Liao 已提交
6739 6740
    while(pRuntimeEnv->tableIndex < num && count < maxNumOfTables) {
      int32_t i = pRuntimeEnv->tableIndex++;
6741

6742 6743 6744 6745 6746 6747
      // discard current result due to offset
      if (pQuery->limit.offset > 0) {
        pQuery->limit.offset -= 1;
        continue;
      }

H
Haojun Liao 已提交
6748
      SExprInfo* pExprInfo = pQuery->pExpr1;
6749
      STableQueryInfo* item = taosArrayGetP(pa, i);
6750

6751 6752
      char *data = NULL, *dst = NULL;
      int16_t type = 0, bytes = 0;
6753
      for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
6754
        // not assign value in case of user defined constant output column
Y
TD-1230  
yihaoDeng 已提交
6755
        if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) {
H
Haojun Liao 已提交
6756 6757
          continue;
        }
6758

6759
        if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
6760 6761
          bytes = tbnameSchema->bytes;
          type = tbnameSchema->type;
6762 6763

          data = tsdbGetTableName(item->pTable);
H
Haojun Liao 已提交
6764
//          dst = pQuery->sdata[j]->data + count * tbnameSchema->bytes;
6765 6766 6767
        } else {
          type = pExprInfo[j].type;
          bytes = pExprInfo[j].bytes;
6768

6769
          data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes);
H
Haojun Liao 已提交
6770
//          dst = pQuery->sdata[j]->data + count * pExprInfo[j].bytes;
6771

6772
        }
6773 6774

        doSetTagValueToResultBuf(dst, data, type, bytes);
H
hjxilinx 已提交
6775
      }
H
Haojun Liao 已提交
6776
      count += 1;
H
hjxilinx 已提交
6777
    }
6778

6779
    qDebug("QInfo:%p create tag values results completed, rows:%d", pQInfo, count);
H
hjxilinx 已提交
6780
  }
6781

H
Haojun Liao 已提交
6782
  pRuntimeEnv->resultInfo.rows = count;
H
Haojun Liao 已提交
6783
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6784
#endif
H
hjxilinx 已提交
6785 6786
}

H
Haojun Liao 已提交
6787
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
6788 6789 6790 6791
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
6792
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
6793 6794
}

H
Haojun Liao 已提交
6795
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
6796
  int64_t t = getQuerySupportBufSize(numOfTables);
6797
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6798
    return TSDB_CODE_SUCCESS;
6799
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
6800 6801

    while(1) {
6802
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
6803 6804
      int64_t remain = s - t;
      if (remain >= 0) {
6805
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817
          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 已提交
6818
void releaseQueryBuf(size_t numOfTables) {
6819
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6820 6821 6822 6823 6824 6825
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
6826
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
6827
}