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

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

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

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

38 39 40 41 42 43 44
#define CHECK_IF_QUERY_KILLED(_q)                        \
  do {                                                   \
    if (isQueryKilled((_q)->qinfo)) {                    \
      longjmp((_q)->env, TSDB_CODE_TSC_QUERY_CANCELLED); \
    }                                                    \
  } while (0)

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

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

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

H
Haojun Liao 已提交
58 59 60 61 62
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP   = 2,
} SResultTsInterpType;

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

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

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

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

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

101

D
fix bug  
dapan1121 已提交
102 103
uint64_t queryHandleId = 0;

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

D
dapan1121 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

int64_t genQueryId(void) {
  int64_t uid = 0;
  int64_t did = tsDnodeId;
  
  uid = did << 54;
  
  int64_t pid = ((int64_t)taosGetPId()) & 0x3FF;

  uid |= pid << 44;
  
  int64_t ts = taosGetTimestampMs() & 0x1FFFFFFFF;

  uid |= ts << 11;
  
  int64_t sid = atomic_add_fetch_64(&queryHandleId, 1) & 0x7FF;

  uid |= sid;

  return uid;
}



132 133
static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) {
  int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
134 135 136
  if (pQuery->interval.intervalUnit != 'n' && pQuery->interval.intervalUnit != 'y') {
    tw->skey += pQuery->interval.sliding * factor;
    tw->ekey = tw->skey + pQuery->interval.interval - 1;
137 138 139
    return;
  }

140
  int64_t key = tw->skey / 1000, interval = pQuery->interval.interval;
141 142 143
  if (pQuery->precision == TSDB_TIME_PRECISION_MICRO) {
    key /= 1000;
  }
144
  if (pQuery->interval.intervalUnit == 'y') {
145 146
    interval *= 12;
  }
147 148 149 150 151

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

S
Shengliang Guan 已提交
152
  int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
153 154 155 156
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->skey = mktime(&tm) * 1000L;

S
Shengliang Guan 已提交
157
  mon = (int)(mon + interval);
158 159 160 161 162 163 164 165 166 167 168
  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;
}

H
Haojun Liao 已提交
169
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
170
static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
171
    int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
172

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

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

H
Haojun Liao 已提交
178
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
179 180
static bool hasMainOutput(SQuery *pQuery);

H
Haojun Liao 已提交
181
static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
182
static void releaseQueryBuf(size_t numOfTables);
183
static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order);
H
Haojun Liao 已提交
184
static STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win);
H
Haojun Liao 已提交
185
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo);
186

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

H
Haojun Liao 已提交
189
static int32_t getNumOfScanTimes(SQuery* pQuery);
H
Haojun Liao 已提交
190 191
static bool isFixedOutputQuery(SQuery* pQuery);

H
Haojun Liao 已提交
192 193
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime);
static SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime);
H
Haojun Liao 已提交
194
static SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
H
Haojun Liao 已提交
195

H
Haojun Liao 已提交
196
static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
197 198 199
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 已提交
200
static SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
201
static SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
202
static SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
203 204 205
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 已提交
206
static SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
207
static SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
D
dapan1121 已提交
208
static SOperatorInfo* createHavingOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
209

H
Haojun Liao 已提交
210 211 212 213
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 已提交
214
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
215
static void destroyOperatorInfo(SOperatorInfo* pOperator);
H
Haojun Liao 已提交
216

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

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

H
Haojun Liao 已提交
222 223
static void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size);
static void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win);
H
Haojun Liao 已提交
224
static bool isPointInterpoQuery(SQuery *pQuery);
H
Haojun Liao 已提交
225 226 227
static void setResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo);
static void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable);
static void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr);
D
fix bug  
dapan1121 已提交
228
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
229 230 231
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
232

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

H
Haojun Liao 已提交
237
  SSDataBlock *res = calloc(1, sizeof(SSDataBlock));
H
Haojun Liao 已提交
238
  res->info.numOfCols = numOfOutput;
H
Haojun Liao 已提交
239

H
Haojun Liao 已提交
240 241
  res->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
242
    SColumnInfoData idata = {{0}};
H
Haojun Liao 已提交
243 244 245
    idata.info.type = pExpr[i].type;
    idata.info.bytes = pExpr[i].bytes;
    idata.info.colId = pExpr[i].base.resColId;
246 247

    idata.pData = calloc(1, MAX(idata.info.bytes * numOfRows, minSize));  // at least to hold a pointer on x64 platform
H
Haojun Liao 已提交
248 249
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
250 251

  return res;
H
Haojun Liao 已提交
252 253
}

H
Haojun Liao 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
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;
}

sangshuduo's avatar
sangshuduo 已提交
271
int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
272 273 274
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);

sangshuduo's avatar
sangshuduo 已提交
275
  int32_t maxOutput = 0;
H
Haojun Liao 已提交
276
  for (int32_t j = 0; j < numOfOutput; ++j) {
H
Haojun Liao 已提交
277
    int32_t id = pCtx[j].functionId;
H
Haojun Liao 已提交
278 279 280 281 282

    /*
     * ts, tag, tagprj function can not decide the output number of current query
     * the number of output result is decided by main output
     */
H
Haojun Liao 已提交
283
    if (hasMainFunction && (id == TSDB_FUNC_TS || id == TSDB_FUNC_TAG || id == TSDB_FUNC_TAGPRJ)) {
H
Haojun Liao 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296
      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 已提交
297
static void clearNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
298 299 300 301 302 303
  for (int32_t j = 0; j < numOfOutput; ++j) {
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    pResInfo->numOfRes = 0;
  }
}

H
Haojun Liao 已提交
304
static bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) {
305 306 307
  if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) {
    return false;
  }
308

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

317 318 319
      return true;
    }
  }
320

321 322 323
  return false;
}

H
Haojun Liao 已提交
324
static bool isStabledev(SQuery* pQuery) {
325 326 327 328 329 330 331 332 333 334
  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;
}

H
Haojun Liao 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
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);
}
353

H
Haojun Liao 已提交
354
static bool isProjQuery(SQuery *pQuery) {
355
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
356
    int32_t functId = pQuery->pExpr1[i].base.functionId;
357 358 359 360 361 362 363 364
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

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

367
static bool isTopBottomQuery(SQuery *pQuery) {
368
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
369
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
370 371 372
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
373

374 375 376 377
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      return true;
    }
  }
378

379 380 381
  return false;
}

382 383 384
static bool timeWindowInterpoRequired(SQuery *pQuery) {
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
385
    if (functionId == TSDB_FUNC_TWA || functionId == TSDB_FUNC_INTERP) {
386 387 388 389 390 391 392
      return true;
    }
  }

  return false;
}

H
Haojun Liao 已提交
393
static bool hasTagValOutput(SQuery* pQuery) {
H
Haojun Liao 已提交
394
  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
H
Haojun Liao 已提交
395 396 397 398
  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 已提交
399
      SExprInfo *pLocalExprInfo = &pQuery->pExpr1[idx];
H
Haojun Liao 已提交
400 401 402 403 404 405 406 407 408 409 410

      // 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 已提交
411 412 413 414 415 416 417 418 419 420 421 422
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;
}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, SQueryRuntimeEnv* pRuntimeEnv) {
  // more than the capacity, reallocate the resources
  if (pResultRowInfo->size < pResultRowInfo->capacity) {
    return;
  }

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

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

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

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

  pResultRowInfo->capacity = (int32_t)newCapacity;
}

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

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

478
  if (!existed) {
479
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
480

481 482 483 484 485 486 487 488 489 490 491 492 493
    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;
494
    }
H
Haojun Liao 已提交
495

496
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
497
    pResultRowInfo->curIndex = pResultRowInfo->size++;
498
  }
499

500
  // too many time window in query
H
Haojun Liao 已提交
501
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
502 503 504
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
505
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
506 507
}

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
static void getInitialStartTimeWindow(SQuery* pQuery, TSKEY ts, STimeWindow* w) {
  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);

    int64_t key = w->skey;
    while(key < ts) { // moving towards end
      if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
        key = taosTimeAdd(key, pQuery->interval.sliding, pQuery->interval.slidingUnit, pQuery->precision);
      } else {
        key += pQuery->interval.sliding;
      }

      if (key >= ts) {
        break;
      }

      w->skey = key;
    }
  }
}

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

H
Haojun Liao 已提交
536
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
537 538 539 540 541 542
    if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
      getInitialStartTimeWindow(pQuery, ts, &w);
      pResultRowInfo->prevSKey = w.skey;
    } else {
      w.skey = pResultRowInfo->prevSKey;
    }
H
Haojun Liao 已提交
543

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

555
  if (w.skey > ts || w.ekey < ts) {
556 557 558
    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;
559 560
    } else {
      int64_t st = w.skey;
561

562
      if (st > ts) {
563
        st -= ((st - ts + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
564
      }
565

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

571
      w.skey = st;
572
      w.ekey = w.skey + pQuery->interval.interval - 1;
573
    }
574
  }
575

576 577 578 579 580 581 582
  /*
   * 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;
  }
583

584 585 586
  return w;
}

H
Haojun Liao 已提交
587 588
// 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) {
589
  if (pWindowRes->pageId != -1) {
590 591
    return 0;
  }
592

593
  tFilePage *pData = NULL;
594

595 596
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
597
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
598

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

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

616 617 618
  if (pData == NULL) {
    return -1;
  }
619

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

H
Haojun Liao 已提交
625
    pData->num += size;
626
    assert(pWindowRes->pageId >= 0);
627
  }
628

629 630 631
  return 0;
}

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

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

644
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
645
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
646
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQuery->intermediateResultRowSize);
H
Haojun Liao 已提交
647
    if (ret != TSDB_CODE_SUCCESS) {
648 649 650
      return -1;
    }
  }
651

652
  // set time window for current result
H
Haojun Liao 已提交
653
  pResultRow->win = (*win);
654
  *pResult = pResultRow;
H
Haojun Liao 已提交
655
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
656

657 658 659
  return TSDB_CODE_SUCCESS;
}

660 661 662 663 664 665 666 667 668
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 已提交
669
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
670 671 672 673 674 675 676 677
  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 已提交
678
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
679 680
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
681

H
Haojun Liao 已提交
682 683 684 685
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
686

H
Haojun Liao 已提交
687 688 689 690 691 692 693 694 695 696 697 698
      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;
      }
699 700
    }
  }
701

H
Haojun Liao 已提交
702
  assert(forwardStep > 0);
703 704 705
  return forwardStep;
}

706
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
707
  int64_t skey = TSKEY_INITIAL_VAL;
708 709 710
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
711
    if (pResult->closed) {
712
      break;
H
Haojun Liao 已提交
713 714
    }

715
    // new closed result rows
716 717 718 719 720 721 722 723 724 725
    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 已提交
726
    } else {
727 728 729 730 731
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
732 733 734
    }
  }

735
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
736
  if (skey == TSKEY_INITIAL_VAL) {
737
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
738 739
  } else {

740 741 742 743 744
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
745
    }
746

D
fix bug  
dapan1121 已提交
747
    if (i == pResultRowInfo->size - 1) {
748
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
749 750 751 752
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

753
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
754
  }
755
}
756

H
Haojun Liao 已提交
757 758 759
static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, SQuery* pQuery, TSKEY lastKey) {
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
  if ((lastKey > pQuery->window.ekey && ascQuery) || (lastKey < pQuery->window.ekey && (!ascQuery))) {
760 761 762
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
763
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
764
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQuery->timeWindowInterpo);
765
  }
766 767 768
}

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

H
Haojun Liao 已提交
772
  int32_t num   = -1;
773
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
774
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
775

H
hjxilinx 已提交
776
  STableQueryInfo* item = pQuery->current;
777

778 779
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (ekey < pDataBlockInfo->window.ekey) {
780
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
781 782
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
783 784
      }
    } else {
785
      num = pDataBlockInfo->rows - startPos;
786
      if (updateLastKey) {
H
hjxilinx 已提交
787
        item->lastKey = pDataBlockInfo->window.ekey + step;
788 789 790 791
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
792
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
793 794
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
795 796 797 798
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
799
        item->lastKey = pDataBlockInfo->window.skey + step;
800 801 802
      }
    }
  }
803

H
Haojun Liao 已提交
804
  assert(num > 0);
805 806 807
  return num;
}

H
Haojun Liao 已提交
808 809
static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, STimeWindow* pWin, int32_t offset,
                             int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput) {
810
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
811 812
  bool hasPrev = pCtx[0].preAggVals.isSet;

813
  for (int32_t k = 0; k < numOfOutput; ++k) {
814
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
815
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
816

817
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
818 819

    int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1);
820 821
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
822 823 824 825 826
    }

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

H
Haojun Liao 已提交
828
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
829

830 831 832 833 834
    // 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 已提交
835

836 837
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
838
    }
839 840 841

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
842
    pCtx[k].pInput = start;
843 844 845 846
  }
}


H
Haojun Liao 已提交
847
static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
848
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
849
  getNextTimeWindow(pQuery, pNext);
850

H
Haojun Liao 已提交
851
  // next time window is not in current block
H
Haojun Liao 已提交
852 853
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
854 855
    return -1;
  }
856

H
Haojun Liao 已提交
857 858
  TSKEY startKey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
859
    startKey = pNext->skey;
H
Haojun Liao 已提交
860 861
    if (startKey < pQuery->window.skey) {
      startKey = pQuery->window.skey;
862
    }
H
Haojun Liao 已提交
863
  } else {
H
Haojun Liao 已提交
864
    startKey = pNext->ekey;
H
Haojun Liao 已提交
865 866
    if (startKey > pQuery->window.skey) {
      startKey = pQuery->window.skey;
867
    }
H
Haojun Liao 已提交
868
  }
869

H
Haojun Liao 已提交
870
  int32_t startPos = 0;
H
Haojun Liao 已提交
871

H
Haojun Liao 已提交
872
  // tumbling time window query, a special case of sliding time window query
873
  if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) {
H
Haojun Liao 已提交
874 875 876
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
877
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
878
      startPos = 0;
H
Haojun Liao 已提交
879
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
880 881 882 883
      startPos = pDataBlockInfo->rows - 1;
    } else {
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order);
    }
H
Haojun Liao 已提交
884
  }
885

H
Haojun Liao 已提交
886 887 888 889
  /*
   * 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 已提交
890 891 892
  if (primaryKeys == NULL) {
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
893
    } else {
H
Haojun Liao 已提交
894
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
895
    }
H
Haojun Liao 已提交
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
  } 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;
      }
915
    }
916
  }
917

H
Haojun Liao 已提交
918
  return startPos;
919 920
}

H
Haojun Liao 已提交
921
static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
922 923 924 925 926 927 928 929 930 931 932 933
  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;
    }
  }
934

935 936 937
  return ekey;
}

H
Haojun Liao 已提交
938 939 940 941 942 943 944 945 946 947 948 949
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;
    }
  }
}

950
// window start key interpolation
H
Haojun Liao 已提交
951

952

H
Haojun Liao 已提交
953
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
954
    int32_t rowIndex) {
955 956 957 958 959 960 961
  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 已提交
962
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
963 964 965
  }
}

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

H
Haojun Liao 已提交
969
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
970
  if (tsCols == NULL) {
H
Haojun Liao 已提交
971
    ts = ascQuery? win->skey : win->ekey;
972
  } else {
H
Haojun Liao 已提交
973
    int32_t offset = ascQuery? 0:rows-1;
974 975 976 977 978 979
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
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 已提交
1003
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
1004
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
1005

H
Haojun Liao 已提交
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
    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 已提交
1030
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
1031
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
1032 1033 1034 1035 1036 1037 1038

    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 已提交
1039
      if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || pCol->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
H
Haojun Liao 已提交
1040 1041
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
H
Haojun Liao 已提交
1042

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

H
Haojun Liao 已提交
1047
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
1048
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
1049
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1050
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
1051
        }
H
Haojun Liao 已提交
1052 1053 1054 1055 1056
      }
    }
  }
}

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

H
Haojun Liao 已提交
1060
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1061
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1062
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
1063
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
1064 1065 1066 1067 1068
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

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

H
Haojun Liao 已提交
1072
  for (int32_t k = 0; k < numOfOutput; ++k) {
1073 1074
    pCtx[k].startTs = pQuery->window.skey;
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
1075 1076 1077
  }
}

H
Haojun Liao 已提交
1078 1079
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 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
  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 已提交
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
    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 已提交
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132

      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 已提交
1133 1134
static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, int32_t pos,
                                              int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols, STimeWindow* win) {
H
Haojun Liao 已提交
1135 1136 1137
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
1138 1139
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

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

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

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

H
Haojun Liao 已提交
1159 1160
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1161 1162 1163 1164
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1165
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
  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 已提交
1191 1192
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
  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 已提交
1214
        tsCols, win);
H
Haojun Liao 已提交
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
    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 已提交
1242 1243 1244
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
  STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info;

H
Haojun Liao 已提交
1245 1246 1247
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
  SQuery*           pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1248 1249

  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
H
Haojun Liao 已提交
1250 1251
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

H
Haojun Liao 已提交
1252
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1253

H
Haojun Liao 已提交
1254 1255 1256
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1257
    tsCols = (int64_t*) pColDataInfo->pData;
H
Haojun Liao 已提交
1258 1259
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1260 1261
  }

H
Haojun Liao 已提交
1262
  int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1);
H
Haojun Liao 已提交
1263
  TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1264 1265

  STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQuery);
H
Haojun Liao 已提交
1266
  bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);
H
Haojun Liao 已提交
1267

H
Haojun Liao 已提交
1268 1269 1270
  SResultRow* pResult = NULL;
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                        numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1271
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1272
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1273 1274 1275
  }

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1276 1277
  TSKEY   ekey = reviseWindowEkey(pQuery, &win);
  forwardStep =
H
Haojun Liao 已提交
1278
      getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1279 1280

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1281
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1282 1283
  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 已提交
1284
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1285
      if (pRes->closed) {
H
Haojun Liao 已提交
1286 1287
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1288
        continue;
H
Haojun Liao 已提交
1289
      }
H
Haojun Liao 已提交
1290 1291

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1292 1293
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1294 1295 1296 1297 1298
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

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

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

H
Haojun Liao 已提交
1303
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1304
      setNotInterpoWindowKey(pInfo->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1305

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

H
Haojun Liao 已提交
1309
    // restore current time window
H
Haojun Liao 已提交
1310 1311
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1312 1313 1314
    if (ret != TSDB_CODE_SUCCESS) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
H
Haojun Liao 已提交
1315 1316 1317
  }

  // window start key interpolation
H
Haojun Liao 已提交
1318
  doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
1319
  doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1320 1321 1322 1323

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1324
    startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1325 1326
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1327 1328
    }

H
Haojun Liao 已提交
1329
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1330 1331
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1332
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1333
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1334 1335
    }

H
Haojun Liao 已提交
1336
    ekey = reviseWindowEkey(pQuery, &nextWin);
1337
    forwardStep = getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1338 1339

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

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

H
Haojun Liao 已提交
1349
  updateResultRowInfoActiveIndex(pResultRowInfo, pQuery, pQuery->current->lastKey);
H
Haojun Liao 已提交
1350 1351
}

H
Haojun Liao 已提交
1352 1353 1354
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  STableQueryInfo*  item = pRuntimeEnv->pQuery->current;
H
Haojun Liao 已提交
1355

H
Haojun Liao 已提交
1356
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1357 1358
  int16_t          bytes = pColInfoData->info.bytes;
  int16_t          type = pColInfoData->info.type;
D
fix bug  
dapan1121 已提交
1359
  SQuery    *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1360 1361

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

H
Haojun Liao 已提交
1366
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
sangshuduo's avatar
sangshuduo 已提交
1367
    char* val = ((char*)pColInfoData->pData) + bytes * j;
H
Haojun Liao 已提交
1368
    if (isNull(val, type)) {
H
Haojun Liao 已提交
1369 1370 1371
      continue;
    }

1372
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1373 1374 1375 1376 1377 1378 1379
    if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) {
      if (pInfo->prevData == NULL) {
        pInfo->prevData = malloc(bytes);
      }

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

D
fix bug  
dapan1121 已提交
1380 1381 1382 1383
      if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
        setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, val, bytes);
      }

H
Haojun Liao 已提交
1384 1385 1386 1387 1388
      int32_t ret =
          setGroupResultOutputBuf(pRuntimeEnv, pInfo, pOperator->numOfOutput, val, type, bytes, item->groupIndex);
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR);
      }
H
Haojun Liao 已提交
1389 1390
    }

H
Haojun Liao 已提交
1391
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1392
      pInfo->binfo.pCtx[k].size = 1;
H
Haojun Liao 已提交
1393 1394
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1395
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1396 1397 1398 1399 1400
      }
    }
  }
}

1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSWindowOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  STableQueryInfo*  item = pRuntimeEnv->pQuery->current;

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

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

  int64_t gap = pOperator->pRuntimeEnv->pQuery->sw.gap;
  pInfo->numOfRows = 0;

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

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

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

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

  SResultRow* pResult = NULL;

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

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

H
Haojun Liao 已提交
1461
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
  int64_t v = -1;
  GET_TYPED_DATA(v, int64_t, type, pData);
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
    if (pResultRow->key == NULL) {
      pResultRow->key = malloc(varDataTLen(pData));
      varDataCopy(pResultRow->key, pData);
    } else {
      assert(memcmp(pResultRow->key, pData, varDataTLen(pData)) == 0);
    }
  } else {
    pResultRow->win.skey = v;
    pResultRow->win.ekey = v;
  }
H
Haojun Liao 已提交
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
}

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

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

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

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

H
Haojun Liao 已提交
1495
  setResultRowKey(pResultRow, pData, type);
H
Haojun Liao 已提交
1496
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
1497
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
H
Haojun Liao 已提交
1498 1499 1500 1501 1502
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1503 1504
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1505 1506
  return TSDB_CODE_SUCCESS;
}
1507

H
Haojun Liao 已提交
1508
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525
  for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) {
    SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, k);
    if (TSDB_COL_IS_TAG(pColIndex->flag)) {
      continue;
    }

    int32_t colId = pColIndex->colId;

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

  assert(0);
sangshuduo's avatar
sangshuduo 已提交
1526
  return -1;
H
Haojun Liao 已提交
1527 1528
}

1529
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1530
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
hjxilinx 已提交
1531
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1532 1533 1534 1535 1536

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

1538 1539 1540
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1541

1542
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
hjxilinx 已提交
1543 1544
    return QUERY_IS_ASC_QUERY(pQuery);
  }
1545

H
Haojun Liao 已提交
1546
  // denote the order type
1547
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
1548
    return pCtx->param[0].i64 == pQuery->order.order;
1549 1550
  }

1551 1552 1553
  // 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)) {
1554 1555
    return false;
  }
1556

1557 1558 1559
  return true;
}

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

H
Haojun Liao 已提交
1563 1564 1565 1566
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1567 1568 1569 1570 1571 1572
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1573
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1574 1575

  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1576
  if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
1577
    pCtx->preAggVals.isSet  = true;
H
Haojun Liao 已提交
1578 1579
    pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey;
    pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey;
H
Haojun Liao 已提交
1580
  }
H
Haojun Liao 已提交
1581 1582
}

H
Haojun Liao 已提交
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
// 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;
}
1624

H
Haojun Liao 已提交
1625
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1626
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1627 1628
  SQuery* pQuery = pRuntimeEnv->pQuery;

1629 1630
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1631
    return NULL;
1632 1633
  }

H
Haojun Liao 已提交
1634
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1635 1636 1637 1638
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1639

H
Haojun Liao 已提交
1640 1641
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base;
1642
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1643

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

Y
TD-1230  
yihaoDeng 已提交
1646
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1647 1648
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1649
    } else {
1650 1651
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1652

H
Haojun Liao 已提交
1653 1654
    pCtx->inputBytes = pSqlFuncMsg->colBytes;
    pCtx->inputType  = pSqlFuncMsg->colType;
H
Haojun Liao 已提交
1655

1656
    pCtx->ptsOutputBuf = NULL;
1657

H
Haojun Liao 已提交
1658 1659
    pCtx->outputBytes  = pExpr[i].bytes;
    pCtx->outputType   = pExpr[i].type;
1660

1661
    pCtx->order        = pQuery->order.order;
H
Haojun Liao 已提交
1662
    pCtx->functionId   = pSqlFuncMsg->functionId;
H
Haojun Liao 已提交
1663
    pCtx->stableQuery  = pQuery->stableQuery;
H
Haojun Liao 已提交
1664
    pCtx->interBufBytes = pExpr[i].interBytes;
1665 1666
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1667

H
Haojun Liao 已提交
1668
    pCtx->numOfParams  = pSqlFuncMsg->numOfParams;
1669 1670 1671
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
      int16_t type = pSqlFuncMsg->arg[j].argType;
      int16_t bytes = pSqlFuncMsg->arg[j].argBytes;
1672 1673 1674 1675
      if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) {
        continue;
      }

1676
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
1677
        tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type);
1678 1679 1680 1681
      } else {
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type);
      }
    }
1682

1683 1684
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1685

1686
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1687
      int32_t f = pExpr[0].base.functionId;
1688
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1689

H
Haojun Liao 已提交
1690
      pCtx->param[2].i64 = pQuery->order.order;
1691
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1692
      pCtx->param[3].i64 = functionId;
1693
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1694

1695
      pCtx->param[1].i64 = pQuery->order.orderColId;
H
Haojun Liao 已提交
1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
    } 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) {
1708
      pCtx->param[0].i64 = pQuery->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1709 1710 1711 1712 1713 1714 1715 1716
      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];
1717
    }
H
Haojun Liao 已提交
1718
  }
1719

H
Haojun Liao 已提交
1720
  for(int32_t i = 1; i < numOfOutput; ++i) {
sangshuduo's avatar
sangshuduo 已提交
1721 1722
    (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) +
        pExpr[i - 1].interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
1723
  }
1724

H
Haojun Liao 已提交
1725 1726
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1727
  return pFuncCtx;
H
Haojun Liao 已提交
1728 1729
}

H
Haojun Liao 已提交
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
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 已提交
1748
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables) {
H
Haojun Liao 已提交
1749
  qDebug("QInfo:%"PRIu64" setup runtime env", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
  SQuery *pQuery = pRuntimeEnv->pQuery;

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

  pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
  pRuntimeEnv->keyBuf  = malloc(pQuery->maxSrcColumnSize + sizeof(int64_t));
  pRuntimeEnv->pool    = initResultRowPool(getResultRowSize(pRuntimeEnv));
  pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQuery->numOfCols + pQuery->srcRowSize);
  pRuntimeEnv->tagVal  = malloc(pQuery->tagLen);
H
Haojun Liao 已提交
1760 1761
  pRuntimeEnv->currentOffset = pQuery->limit.offset;

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

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

H
Haojun Liao 已提交
1767 1768
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1769 1770 1771
    goto _clean;
  }

H
Haojun Liao 已提交
1772 1773 1774 1775 1776 1777
  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 已提交
1778

H
Haojun Liao 已提交
1779 1780
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1781

H
Haojun Liao 已提交
1782
  qDebug("QInfo:%"PRIu64" init runtime environment completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1783 1784

  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
1785
  // interval (down sampling operation)
H
Haojun Liao 已提交
1786 1787 1788
  if (onlyQueryTags(pQuery)) {  // do nothing for tags query

  } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
1789
    if (pQuery->stableQuery) {
H
Haojun Liao 已提交
1790 1791
      pRuntimeEnv->proot = createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner,
                                                                    pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1792
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1793
    } else {
H
Haojun Liao 已提交
1794 1795
      pRuntimeEnv->proot =
          createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1796
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1797

H
Haojun Liao 已提交
1798
      if (pQuery->pExpr2 != NULL) {
H
Haojun Liao 已提交
1799 1800
        pRuntimeEnv->proot =
            createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1801
      }
H
Haojun Liao 已提交
1802

H
Haojun Liao 已提交
1803
      if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
1804 1805
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
H
Haojun Liao 已提交
1806
      }
H
Haojun Liao 已提交
1807
    }
H
Haojun Liao 已提交
1808

H
Haojun Liao 已提交
1809 1810 1811 1812
  } else if (pQuery->groupbyColumn) {
    pRuntimeEnv->proot =
        createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1813

1814 1815 1816 1817 1818 1819 1820
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
    }
  } else if (pQuery->sw.gap > 0) {
    pRuntimeEnv->proot = createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);

H
Haojun Liao 已提交
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
    }
  } else if (isFixedOutputQuery(pQuery)) {
    if (pQuery->stableQuery && !isTsCompQuery(pQuery)) {
      pRuntimeEnv->proot =
          createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    } else {
      pRuntimeEnv->proot =
          createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    }
1832

H
Haojun Liao 已提交
1833
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1834

H
Haojun Liao 已提交
1835 1836
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1837
    }
H
Haojun Liao 已提交
1838 1839 1840 1841 1842 1843
  } else {  // diff/add/multiply/subtract/division
    assert(pQuery->checkResultBuf == 1);
    if (!onlyQueryTags(pQuery)) {
      pRuntimeEnv->proot =
          createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1844
    }
H
Haojun Liao 已提交
1845
  }
H
Haojun Liao 已提交
1846

D
dapan1121 已提交
1847 1848 1849 1850
  if (pQuery->havingNum > 0) {
    pRuntimeEnv->proot = createHavingOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr1, pQuery->numOfOutput);
  }

H
Haojun Liao 已提交
1851 1852 1853
  if (pQuery->limit.offset > 0) {
    pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }
H
Haojun Liao 已提交
1854

H
Haojun Liao 已提交
1855 1856 1857 1858 1859
  if (pQuery->limit.limit > 0) {
    pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }

  return TSDB_CODE_SUCCESS;
1860

1861
_clean:
1862
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1863 1864 1865 1866
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1867

1868
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1869 1870
}

H
Haojun Liao 已提交
1871
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1872
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1873 1874 1875 1876

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

H
Haojun Liao 已提交
1877
  SMemRef* pMemRef = &pQuery->memRef;
1878
  assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
H
Haojun Liao 已提交
1879 1880
}

H
Haojun Liao 已提交
1881
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
1882
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1883
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1884

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

1887 1888 1889
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1890
      tfree(pRuntimeEnv->sasArray[i].colList);
1891 1892 1893 1894 1895
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1896
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1897
  doFreeQueryHandle(pRuntimeEnv);
1898

H
Haojun Liao 已提交
1899
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1900

S
TD-1848  
Shengliang Guan 已提交
1901
  tfree(pRuntimeEnv->keyBuf);
1902
  tfree(pRuntimeEnv->prevRow);
1903 1904
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1905 1906
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1907

H
Haojun Liao 已提交
1908 1909 1910
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1911
  destroyOperatorInfo(pRuntimeEnv->proot);
D
dapan1121 已提交
1912 1913 1914 1915 1916

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

1917 1918
}

1919 1920 1921 1922
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1923
bool isQueryKilled(SQInfo *pQInfo) {
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
  if (IS_QUERY_KILLED(pQInfo)) {
    return true;
  }

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

    assert(pQInfo->startExecTs != 0);
H
Haojun Liao 已提交
1934 1935
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1936 1937 1938 1939 1940 1941
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
1944
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
1945
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
1946 1947
    return false;
  }
1948

1949
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1950
  if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) {
1951 1952
    return true;
  }
1953

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

1957 1958
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
1959
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
1960 1961
      continue;
    }
1962

1963 1964 1965
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
1966

H
Haojun Liao 已提交
1967
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
1968 1969 1970
      return true;
    }
  }
1971

1972 1973 1974
  return false;
}

1975
// todo refactor with isLastRowQuery
1976
bool isPointInterpoQuery(SQuery *pQuery) {
1977
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1978 1979
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
1980 1981 1982
      return true;
    }
  }
1983

1984 1985 1986 1987
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
1988
static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) {
1989
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1990
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1991 1992 1993
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
1994

1995 1996 1997 1998 1999
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
2000

2001 2002 2003
  return false;
}

H
hjxilinx 已提交
2004
static bool isFirstLastRowQuery(SQuery *pQuery) {
2005
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2006
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
2007 2008 2009 2010
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
2011

2012 2013 2014
  return false;
}

H
hjxilinx 已提交
2015
static bool needReverseScan(SQuery *pQuery) {
2016
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2017
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2018 2019 2020
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
2021

2022
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
2023 2024
      return true;
    }
2025 2026

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
2027
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
2028
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
2029 2030 2031
      if (order != pQuery->order.order) {
        return true;
      }
2032
    }
2033
  }
2034

2035 2036
  return false;
}
H
hjxilinx 已提交
2037

H
Haojun Liao 已提交
2038 2039 2040 2041
/**
 * 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 已提交
2042
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
2043
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2044
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
2045 2046

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
2047 2048 2049 2050

    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 已提交
2051
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
2052 2053 2054
      return false;
    }
  }
2055

H
hjxilinx 已提交
2056 2057 2058
  return true;
}

2059 2060
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2061
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
2062 2063
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
2064 2065

  /*
2066
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
2067 2068
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
2069 2070
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
2071
    win->ekey = INT64_MAX;
2072 2073
  } 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 已提交
2074
  } else {
2075
    win->ekey = win->skey + pQuery->interval.interval - 1;
2076 2077 2078 2079 2080
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
2081
    pQuery->checkResultBuf = 0;
2082
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
2083
    pQuery->checkResultBuf = 0;
2084 2085
  } else {
    bool hasMultioutput = false;
2086
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2087
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
2088 2089 2090
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
2091

H
Haojun Liao 已提交
2092
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
2093 2094 2095 2096
      if (!hasMultioutput) {
        break;
      }
    }
2097

H
Haojun Liao 已提交
2098
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
2099 2100 2101 2102 2103 2104
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2105
bool colIdCheck(SQuery *pQuery, uint64_t qId) {
2106 2107
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
2108
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
H
Haojun Liao 已提交
2109
      qError("QInfo:%"PRIu64" invalid data load column for query", qId);
2110 2111 2112
      return false;
    }
  }
2113

2114 2115 2116 2117 2118 2119
  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) {
2120
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2121
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2122

2123 2124 2125 2126
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2127

2128 2129 2130 2131
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2132

2133 2134 2135 2136 2137 2138 2139
  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); }

2140
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2141 2142
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2143
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2144
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2145 2146 2147

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

2150 2151 2152 2153
      // 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 已提交
2154 2155 2156 2157
    }
  }
}

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

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

2165 2166
  // 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 已提交
2167
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
2168
    qDebug("QInfo:%"PRIu64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId, pQuery->order.order, TSDB_ORDER_ASC);
2169

H
Haojun Liao 已提交
2170
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2171 2172 2173
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2174

2175 2176
    return;
  }
2177

2178
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2179
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2180 2181 2182
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2183

2184
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2185 2186 2187
    return;
  }

2188
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2189
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2190
      qDebug(msg, pQInfo->qId, "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);
H
Haojun Liao 已提交
2191 2192
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2193

2194
    pQuery->order.order = TSDB_ORDER_ASC;
2195 2196
    return;
  }
2197

2198
  if (pQuery->interval.interval == 0) {
2199 2200
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2201
        qDebug(msg, pQInfo->qId, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2202 2203
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2204
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2205
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2206
      }
2207

2208
      pQuery->order.order = TSDB_ORDER_ASC;
2209 2210
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2211
        qDebug(msg, pQInfo->qId, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2212 2213
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2214
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2215
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2216
      }
2217

2218
      pQuery->order.order = TSDB_ORDER_DESC;
2219
    }
2220

2221
  } else {  // interval query
2222
    if (stableQuery) {
2223 2224
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2225
          qDebug(msg, pQInfo->qId, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2226 2227
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2228
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2229
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2230
        }
2231

2232
        pQuery->order.order = TSDB_ORDER_ASC;
2233 2234
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2235
          qDebug(msg, pQInfo->qId, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2236 2237
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2238
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2239
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2240
        }
2241

2242
        pQuery->order.order = TSDB_ORDER_DESC;
2243 2244 2245 2246 2247
      }
    }
  }
}

2248 2249
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2250
  int32_t MIN_ROWS_PER_PAGE = 4;
2251

H
Haojun Liao 已提交
2252
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2253 2254 2255 2256
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2261 2262
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2263 2264
}

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

H
Haojun Liao 已提交
2267
static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) {
H
Haojun Liao 已提交
2268
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2269

H
Haojun Liao 已提交
2270
  if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) {
2271 2272 2273 2274 2275
    return true;
  }

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

H
Haojun Liao 已提交
2277 2278 2279 2280 2281 2282 2283 2284
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2285
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2286
    if (index == -1) {
H
Haojun Liao 已提交
2287
      return true;
2288
    }
2289

2290
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2291
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2292
      return true;
2293
    }
2294

2295
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2296
    if (pDataStatis[index].numOfNull == numOfRows) {
2297 2298 2299 2300

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2301
        if (pFilterElem->fp == isNullOperator) {
2302 2303 2304 2305
          return true;
        }
      }

2306 2307
      continue;
    }
2308

H
Haojun Liao 已提交
2309 2310 2311
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2315
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2316
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2317 2318 2319 2320 2321
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2322
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2323 2324 2325 2326 2327
          return true;
        }
      }
    }
  }
2328

H
Haojun Liao 已提交
2329
  return false;
2330 2331
}

H
Haojun Liao 已提交
2332 2333 2334 2335 2336 2337 2338 2339
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 已提交
2340
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2341

H
Haojun Liao 已提交
2342
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2343 2344 2345 2346
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2347
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2348
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2349 2350 2351
        break;
      }

H
Haojun Liao 已提交
2352 2353
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2354 2355 2356 2357 2358
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2359 2360 2361
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2362 2363 2364 2365
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2366
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2367 2368 2369 2370
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2371 2372
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2373 2374 2375 2376 2377 2378 2379 2380
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
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;
}
2406

H
Haojun Liao 已提交
2407
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
H
Haojun Liao 已提交
2408
                        SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2409 2410 2411 2412 2413
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2414
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

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

      if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) {
        break;
      }
    }
H
Haojun Liao 已提交
2435 2436 2437

    // save the cursor status
    pRuntimeEnv->pQuery->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
2438 2439 2440
  } else {
    for (int32_t i = 0; i < numOfRows; ++i) {
      bool qualified = false;
H
Haojun Liao 已提交
2441

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

H
Haojun Liao 已提交
2445 2446 2447
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2448

H
Haojun Liao 已提交
2449 2450 2451 2452 2453 2454 2455 2456
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2457
          } else {
H
Haojun Liao 已提交
2458 2459 2460 2461 2462 2463
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2464
          }
H
Haojun Liao 已提交
2465 2466

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2467 2468 2469 2470 2471
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2472
        if (!qualified) {
H
Haojun Liao 已提交
2473 2474 2475 2476
          break;
        }
      }

H
Haojun Liao 已提交
2477
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2478
      if (!qualified) {
H
Haojun Liao 已提交
2479
        all = false;
H
Haojun Liao 已提交
2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496
      }
    }
  }

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

            int16_t bytes = pColumnInfoData->info.bytes;
sangshuduo's avatar
sangshuduo 已提交
2497
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2498 2499 2500
          }

          start += len;
2501
          len = 0;
H
Haojun Liao 已提交
2502 2503 2504 2505
        }
      }
    }

2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518
    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 已提交
2519 2520 2521 2522
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

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

H
Haojun Liao 已提交
2527 2528
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
H
Haojun Liao 已提交
2529 2530 2531 2532 2533 2534
    }
  }

  tfree(p);
}

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

H
Haojun Liao 已提交
2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574
static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) {
  SQLFunctionCtx* pCtx = pTableScanInfo->pCtx;
  uint32_t status = BLK_DATA_NO_NEEDED;

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

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

  return status;
}

static void doSetFilterColumnInfo(SQuery* pQuery, SSDataBlock* pBlock) {
  if (pQuery->numOfFilterCols > 0 && pQuery->pFilterInfo[0].pData != NULL) {
    return;
  }

  // set the initial static data value filter expression
  for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j);

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

H
Haojun Liao 已提交
2575 2576
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2577
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2578
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2579
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2580

H
Haojun Liao 已提交
2581
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2582
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
2583
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQuery);
H
Haojun Liao 已提交
2584

H
Haojun Liao 已提交
2585
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2586 2587
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2588
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2589
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2590

H
Haojun Liao 已提交
2591
    if (pQuery->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2592 2593 2594 2595 2596 2597 2598
      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);
H
Haojun Liao 已提交
2599
      setTimestampListJoinInfo(pRuntimeEnv, &t, pQuery->current);
H
Haojun Liao 已提交
2600 2601 2602 2603 2604 2605

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

H
Haojun Liao 已提交
2609 2610
  // 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.
2611
  if (pQuery->numOfFilterCols > 0 || pQuery->groupbyColumn || pQuery->sw.gap > 0 ||
H
Haojun Liao 已提交
2612 2613 2614
      (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info))) {
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2615

H
Haojun Liao 已提交
2616 2617 2618 2619 2620 2621
  // check if this data block is required to load
  if ((*status) != BLK_DATA_ALL_NEEDED) {
    // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet,
    // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer
    if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
      SResultRow* pResult = NULL;
H
Haojun Liao 已提交
2622

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

H
Haojun Liao 已提交
2626 2627 2628 2629 2630
      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQuery);
      if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                  pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                  pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
2631
      }
H
Haojun Liao 已提交
2632
    } else if (pQuery->stableQuery && (!isTsCompQuery(pQuery))) { // stable aggregate, not interval aggregate or normal column aggregate
2633 2634 2635
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
                               pQuery->current->groupIndex);
H
Haojun Liao 已提交
2636
    }
H
Haojun Liao 已提交
2637 2638

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

H
Haojun Liao 已提交
2641
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2642
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
2643
    qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2644
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2645 2646 2647 2648
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2649
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2650

H
Haojun Liao 已提交
2651
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2652
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2653
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2654 2655 2656 2657 2658 2659
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2662
    if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677
      { // set previous window
        if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
          SResultRow* pResult = NULL;

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

          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQuery);
          if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                      pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                      pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
            longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
          }
        }
      }
H
Haojun Liao 已提交
2678 2679
      bool load = false;
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2680
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2681
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2682 2683
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2684
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2685
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2686
            qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2687
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2688 2689 2690 2691 2692 2693 2694 2695
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2696
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2697
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2698
      qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2699
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2700
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2701
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2702 2703 2704 2705
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2706
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2707
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2708 2709
      return terrno;
    }
H
Haojun Liao 已提交
2710

H
Haojun Liao 已提交
2711
    doSetFilterColumnInfo(pQuery, pBlock);
H
Haojun Liao 已提交
2712
    if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2713
      filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2714
    }
H
Haojun Liao 已提交
2715 2716 2717 2718 2719
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2720
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2721
  int32_t midPos = -1;
H
Haojun Liao 已提交
2722
  int32_t numOfRows;
2723

2724 2725 2726
  if (num <= 0) {
    return -1;
  }
2727

2728
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2729 2730

  TSKEY * keyList = (TSKEY *)pValue;
2731
  int32_t firstPos = 0;
2732
  int32_t lastPos = num - 1;
2733

2734
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2735 2736 2737 2738 2739
    // 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;
2740

H
Haojun Liao 已提交
2741 2742
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2743

H
hjxilinx 已提交
2744 2745 2746 2747 2748 2749 2750 2751
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2752

H
hjxilinx 已提交
2753 2754 2755 2756 2757
  } 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;
2758

H
hjxilinx 已提交
2759 2760 2761 2762 2763 2764 2765
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2766

H
Haojun Liao 已提交
2767
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2768
      midPos = (numOfRows >> 1u) + firstPos;
2769

H
hjxilinx 已提交
2770 2771 2772 2773 2774 2775 2776 2777 2778
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2779

H
hjxilinx 已提交
2780 2781 2782
  return midPos;
}

H
Haojun Liao 已提交
2783 2784 2785 2786 2787 2788
/*
 * 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);
2789

H
Haojun Liao 已提交
2790
  char* val = NULL;
H
Haojun Liao 已提交
2791
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2792
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2793 2794
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2795 2796
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2797

H
Haojun Liao 已提交
2798 2799 2800 2801
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2802

H
Haojun Liao 已提交
2803
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2804 2805 2806 2807
    int32_t maxLen = bytes - VARSTR_HEADER_SIZE;
    int32_t len = (varDataLen(val) > maxLen)? maxLen:varDataLen(val);
    tVariantCreateFromBinary(tag, varDataVal(val), len, type);
    //tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
H
Haojun Liao 已提交
2808 2809
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2810
  }
2811 2812
}

2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824
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 已提交
2825
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2826
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2827

H
Haojun Liao 已提交
2828 2829 2830 2831
  SExprInfo *pExpr  = pOperatorInfo->pExpr;
  SQuery    *pQuery = pRuntimeEnv->pQuery;

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

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

2838
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2839
    return;
H
Haojun Liao 已提交
2840 2841 2842 2843
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
H
Haojun Liao 已提交
2844

H
Haojun Liao 已提交
2845 2846 2847 2848 2849 2850 2851 2852 2853
    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 已提交
2854 2855
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type,
                           pLocalExprInfo->bytes);
H
Haojun Liao 已提交
2856 2857 2858 2859

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
2860
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2861 2862 2863 2864 2865
      }

      offset += pLocalExprInfo->bytes;
    }

H
Haojun Liao 已提交
2866
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2867
    if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2868
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2869
    }
H
Haojun Liao 已提交
2870
  }
H
Haojun Liao 已提交
2871

H
Haojun Liao 已提交
2872 2873 2874
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2875 2876
  }
}
2877

2878
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946
  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);
  }
}

2947
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
2948
  SQuery* pQuery = pRuntimeEnv->pQuery;
2949
  int32_t numOfCols = pQuery->numOfOutput;
2950
  printf("super table query intermediate result, total:%d\n", numOfRows);
2951

2952 2953
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2954

H
Haojun Liao 已提交
2955
      switch (pQuery->pExpr1[i].type) {
2956
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2957 2958
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
2959 2960 2961 2962 2963
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2964
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2965 2966
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2967
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2968 2969
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2970
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2971 2972
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2973
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2974 2975 2976 2977 2978 2979 2980
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2981
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2982
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2983
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2984 2985

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2986
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2987 2988 2989
    // 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 已提交
2990
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2991 2992 2993 2994
        return;
      }
    }

H
Haojun Liao 已提交
2995
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2996 2997

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2998
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2999 3000
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3001
        break;
H
Haojun Liao 已提交
3002 3003 3004
      }
    }

H
Haojun Liao 已提交
3005 3006 3007 3008
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
3009
    }
H
Haojun Liao 已提交
3010

H
Haojun Liao 已提交
3011 3012
}

3013 3014 3015 3016
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
3017

3018 3019
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3020

3021 3022
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
3023

H
Haojun Liao 已提交
3024
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
3025
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
3026 3027
}

H
Haojun Liao 已提交
3028 3029
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3030

H
Haojun Liao 已提交
3031
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
3032 3033 3034
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
3035

H
Haojun Liao 已提交
3036 3037 3038 3039
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
3040

H
Haojun Liao 已提交
3041 3042 3043 3044
      // 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 已提交
3045

H
Haojun Liao 已提交
3046
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
3047
    }
H
Haojun Liao 已提交
3048 3049
  }
}
H
Haojun Liao 已提交
3050

H
Haojun Liao 已提交
3051 3052 3053
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3054 3055 3056
  }
}

H
Haojun Liao 已提交
3057 3058 3059 3060 3061 3062
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3063

H
Haojun Liao 已提交
3064 3065 3066 3067 3068 3069 3070 3071
/*
 * The start of each column SResultRowCellInfo is denote by RowCellInfoOffset.
 * Note that in case of top/bottom query, the whole multiple rows of result is treated as only one row of results.
 * +------------+-----------------result column 1-----------+-----------------result column 2-----------+
 * + SResultRow | SResultRowCellInfo | intermediate buffer1 | SResultRowCellInfo | intermediate buffer 2|
 * +------------+-------------------------------------------+-------------------------------------------+
 *           offset[0]                                  offset[1]
 */
H
Haojun Liao 已提交
3072 3073 3074 3075 3076 3077
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 已提交
3078 3079
  int32_t tid = 0;
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
3080

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

H
Haojun Liao 已提交
3084 3085 3086 3087 3088 3089 3090 3091 3092 3093
    /*
     * 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);
3094

H
Haojun Liao 已提交
3095 3096 3097 3098 3099
    // 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;
    }
3100
  }
3101

H
Haojun Liao 已提交
3102
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3103
}
3104

H
Haojun Liao 已提交
3105 3106 3107
void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) {
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
  SSDataBlock* pDataBlock = pBInfo->pRes;
3108

H
Haojun Liao 已提交
3109 3110 3111 3112 3113 3114 3115
  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;
3116

H
Haojun Liao 已提交
3117 3118 3119 3120 3121
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        pInfo->bufCapacity = newSize;
      } else {
        // longjmp
3122 3123
      }
    }
H
Haojun Liao 已提交
3124
  }
3125

H
Haojun Liao 已提交
3126 3127 3128
  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;
3129

H
Haojun Liao 已提交
3130 3131 3132 3133
    // 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 已提交
3134
    }
H
Haojun Liao 已提交
3135 3136
  }
}
3137

H
Haojun Liao 已提交
3138
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3139 3140 3141 3142
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3143 3144
    }

H
Haojun Liao 已提交
3145
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3146
  }
H
Haojun Liao 已提交
3147
}
3148

H
Haojun Liao 已提交
3149
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3150
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3151
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3152 3153
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3154 3155
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3156 3157
  }
}
3158

H
Haojun Liao 已提交
3159
static void setupEnvForReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
3160
  SQuery *pQuery = pRuntimeEnv->pQuery;
3161

H
Haojun Liao 已提交
3162 3163 3164 3165
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3166
  }
3167

H
Haojun Liao 已提交
3168 3169 3170 3171
  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3172
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3173

H
Haojun Liao 已提交
3174
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3175
  SWITCH_ORDER(pQuery->order.order);
H
Haojun Liao 已提交
3176 3177

  setupQueryRangeForReverseScan(pRuntimeEnv);
3178 3179
}

H
Haojun Liao 已提交
3180
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3181
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3182
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3183 3184

  int32_t numOfOutput = pOperator->numOfOutput;
3185
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || pQuery->sw.gap > 0) {
H
Haojun Liao 已提交
3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196
    // 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 已提交
3197
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3198 3199 3200 3201 3202 3203 3204 3205 3206

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

      /*
       * set the number of output results for group by normal columns, the number of output rows usually is 1 except
       * the top and bottom query
       */
H
Haojun Liao 已提交
3207
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3208 3209 3210 3211 3212 3213 3214 3215 3216
    }

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

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

3221 3222 3223 3224
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3225

3226 3227 3228
  return false;
}

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

H
hjxilinx 已提交
3232 3233
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3234

3235
  pTableQueryInfo->pTable = pTable;
3236
  pTableQueryInfo->cur.vgroupIndex = -1;
3237

H
Haojun Liao 已提交
3238
  // set more initial size of interval/groupby query
3239
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
3240
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3241
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3242 3243 3244
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3245
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3246 3247
  }

3248 3249 3250
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3251
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3252 3253 3254
  if (pTableQueryInfo == NULL) {
    return;
  }
3255

H
Haojun Liao 已提交
3256
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3257
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3258 3259
}

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

H
Haojun Liao 已提交
3265
  int16_t offset = 0;
3266
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3267
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3268 3269 3270

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3271
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3272 3273
      continue;
    }
3274

3275
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, bufPage, pResult->offset, offset, pCtx[i].outputBytes);
H
Haojun Liao 已提交
3276
    offset += pCtx[i].outputBytes;
3277

3278
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3279
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3280
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3281
    }
3282

3283
    if (!pResInfo->initialized) {
3284
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3285 3286 3287 3288
    }
  }
}

3289 3290
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3291
  int64_t uid = 0;
H
Haojun Liao 已提交
3292
  SResultRow* pResultRow =
3293
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3294
  assert (pResultRow != NULL);
3295

3296 3297 3298 3299 3300
  /*
   * 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) {
3301 3302
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
    if (ret != TSDB_CODE_SUCCESS) {
3303
      return;
3304 3305 3306
    }
  }

3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
}

void setExecutionContext(SQueryRuntimeEnv* pRuntimeEnv, SOptrBasicInfo* pInfo, int32_t numOfOutput, int32_t groupIndex,
                         TSKEY nextKey) {
  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->pQuery->current;

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

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

3322 3323
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3324 3325
}

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

H
Haojun Liao 已提交
3331
  int16_t offset = 0;
3332
  for (int32_t i = 0; i < numOfCols; ++i) {
3333
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, page, pResult->offset, offset, pCtx[i].outputBytes);
H
Haojun Liao 已提交
3334
    offset += pCtx[i].outputBytes;
3335

3336 3337 3338
    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;
3339 3340
    }

3341 3342 3343 3344
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3345
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3346 3347 3348
  }
}

H
Haojun Liao 已提交
3349 3350
void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
3351

H
Haojun Liao 已提交
3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
  SSqlFuncMsg* pFuncMsg = &pExprInfo->base;
  if (pQuery->stableQuery && (pRuntimeEnv->pTsBuf != NULL) &&
      (pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) &&
      (pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
    assert(pFuncMsg->numOfParams == 1);

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

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

    int16_t tagType = pCtx[0].tag.nType;
    if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3365
      qDebug("QInfo:%"PRIu64" set tag value for join comparison, colId:%" PRId64 ", val:%s", GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3366 3367
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz);
    } else {
H
Haojun Liao 已提交
3368
      qDebug("QInfo:%"PRIu64" set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3369 3370 3371 3372 3373 3374
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64);
    }
  }
}

int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo) {
H
Haojun Liao 已提交
3375 3376
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387
  assert(pRuntimeEnv->pTsBuf != NULL);

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

    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) {
H
Haojun Liao 已提交
3388
        qError("QInfo:%"PRIu64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3389
      } else {
H
Haojun Liao 已提交
3390
        qError("QInfo:%"PRIu64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3391 3392 3393 3394 3395 3396 3397 3398
      }

      return -1;
    }

    // Keep the cursor info of current table
    pTableQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3399
      qDebug("QInfo:%"PRIu64" find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3400
    } else {
H
Haojun Liao 已提交
3401
      qDebug("QInfo:%"PRIu64" find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3402 3403 3404 3405 3406
    }

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

H
Haojun Liao 已提交
3413 3414 3415 3416 3417 3418
  return 0;
}

void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

H
Haojun Liao 已提交
3419 3420 3421
  int32_t numOfExprs = pQuery->numOfOutput;
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SExprInfo* pExprInfo = &(pExpr[i]);
H
Haojun Liao 已提交
3422
    if (pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3423 3424 3425 3426 3427 3428
      continue;
    }

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3432 3433 3434
    int32_t numOfGroup = (int32_t)taosArrayGetSize(pRuntimeEnv->prevResult);
    for (int32_t j = 0; j < numOfGroup; ++j) {
      SInterResult* p = taosArrayGet(pRuntimeEnv->prevResult, j);
H
Haojun Liao 已提交
3435
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
H
Haojun Liao 已提交
3436 3437
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3449

D
fix bug  
dapan1121 已提交
3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485
void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

  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 (bytes == 0 || memcmp(p->tags, val, bytes) == 0) {
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}



3486 3487 3488 3489 3490 3491 3492 3493 3494
/*
 * 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 已提交
3495
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3496 3497 3498
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3499

H
Haojun Liao 已提交
3500 3501 3502
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3503

H
Haojun Liao 已提交
3504 3505
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
3506

H
Haojun Liao 已提交
3507 3508 3509 3510 3511 3512
  /**
   * 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 已提交
3513
  STimeWindow w = TSWINDOW_INITIALIZER;
3514

H
Haojun Liao 已提交
3515 3516 3517
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
3518

H
Haojun Liao 已提交
3519 3520 3521
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
3522
    }
H
Haojun Liao 已提交
3523

H
Haojun Liao 已提交
3524
    pWindowResInfo->prevSKey = w.skey;
3525
  }
H
Haojun Liao 已提交
3526 3527

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3528 3529 3530
}

/**
H
Haojun Liao 已提交
3531
 * copyToOutputBuf support copy data in ascending/descending order
3532 3533 3534 3535 3536 3537 3538
 * 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 已提交
3539

H
Haojun Liao 已提交
3540
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3541
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3542
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3543 3544 3545 3546

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3547
  qDebug("QInfo:%"PRIu64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567
  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 已提交
3568 3569

    int16_t offset = 0;
H
Haojun Liao 已提交
3570 3571 3572 3573 3574
    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;
3575
      char *in  = getPosInResultPage(pRuntimeEnv, page, pRow->offset, offset, bytes);
H
Haojun Liao 已提交
3576
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3577 3578

      offset += bytes;
H
Haojun Liao 已提交
3579 3580 3581
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3582
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3583 3584 3585 3586
      break;
    }
  }

H
Haojun Liao 已提交
3587
  qDebug("QInfo:%"PRIu64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3588 3589 3590 3591 3592 3593
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3595
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3596
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3597 3598 3599 3600 3601
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3602
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3603 3604 3605

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

H
Haojun Liao 已提交
3606 3607 3608
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3609
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3610
  }
3611 3612
}

H
Haojun Liao 已提交
3613
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv *pRuntimeEnv,
H
Haojun Liao 已提交
3614
    SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
3615
  SQuery *pQuery = pRuntimeEnv->pQuery;
3616

3617
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3618 3619 3620
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
3621

3622 3623
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3624

3625 3626
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3627 3628
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3629
      }
H
Haojun Liao 已提交
3630

H
Haojun Liao 已提交
3631
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3632
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3633 3634 3635 3636 3637
    }
  }
}

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

H
Haojun Liao 已提交
3641
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3642

H
Haojun Liao 已提交
3643
  if (pQuery->pExpr2 == NULL) {
H
Haojun Liao 已提交
3644 3645 3646 3647
    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 已提交
3648 3649 3650
    }
  } else {
    for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3651 3652 3653
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3654
    }
3655
  }
3656

H
Haojun Liao 已提交
3657
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3658 3659
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3660

3661
  int32_t total = 0;
H
Haojun Liao 已提交
3662
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3663

3664
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3665
    STableIdInfo* pDst = (STableIdInfo*)data;
3666 3667 3668 3669
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3670
    data += sizeof(STableIdInfo);
3671 3672
    total++;

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

H
Haojun Liao 已提交
3677
  qDebug("QInfo:%"PRIu64" set %d subscribe info", pQInfo->qId, total);
H
Haojun Liao 已提交
3678
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3679 3680
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3681
  }
3682 3683
}

H
Haojun Liao 已提交
3684
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3685 3686 3687 3688 3689 3690
  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 已提交
3691
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3692
  tfree(p);
H
Haojun Liao 已提交
3693 3694
  return pOutput->info.rows;
}
3695

H
Haojun Liao 已提交
3696
void queryCostStatis(SQInfo *pQInfo) {
3697
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3698
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3699

H
Haojun Liao 已提交
3700
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3701
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3702 3703
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3704 3705 3706
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3707
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3708 3709 3710 3711 3712 3713 3714
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3715

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

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

3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756
//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 已提交
3757
//  qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
3758 3759
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3760

3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775
//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 已提交
3776
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3777 3778 3779 3780 3781 3782 3783 3784 3785 3786
//      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 已提交
3787
//      qDebug("QInfo:%"PRIu64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798
//             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 已提交
3799

3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834
//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
//
H
Haojun Liao 已提交
3835 3836
//    qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 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
//           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;
//}
3960

H
Haojun Liao 已提交
3961 3962
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

B
Bomin Zhang 已提交
3963
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
3964
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
3965 3966
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
Haojun Liao 已提交
3967
  // TODO set the tags scan handle
B
Bomin Zhang 已提交
3968
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
3969
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3970 3971
  }

H
Haojun Liao 已提交
3972
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
3973 3974 3975
  if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3976

B
Bomin Zhang 已提交
3977
  if (!isSTableQuery
H
Haojun Liao 已提交
3978
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3979
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3980
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
3981
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
3982
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
3983
  ) {
H
Haojun Liao 已提交
3984
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3985 3986
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3987
  }
B
Bomin Zhang 已提交
3988

B
Bomin Zhang 已提交
3989
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3990
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
3991
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
3992

H
Haojun Liao 已提交
3993 3994
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
3995
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3996
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3997
    } else {
H
Haojun Liao 已提交
3998
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3999
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
4000
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
4001

H
Haojun Liao 已提交
4002 4003 4004
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
4005

H
Haojun Liao 已提交
4006 4007 4008
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
4009 4010
      }
    }
4011
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4012
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
4013
  } else {
H
Haojun Liao 已提交
4014
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
4015
  }
4016

B
Bomin Zhang 已提交
4017
  return terrno;
B
Bomin Zhang 已提交
4018 4019
}

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

H
Haojun Liao 已提交
4023
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
4024 4025 4026 4027
  if (pFillCol == NULL) {
    return NULL;
  }

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

4031
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
4032
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
4033
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
4034
    pFillCol[i].tagIndex   = -2;
4035 4036
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
4037
    pFillCol[i].fillVal.i  = fillVal[i];
4038

4039 4040
    offset += pExprInfo->bytes;
  }
4041

4042 4043 4044
  return pFillCol;
}

D
dapan1121 已提交
4045
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bool isSTableQuery) {
4046 4047 4048
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

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

H
Haojun Liao 已提交
4051 4052
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
4053
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
H
Haojun Liao 已提交
4054
  pQuery->stabledev = isStabledev(pQuery);
H
Haojun Liao 已提交
4055

4056
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
4057

H
Haojun Liao 已提交
4058
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
4059 4060 4061
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
4062

H
Haojun Liao 已提交
4063
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
4064
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
4065 4066
  pQuery->stableQuery = isSTableQuery;
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);
H
Haojun Liao 已提交
4067
  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);
H
Haojun Liao 已提交
4068

sangshuduo's avatar
sangshuduo 已提交
4069
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
4070 4071

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
4072
  pRuntimeEnv->pTsBuf = pTsBuf;
4073
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4074
  setResultBufSize(pQuery, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4075

4076
  if (onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
4077
    pRuntimeEnv->resultInfo.capacity = 4096;
H
Haojun Liao 已提交
4078
    pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
4079 4080
  } else if (pQuery->queryBlockDist) {
    pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4081
  } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4082
    pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
4083
  } else if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
4084
    pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
4085
  } else {
H
Haojun Liao 已提交
4086
    pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
4087 4088
  }

H
Haojun Liao 已提交
4089
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4090 4091
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4092 4093
  }

4094
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
4095
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize);
4096

H
Haojun Liao 已提交
4097
  int32_t TENMB = 1024*1024*10;
H
Haojun Liao 已提交
4098
  code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo->qId);
H
Haojun Liao 已提交
4099 4100
  if (code != TSDB_CODE_SUCCESS) {
    return code;
4101 4102
  }

H
Haojun Liao 已提交
4103
  // create runtime environment
sangshuduo's avatar
sangshuduo 已提交
4104
  int32_t numOfTables = (int32_t)pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4105
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4106
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables);
H
Haojun Liao 已提交
4107 4108 4109 4110
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4111
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4112
  return TSDB_CODE_SUCCESS;
4113 4114
}

H
Haojun Liao 已提交
4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128
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 已提交
4129
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
4130 4131 4132 4133
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
H
Haojun Liao 已提交
4134
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4135
      .loadExternalRows = false,
4136 4137
  };

H
Haojun Liao 已提交
4138
  TIME_WINDOW_COPY(cond.twindow, *win);
4139 4140 4141
  return cond;
}

H
Haojun Liao 已提交
4142
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
4143
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
4144
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
4145 4146 4147

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
4148
  tidInfo.key = pTableQueryInfo->lastKey;
4149 4150 4151 4152

  return tidInfo;
}

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

H
Haojun Liao 已提交
4157 4158
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4159 4160 4161 4162 4163 4164 4165 4166
  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 已提交
4167 4168 4169 4170
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);
4171

H
Haojun Liao 已提交
4172 4173 4174 4175
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4176 4177
    }
  }
4178 4179
}

H
Haojun Liao 已提交
4180 4181 4182 4183
static SSDataBlock* doTableScanImpl(void* param) {
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4184
  SSDataBlock*     pBlock = &pTableScanInfo->block;
H
Haojun Liao 已提交
4185 4186
  SQuery*          pQuery = pOperator->pRuntimeEnv->pQuery;
  STableGroupInfo* pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4187

H
Haojun Liao 已提交
4188
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4189 4190 4191
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4192

4193
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4194
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4195

4196
    // todo opt
H
Haojun Liao 已提交
4197
    if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4198 4199
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4200 4201 4202 4203 4204 4205 4206 4207
      if (pTableQueryInfo == NULL) {
        break;
      }

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

H
Haojun Liao 已提交
4208
    // this function never returns error?
H
Haojun Liao 已提交
4209
    uint32_t status;
H
Haojun Liao 已提交
4210
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4211
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4212
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4213
    }
H
Haojun Liao 已提交
4214

H
Haojun Liao 已提交
4215
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4216
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4217
      continue;
H
Haojun Liao 已提交
4218 4219 4220 4221
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4222 4223

  return NULL;
H
Haojun Liao 已提交
4224 4225 4226
}

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

H
Haojun Liao 已提交
4229
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4230
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4231
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4232

H
Haojun Liao 已提交
4233 4234
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;

H
Haojun Liao 已提交
4235
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4236
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4237 4238
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4239 4240
    }

H
Haojun Liao 已提交
4241
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4242 4243 4244 4245 4246
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4247
    }
H
Haojun Liao 已提交
4248

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

H
Haojun Liao 已提交
4253
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4254
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4255

H
Haojun Liao 已提交
4256 4257 4258 4259 4260
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4261 4262 4263 4264
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4265

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

H
Haojun Liao 已提交
4270
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4271
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4272

H
Haojun Liao 已提交
4273
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4274
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4275

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

H
Haojun Liao 已提交
4279 4280
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4281 4282
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4283 4284
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4285

H
Haojun Liao 已提交
4286 4287 4288 4289
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4290

H
Haojun Liao 已提交
4291
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4292 4293
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4294 4295
    }
  }
H
Haojun Liao 已提交
4296

H
Haojun Liao 已提交
4297 4298 4299
  return NULL;
}

H
Haojun Liao 已提交
4300 4301
static SSDataBlock* doBlockInfoScan(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4302 4303 4304
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4305 4306 4307 4308

  STableScanInfo *pTableScanInfo = pOperator->info;

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

H
Haojun Liao 已提交
4312
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4313
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4314 4315 4316 4317 4318

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

H
Haojun Liao 已提交
4319 4320 4321 4322 4323 4324
  SBufferWriter bw = tbufInitWriter(NULL, false);
  blockDistInfoToBinary(&tableBlockDist, &bw);
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);

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

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

H
Haojun Liao 已提交
4329
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4330

H
Haojun Liao 已提交
4331 4332 4333 4334 4335
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
  pOperator->pRuntimeEnv->pQuery->current = taosArrayGetP(g, 0);

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

H
Haojun Liao 已提交
4338
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4339 4340
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4341 4342
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4343
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4344
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4345 4346
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->current      = 0;
H
Haojun Liao 已提交
4347

H
Haojun Liao 已提交
4348
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4349
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4350
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4351 4352
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4353
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4354
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4355
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4356 4357 4358 4359

  return pOperator;
}

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

H
Haojun Liao 已提交
4363 4364 4365 4366 4367
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
  pInfo->order            = pRuntimeEnv->pQuery->order.order;
  pInfo->current          = 0;
H
Haojun Liao 已提交
4368 4369

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4370 4371
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4372 4373 4374 4375
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4376 4377
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4378

H
Haojun Liao 已提交
4379 4380 4381
  return pOperator;
}

H
Haojun Liao 已提交
4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406
SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv) {
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));

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

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

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "TableBlockInfoScanOperator";
  pOperator->operatorType = OP_TableBlockInfoScan;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
  pOperator->exec         = doBlockInfoScan;

  return pOperator;
}

H
Haojun Liao 已提交
4407 4408 4409
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4410 4411 4412
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4413
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4414
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4415

H
Haojun Liao 已提交
4416 4417 4418
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
4419
  } else if (pDownstream->operatorType == OP_TimeWindow) {
H
Haojun Liao 已提交
4420
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4421 4422 4423

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

H
Haojun Liao 已提交
4426
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4427
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4428

H
Haojun Liao 已提交
4429 4430 4431
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4432

H
Haojun Liao 已提交
4433
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4434
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4435

4436 4437
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4438 4439
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4440
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4441
    SArithOperatorInfo *pInfo = pDownstream->info;
4442

4443 4444 4445 4446 4447 4448
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
  } else if (pDownstream->operatorType == OP_SessionWindow) {
    SSWindowOperatorInfo* pInfo = pDownstream->info;

H
Haojun Liao 已提交
4449 4450 4451
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4452 4453 4454
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4455 4456
}

H
Haojun Liao 已提交
4457
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4458 4459 4460 4461
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4462
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4463
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4464 4465
  pInfo->current      = 0;
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
H
Haojun Liao 已提交
4466 4467

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4468 4469
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4470
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4471 4472 4473
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4474 4475

  return pOptr;
H
Haojun Liao 已提交
4476 4477
}

H
Haojun Liao 已提交
4478
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4479 4480 4481
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4482
// this is a blocking operator
H
Haojun Liao 已提交
4483
static SSDataBlock* doAggregate(void* param) {
H
Haojun Liao 已提交
4484
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4485
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4486 4487
    return NULL;
  }
H
Haojun Liao 已提交
4488

H
Haojun Liao 已提交
4489
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4490 4491
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4492
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4493

H
Haojun Liao 已提交
4494
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4495
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
4496

H
Haojun Liao 已提交
4497
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4498

H
Haojun Liao 已提交
4499
  while(1) {
H
Haojun Liao 已提交
4500
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4501 4502 4503 4504
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4505
    setTagValue(pOperator, pQuery->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
4506

H
Haojun Liao 已提交
4507
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4508
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4509 4510 4511
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4512
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4513 4514
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4515 4516
  }

H
Haojun Liao 已提交
4517
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4518
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4519

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

H
Haojun Liao 已提交
4523
  return pInfo->pRes;
H
Haojun Liao 已提交
4524 4525
}

H
Haojun Liao 已提交
4526
static SSDataBlock* doSTableAggregate(void* param) {
H
Haojun Liao 已提交
4527
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4528
  if (pOperator->status == OP_EXEC_DONE) {
4529 4530
    return NULL;
  }
H
Haojun Liao 已提交
4531

H
Haojun Liao 已提交
4532
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4533 4534
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4535
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4536

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

H
Haojun Liao 已提交
4540 4541
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4542 4543
    }

H
Haojun Liao 已提交
4544
    return pInfo->pRes;
4545
  }
H
Haojun Liao 已提交
4546

H
Haojun Liao 已提交
4547
  SQuery* pQuery = pRuntimeEnv->pQuery;
4548 4549 4550 4551 4552 4553 4554 4555 4556 4557
  int32_t order = pQuery->order.order;

  SOperatorInfo* upstream = pOperator->upstream;

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

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

H
Haojun Liao 已提交
4560
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4561
      STableScanInfo* pScanInfo = upstream->info;
4562 4563 4564 4565
      order = getTableScanOrder(pScanInfo);
    }

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

4568 4569
    TSKEY key = QUERY_IS_ASC_QUERY(pQuery)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
    setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pQuery->current->groupIndex, key);
H
Haojun Liao 已提交
4570
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
4571
  }
H
Haojun Liao 已提交
4572

H
Haojun Liao 已提交
4573 4574
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4575

H
Haojun Liao 已提交
4576
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4577
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4578

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

H
Haojun Liao 已提交
4581 4582 4583
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4584 4585
  }

H
Haojun Liao 已提交
4586
  return pInfo->pRes;
4587 4588 4589 4590 4591
}

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

H
Haojun Liao 已提交
4592 4593
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4594
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4595

H
Haojun Liao 已提交
4596 4597 4598 4599
  SSDataBlock* pRes = pInfo->pRes;
  int32_t order = pRuntimeEnv->pQuery->order.order;

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

H
Haojun Liao 已提交
4601
  while(1) {
H
Haojun Liao 已提交
4602
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4603
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4604
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4605
      break;
H
Haojun Liao 已提交
4606 4607
    }

H
Haojun Liao 已提交
4608 4609 4610 4611
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current;

    // todo dynamic set tags
    setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4612

H
Haojun Liao 已提交
4613
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4614
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
4615 4616
    updateOutputBuf(pArithInfo, pBlock->info.rows);

H
Haojun Liao 已提交
4617 4618
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
H
Haojun Liao 已提交
4619

H
Haojun Liao 已提交
4620 4621
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4622 4623 4624 4625
      break;
    }
  }

H
Haojun Liao 已提交
4626
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4627
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4628 4629 4630 4631
}

static SSDataBlock* doLimit(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4632
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4633
    return NULL;
H
Haojun Liao 已提交
4634 4635
  }

H
Haojun Liao 已提交
4636
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4637

H
Haojun Liao 已提交
4638
  SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4639
  if (pBlock == NULL) {
H
Haojun Liao 已提交
4640
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4641
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4642 4643 4644 4645
    return NULL;
  }

  if (pInfo->total + pBlock->info.rows >= pInfo->limit) {
sangshuduo's avatar
sangshuduo 已提交
4646
    pBlock->info.rows = (int32_t) (pInfo->limit - pInfo->total);
H
Haojun Liao 已提交
4647

H
Haojun Liao 已提交
4648 4649
    pInfo->total = pInfo->limit;

H
Haojun Liao 已提交
4650
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4651
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4652 4653
  } else {
    pInfo->total += pBlock->info.rows;
H
Haojun Liao 已提交
4654 4655 4656 4657 4658
  }

  return pBlock;
}

H
Haojun Liao 已提交
4659
// TODO add log
H
Haojun Liao 已提交
4660 4661
static SSDataBlock* doOffset(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
H
Haojun Liao 已提交
4662
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4663 4664
    return NULL;
  }
H
Haojun Liao 已提交
4665

H
Haojun Liao 已提交
4666
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4667 4668

  while (1) {
H
Haojun Liao 已提交
4669
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4670
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4671
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4672
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4673 4674 4675
      return NULL;
    }

H
Haojun Liao 已提交
4676
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4677
      return pBlock;
4678
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4679
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4680
    } else {
sangshuduo's avatar
sangshuduo 已提交
4681
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4682 4683 4684 4685 4686 4687
      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 已提交
4688
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4689 4690
      }

H
Haojun Liao 已提交
4691
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4692 4693 4694 4695 4696
      return pBlock;
    }
  }
}

D
dapan1121 已提交
4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747

bool doFilterData(SColumnInfoData* p, int32_t rid, SColumnFilterElem *filterElem, __filter_func_t fp) {
  char* input = p->pData + p->info.bytes * rid;
  bool isnull = isNull(input, p->info.type);
  if (isnull) {
    return (fp == isNullOperator) ? true : false;
  } else {
    if (fp == notNullOperator) {
      return true;
    } else if (fp == isNullOperator) {
      return false;
    }
  }
  
  if (fp(filterElem, input, input, p->info.type)) {
    return true;
  }

  return false;
}


void doHavingImpl(SOperatorInfo *pOperator, SSDataBlock *pBlock) {
  SHavingOperatorInfo* pInfo = pOperator->info;
  int32_t f = 0;
  int32_t allQualified = 1;
  int32_t exprQualified = 0;
  
  for (int32_t r = 0; r < pBlock->info.rows; ++r) {
    allQualified = 1;
    
    for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
      SExprInfo* pExprInfo = &(pOperator->pExpr[i]);
      if (pExprInfo->pFilter == NULL) {
        continue;
      }
      
      SArray* es = taosArrayGetP(pInfo->fp, i);
      assert(es);

      size_t fpNum = taosArrayGetSize(es);
      
      exprQualified = 0;
      for (int32_t m = 0; m < fpNum; ++m) {
        __filter_func_t fp = taosArrayGetP(es, m);

        assert(fp);
      
        //SColIndex* colIdx = &pExprInfo->base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, i);

D
dapan1121 已提交
4748
        SColumnFilterElem filterElem = {.filterInfo = pExprInfo->pFilter[m]};
D
dapan1121 已提交
4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801
        
        if (doFilterData(p, r, &filterElem, fp)) {
          exprQualified = 1;
          break;
        }
      }

      if (exprQualified == 0) {
        allQualified = 0;
        break;
      }
    }

    if (allQualified == 0) {
      continue;
    }
    
    for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
      SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
    
      int16_t bytes = pColInfoData->info.bytes;
      memmove(pColInfoData->pData + f * bytes, pColInfoData->pData + bytes * r, bytes);
    }

    ++f;
  }
  
  pBlock->info.rows = f;
}

static SSDataBlock* doHaving(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

  while (1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
      pOperator->status = OP_EXEC_DONE;
      return NULL;
    }
    
    doHavingImpl(pOperator, pBlock);

    return pBlock;
  }
}


H
Haojun Liao 已提交
4802
static SSDataBlock* doIntervalAgg(void* param) {
H
Haojun Liao 已提交
4803
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4804
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4805 4806 4807
    return NULL;
  }

H
Haojun Liao 已提交
4808
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4809

H
Haojun Liao 已提交
4810
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4811
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4812 4813
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4814
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4815
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4816 4817 4818 4819
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4822
  int32_t order = pQuery->order.order;
4823
  STimeWindow win = pQuery->window;
H
Haojun Liao 已提交
4824

H
Haojun Liao 已提交
4825
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4826 4827 4828 4829 4830 4831 4832 4833

  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 已提交
4834
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
H
Haojun Liao 已提交
4835
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4836 4837
  }

4838 4839 4840 4841
  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

H
Haojun Liao 已提交
4842
  pOperator->status = OP_RES_TO_RETURN;
4843
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4844
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4845
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4846

H
Haojun Liao 已提交
4847
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4848
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4849

H
Haojun Liao 已提交
4850
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4851
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4852 4853
  }

H
Haojun Liao 已提交
4854
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4855 4856
}

H
Haojun Liao 已提交
4857
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
4858
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4859
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4860 4861 4862
    return NULL;
  }

H
Haojun Liao 已提交
4863
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4864
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4865

H
Haojun Liao 已提交
4866
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4867
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4868
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4869
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4870 4871 4872 4873 4874
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
4875 4876 4877
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
4878
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4879 4880

  while(1) {
H
Haojun Liao 已提交
4881
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4882
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4883
      break;
H
Haojun Liao 已提交
4884 4885
    }

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

H
Haojun Liao 已提交
4889
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4890
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
4891
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
4892

H
Haojun Liao 已提交
4893
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
4894
  }
H
Haojun Liao 已提交
4895

H
Haojun Liao 已提交
4896
  pOperator->status = OP_RES_TO_RETURN;
4897 4898
  pQuery->order.order = order;   // TODO : restore the order
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
4899
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4900

H
Haojun Liao 已提交
4901
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4902
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4903
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4904 4905 4906 4907
  }

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

4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964
static SSDataBlock* doSessionWindowAgg(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SSWindowOperatorInfo* pWindowInfo = pOperator->info;
  SOptrBasicInfo* pBInfo = &pWindowInfo->binfo;

  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  if (pOperator->status == OP_RES_TO_RETURN) {
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pBInfo->pRes);

    if (pBInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
    }

    return pBInfo->pRes;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;
  STimeWindow win = pQuery->window;

  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
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQuery->order.order);
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pBInfo->resultRowInfo);
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  finalizeQueryResult(pOperator, pBInfo->pCtx, &pBInfo->resultRowInfo, pBInfo->rowCellInfoOffset);

  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pBInfo->resultRowInfo);
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pBInfo->pRes);

  if (pBInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
  }

  return pBInfo->pRes->info.rows == 0? NULL:pBInfo->pRes;
}

H
Haojun Liao 已提交
4965
static SSDataBlock* hashGroupbyAggregate(void* param) {
H
Haojun Liao 已提交
4966
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4967
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4968 4969 4970
    return NULL;
  }

H
Haojun Liao 已提交
4971
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
4972

H
Haojun Liao 已提交
4973
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4974
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4975
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4976 4977

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

H
Haojun Liao 已提交
4981
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992
  }

  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 已提交
4993
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
H
Haojun Liao 已提交
4994
    setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4995
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
4996
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
4997 4998
    }

H
Haojun Liao 已提交
4999
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5000 5001
  }

H
Haojun Liao 已提交
5002
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5003
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5004
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5005

H
Haojun Liao 已提交
5006
  if (!pRuntimeEnv->pQuery->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5007 5008 5009
    finalizeQueryResult(pOperator, pInfo->binfo.pCtx, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
  } else {
    updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, &pInfo->binfo.resultRowInfo, pInfo->binfo.rowCellInfoOffset);
5010 5011
  }

H
Haojun Liao 已提交
5012
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5013
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5014

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

H
Haojun Liao 已提交
5019
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5020 5021
}

H
Haojun Liao 已提交
5022 5023
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5024
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5025 5026 5027
    return NULL;
  }

H
Haojun Liao 已提交
5028 5029
  SFillOperatorInfo *pInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5030

H
Haojun Liao 已提交
5031
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
sangshuduo's avatar
sangshuduo 已提交
5032
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5033 5034 5035 5036 5037 5038
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5039
      if (pInfo->totalInputRows == 0) {
H
Haojun Liao 已提交
5040
        pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5041 5042 5043
        return NULL;
      }

H
Haojun Liao 已提交
5044
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
H
Haojun Liao 已提交
5045
    } else {
H
Haojun Liao 已提交
5046 5047
      pInfo->totalInputRows += pBlock->info.rows;

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

H
Haojun Liao 已提交
5050 5051
      taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
H
Haojun Liao 已提交
5052 5053
    }

H
Haojun Liao 已提交
5054
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5055
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
5056 5057
  }
}
H
Haojun Liao 已提交
5058

H
Haojun Liao 已提交
5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070
// 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 已提交
5071 5072 5073 5074 5075
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5076
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5077
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5078 5079
  }

H
Haojun Liao 已提交
5080
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5081
  tfree(pOperator->info);
H
Haojun Liao 已提交
5082 5083 5084
  tfree(pOperator);
}

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

H
Haojun Liao 已提交
5088 5089 5090 5091
  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 已提交
5092
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5093

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

H
Haojun Liao 已提交
5096
  pInfo->seed = rand();
H
Haojun Liao 已提交
5097
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed);
H
Haojun Liao 已提交
5098

H
Haojun Liao 已提交
5099
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5100
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5101
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5102
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5103
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5104
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5105
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5106 5107 5108
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5109

H
Haojun Liao 已提交
5110 5111
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5112 5113 5114
  return pOperator;
}

H
Haojun Liao 已提交
5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131
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 已提交
5132
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5133 5134 5135 5136
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5137
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5138
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5139
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5140 5141 5142 5143 5144 5145 5146
}

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

H
Haojun Liao 已提交
5147 5148 5149 5150 5151
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

D
dapan1121 已提交
5152 5153 5154 5155 5156 5157 5158
static void destroyHavingOperatorInfo(void* param, int32_t numOfOutput) {
  SHavingOperatorInfo* pInfo = (SHavingOperatorInfo*) param;
  if (pInfo->fp) {
    taosArrayDestroy(pInfo->fp);
  }
}

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

H
Haojun Liao 已提交
5162
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5163

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

5168
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5169 5170
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5171
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5172
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5173
  pOperator->info         = pInfo;
5174
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5175 5176 5177
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5178

H
Haojun Liao 已提交
5179 5180 5181
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5182
  return pOperator;
H
Haojun Liao 已提交
5183 5184
}

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

H
Haojun Liao 已提交
5188
  pInfo->seed = rand();
H
Haojun Liao 已提交
5189
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5190

H
Haojun Liao 已提交
5191
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5192
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5193 5194 5195
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5196
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed);
H
Haojun Liao 已提交
5197 5198

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5199 5200
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5201
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5202
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5203
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5204
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5205 5206 5207
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5208

H
Haojun Liao 已提交
5209 5210 5211
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5212 5213 5214
  return pOperator;
}

D
dapan1121 已提交
5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243

int32_t initFilterFp(SExprInfo* pExpr, int32_t numOfOutput, SArray** fps) {
  __filter_func_t fp = NULL;

  *fps = taosArrayInit(numOfOutput, sizeof(SArray*));
  if (*fps == NULL) {
    return TSDB_CODE_TSC_OUT_OF_MEMORY;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &(pExpr[i]);
    SColIndex* colIdx = &pExprInfo->base.colInfo;

    if (pExprInfo->pFilter == NULL || !TSDB_COL_IS_NORMAL_COL(colIdx->flag)) {
      taosArrayPush(*fps, &fp);
      
      continue;
    }

    int32_t filterNum = pExprInfo->base.filterNum;
    SColumnFilterInfo *filterInfo = pExprInfo->pFilter;

    SArray* es = taosArrayInit(filterNum, sizeof(__filter_func_t));

    for (int32_t j = 0; j < filterNum; ++j) {      
      int32_t lower = filterInfo->lowerRelOptr;
      int32_t upper = filterInfo->upperRelOptr;
      if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
        qError("invalid rel optr");
D
dapan1121 已提交
5244
        taosArrayDestroy(es);
D
dapan1121 已提交
5245 5246 5247 5248 5249 5250
        return TSDB_CODE_QRY_APP_ERROR;
      }

      __filter_func_t ffp = getFilterOperator(lower, upper);
      if (ffp == NULL) {
        qError("invalid filter info");
D
dapan1121 已提交
5251
        taosArrayDestroy(es);
D
dapan1121 已提交
5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291
        return TSDB_CODE_QRY_APP_ERROR;
      }
      
      taosArrayPush(es, &ffp);
      
      filterInfo += 1;
    }

    taosArrayPush(*fps, &es);
  }

  return TSDB_CODE_SUCCESS;
}

SOperatorInfo* createHavingOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
  SHavingOperatorInfo* pInfo = calloc(1, sizeof(SHavingOperatorInfo));

  initFilterFp(pExpr, numOfOutput, &pInfo->fp);

  assert(pInfo->fp);
  
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "HavingOperator";
  pOperator->operatorType = OP_Having;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
  pOperator->exec         = doHaving;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->cleanup      = destroyHavingOperatorInfo;

  return pOperator;
}



H
Haojun Liao 已提交
5292
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5293 5294 5295 5296 5297
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;

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

H
Haojun Liao 已提交
5298 5299
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5300
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5301
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5302
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5303
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5304 5305
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5306 5307 5308 5309

  return pOperator;
}

H
Haojun Liao 已提交
5310
SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5311 5312 5313 5314 5315
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

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

H
Haojun Liao 已提交
5316 5317
  pOperator->name         = "OffsetOperator";
  pOperator->operatorType = OP_Offset;
H
Haojun Liao 已提交
5318
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5319
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5320
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5321
  pOperator->exec         = doOffset;
H
Haojun Liao 已提交
5322 5323
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5324 5325 5326 5327

  return pOperator;
}

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

H
Haojun Liao 已提交
5331
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5332
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5333
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5334 5335 5336

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

H
Haojun Liao 已提交
5337
  pOperator->name         = "TimeIntervalAggOperator";
5338
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5339
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5340
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5341
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5342 5343 5344 5345
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5346
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5347 5348
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5349 5350 5351
  return pOperator;
}

5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376
SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
  SSWindowOperatorInfo* pInfo = calloc(1, sizeof(SSWindowOperatorInfo));

  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  pInfo->prevTs = INT64_MIN;
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "SessionWindowAggOperator";
  pOperator->operatorType = OP_SessionWindow;
  pOperator->blockingOptr = true;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doSessionWindowAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

  return pOperator;
}

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

H
Haojun Liao 已提交
5380
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5381
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5382
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5383 5384

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5385 5386
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5387
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5388
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5389
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5390 5391
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5392 5393
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5394

H
Haojun Liao 已提交
5395 5396 5397
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5398 5399 5400
  return pOperator;
}

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

H
Haojun Liao 已提交
5405
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5406
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5407
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5408 5409

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5410
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5411
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5412 5413
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5414
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5415 5416 5417 5418
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5419
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5420 5421
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5422 5423
  return pOperator;
}
H
Haojun Liao 已提交
5424

H
Haojun Liao 已提交
5425
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5426
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5427
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442
  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 已提交
5443 5444 5445

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

H
Haojun Liao 已提交
5446
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5447
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5448 5449 5450
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5451
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5452 5453 5454 5455
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5456

H
Haojun Liao 已提交
5457 5458 5459
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5460 5461 5462
  return pOperator;
}

5463 5464
static SSDataBlock* doTagScan(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5465
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5466 5467
    return NULL;
  }
5468

H
Haojun Liao 已提交
5469
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5470

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

H
Haojun Liao 已提交
5473 5474
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
5475 5476

  int32_t count = 0;
H
Haojun Liao 已提交
5477 5478 5479 5480 5481
  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;
5482 5483 5484 5485
    assert(pQuery->numOfOutput == 1);

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
    int32_t rsize = pExprInfo->bytes;
H
Haojun Liao 已提交
5486

5487 5488 5489
    count = 0;

    int16_t bytes = pExprInfo->bytes;
H
Haojun Liao 已提交
5490
    int16_t type  = pExprInfo->type;
5491 5492 5493 5494 5495 5496 5497 5498 5499

    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 已提交
5500 5501 5502 5503
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5506
      char *output = pColInfo->pData + count * rsize;
5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523
      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 已提交
5524
      char* data = NULL;
5525
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5526
        data = tsdbGetTableName(item->pTable);
5527
      } else {
H
Haojun Liao 已提交
5528
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5529 5530
      }

H
Haojun Liao 已提交
5531
      doSetTagValueToResultBuf(output, data, type, bytes);
5532 5533 5534
      count += 1;
    }

H
Haojun Liao 已提交
5535
    qDebug("QInfo:%"PRIu64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5536 5537 5538
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5539
    count = 1;
H
Haojun Liao 已提交
5540 5541

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

H
Haojun Liao 已提交
5546 5547 5548
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559

      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 已提交
5560
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5561 5562
        type  = pExprInfo[j].type;
        bytes = pExprInfo[j].bytes;
5563 5564 5565 5566 5567 5568 5569

        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 已提交
5570
        dst  = pColInfo->pData + count * pExprInfo[j].bytes;
5571 5572
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5573

5574 5575 5576
      count += 1;
    }

H
Haojun Liao 已提交
5577 5578 5579 5580
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

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

H
Haojun Liao 已提交
5584
  pRes->info.rows = count;
H
Haojun Liao 已提交
5585
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5586 5587
}

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

H
Haojun Liao 已提交
5592 5593 5594 5595 5596 5597
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5598
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5599
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5600
  pOperator->operatorType = OP_TagScan;
5601
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5602
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5603 5604
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5605 5606
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5607
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5608
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5609

5610 5611
  return pOperator;
}
H
Haojun Liao 已提交
5612

5613
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
5614
  int32_t j = 0;
5615

5616
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
5617
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5618
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
5619 5620
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5621
    }
Y
yihaoDeng 已提交
5622
    
H
Haojun Liao 已提交
5623

5624 5625 5626 5627
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
5628

5629 5630
      j += 1;
    }
5631

Y
TD-1230  
yihaoDeng 已提交
5632
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5633
    return TSDB_UD_COLUMN_INDEX;
5634 5635 5636 5637 5638
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
5639

5640
      j += 1;
5641 5642
    }
  }
5643 5644

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5645 5646
}

5647 5648
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
5649
  return j != INT32_MIN;
5650 5651
}

5652
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5653 5654
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5655
    return false;
5656 5657
  }

5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668
  if (pQueryMsg->sw.gap < 0 || pQueryMsg->sw.primaryColId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
    qError("qmsg:%p illegal value of session window time %" PRId64, pQueryMsg, pQueryMsg->sw.gap);
    return false;
  }

  if (pQueryMsg->sw.gap > 0 && pQueryMsg->interval.interval > 0) {
    qError("qmsg:%p illegal value of session window time %" PRId64" and interval value %"PRId64, pQueryMsg,
        pQueryMsg->sw.gap, pQueryMsg->interval.interval);
    return false;
  }

H
hjxilinx 已提交
5669
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5670
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5671
    return false;
5672 5673
  }

H
hjxilinx 已提交
5674
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5675
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5676
    return false;
5677 5678
  }

5679 5680
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5681
    return false;
5682 5683
  }

5684 5685 5686
  return true;
}

5687
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5688 5689 5690 5691
  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;
5692 5693 5694
  }

  if (numOfTotal == 0) {
5695
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
5696 5697 5698 5699
      SSqlFuncMsg* pFuncMsg = pExprMsg[i];

      if ((pFuncMsg->functionId == TSDB_FUNC_TAGPRJ) ||
          (pFuncMsg->functionId == TSDB_FUNC_TID_TAG && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
H
Haojun Liao 已提交
5700 5701
          (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (pFuncMsg->functionId == TSDB_FUNC_BLKINFO)) {
5702
        continue;
5703
      }
5704

5705
      return false;
5706 5707
    }
  }
5708

5709 5710 5711 5712 5713 5714
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5715
  return true;
5716 5717
}

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

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

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

5726
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5727 5728
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5729

H
hjxilinx 已提交
5730 5731 5732
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5733

H
hjxilinx 已提交
5734 5735
  return pMsg;
}
5736

5737
/**
H
hjxilinx 已提交
5738
 * pQueryMsg->head has been converted before this function is called.
5739
 *
H
hjxilinx 已提交
5740
 * @param pQueryMsg
5741 5742 5743 5744
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5745
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5746 5747
  int32_t code = TSDB_CODE_SUCCESS;

5748 5749 5750 5751
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5752 5753 5754 5755
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5756 5757 5758
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5759 5760
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5761
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5762

5763 5764
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5765
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5766
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5767 5768

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5769
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5770
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5771 5772 5773
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
5774
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
5775
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
5776
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5777
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5778
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5779
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5780
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5781 5782
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
5783

5784
  // query msg safety check
5785
  if (!validateQueryMsg(pQueryMsg)) {
5786 5787
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5788 5789
  }

H
hjxilinx 已提交
5790 5791
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
5792 5793
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
5794
    pColInfo->colId = htons(pColInfo->colId);
5795
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
5796 5797
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
5798

5799 5800 5801 5802 5803
    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;
    }
5804

H
hjxilinx 已提交
5805
    int32_t numOfFilters = pColInfo->numOfFilters;
5806
    if (numOfFilters > 0) {
H
hjxilinx 已提交
5807
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
5808 5809 5810 5811
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
5812 5813 5814
    }

    for (int32_t f = 0; f < numOfFilters; ++f) {
5815
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pMsg;
5816

5817 5818
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
5819 5820 5821

      pMsg += sizeof(SColumnFilterInfo);

5822 5823
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
5824

5825
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
5826 5827 5828 5829 5830
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

5831
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
5832
        pMsg += (pColFilter->len + 1);
5833
      } else {
5834 5835
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
5836 5837
      }

5838 5839
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
5840 5841 5842
    }
  }

5843 5844
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
5845 5846 5847 5848
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

5849
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
5850

5851
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5852
    param->pExprMsg[i] = pExprMsg;
5853

5854
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
5855
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5856
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5857 5858 5859
    pExprMsg->colType       = htons(pExprMsg->colType);
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5860 5861 5862
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
D
dapan1121 已提交
5863
    pExprMsg->filterNum     = htonl(pExprMsg->filterNum);
5864

5865
    pMsg += sizeof(SSqlFuncMsg);
5866

D
dapan1121 已提交
5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891
    SColumnFilterInfo* pExprFilterInfo = pExprMsg->filterInfo;

    pMsg += sizeof(SColumnFilterInfo) * pExprMsg->filterNum;

    for (int32_t f = 0; f < pExprMsg->filterNum; ++f) {
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pExprFilterInfo;

      pFilterMsg->filterstr = htons(pFilterMsg->filterstr);

      if (pFilterMsg->filterstr) {
        pFilterMsg->len = htobe64(pFilterMsg->len);

        pFilterMsg->pz = (int64_t)pMsg;
        pMsg += (pFilterMsg->len + 1);
      } else {
        pFilterMsg->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pFilterMsg->upperBndi = htobe64(pFilterMsg->upperBndi);
      }

      pFilterMsg->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pFilterMsg->upperRelOptr = htons(pFilterMsg->upperRelOptr);

      pExprFilterInfo++;
    }

5892
    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
5893
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
5894 5895 5896 5897
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
5898
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
5899 5900 5901 5902 5903
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
5904 5905
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
5906
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
5907 5908
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
5909 5910 5911
      }
    }

5912
    pExprMsg = (SSqlFuncMsg *)pMsg;
5913
  }
5914

H
Haojun Liao 已提交
5915 5916
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
5917
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
5918

H
Haojun Liao 已提交
5919
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
5920
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
5921 5922 5923

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5924
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5925 5926 5927
      pExprMsg->colType       = htons(pExprMsg->colType);
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956
      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;
    }
  }

5957
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
5958

H
hjxilinx 已提交
5959
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
5960 5961
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
5962 5963 5964
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5965 5966

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

5970 5971
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
5972

5973 5974
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
5975

5976 5977
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
5978
    }
5979

H
hjxilinx 已提交
5980 5981
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
5982 5983
  }

5984 5985
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
5986
    pQueryMsg->fillVal = (uint64_t)(pMsg);
5987 5988

    int64_t *v = (int64_t *)pMsg;
5989
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5990 5991
      v[i] = htobe64(v[i]);
    }
5992

5993
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
5994
  }
5995

5996
  if (pQueryMsg->numOfTags > 0) {
5997 5998
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
5999 6000 6001 6002
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6003 6004
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6005

6006 6007 6008 6009
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
6010

6011
      param->pTagColumnInfo[i] = *pTagCol;
6012
      pMsg += sizeof(SColumnInfo);
6013
    }
H
hjxilinx 已提交
6014
  }
6015

6016 6017
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6018 6019
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6020 6021 6022
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6023 6024

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6025 6026
    pMsg += pQueryMsg->tagCondLen;
  }
6027

6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038
  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 已提交
6039
  if (pQueryMsg->tbnameCondLen > 0) {
6040 6041
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6042 6043 6044 6045
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6046
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6047
    pMsg += pQueryMsg->tbnameCondLen;
6048 6049
  }

D
dapan1121 已提交
6050 6051 6052 6053 6054
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

6055
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6056

6057
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
6058 6059
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6060
  }
6061

6062
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6063 6064
         "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,
6065
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6066
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6067

6068
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6069
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6070 6071

_cleanup:
6072
  freeParam(param);
6073
  return code;
6074 6075
}

D
dapan1121 已提交
6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088
int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
  if (filterNum <= 0) {
    return TSDB_CODE_SUCCESS;
  }

  *dst = calloc(filterNum, sizeof(*src));
  if (*dst == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  memcpy(*dst, src, sizeof(*src) * filterNum);
  
  for (int32_t i = 0; i < filterNum; i++) {
D
dapan1121 已提交
6089
    if ((*dst)[i].filterstr && dst[i]->len > 0) {
D
dapan1121 已提交
6090
      void *pz = calloc(1, (size_t)(*dst)[i].len + 1); 
D
dapan1121 已提交
6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101
    
      if (pz == NULL) {
        if (i == 0) {
          free(*dst);
        } else {
          freeColumnFilterInfo(*dst, i);
        }

        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }

D
dapan1121 已提交
6102
      memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6103

D
dapan1121 已提交
6104
      (*dst)[i].pz = (int64_t)pz;
D
dapan1121 已提交
6105 6106 6107 6108 6109 6110 6111
    }
  }

  return TSDB_CODE_SUCCESS;
}


H
Haojun Liao 已提交
6112 6113
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6114 6115

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6116
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
6117 6118 6119
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
6120
    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 已提交
6121 6122 6123
    return code;
  } END_TRY

H
hjxilinx 已提交
6124
  if (pExprNode == NULL) {
6125
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
6126
    return TSDB_CODE_QRY_APP_ERROR;
6127
  }
6128

6129
  pArithExprInfo->pExpr = pExprNode;
6130 6131 6132
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6133
static int32_t updateOutputBufForTopBotQuery(SQueryTableMsg* pQueryMsg, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152
  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;
}

H
Haojun Liao 已提交
6153
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6154 6155
int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                   SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
6156
  *pExprInfo = NULL;
H
hjxilinx 已提交
6157
  int32_t code = TSDB_CODE_SUCCESS;
6158

H
Haojun Liao 已提交
6159
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
6160
  if (pExprs == NULL) {
6161
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6162 6163 6164 6165 6166
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6167
  for (int32_t i = 0; i < numOfOutput; ++i) {
6168
    pExprs[i].base = *pExprMsg[i];
6169
    pExprs[i].bytes = 0;
6170 6171 6172 6173

    int16_t type = 0;
    int16_t bytes = 0;

6174
    // parse the arithmetic expression
6175
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6176
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
6177

6178
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6179
        tfree(pExprs);
6180
        return code;
6181 6182
      }

6183
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6184
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6185
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6186 6187 6188
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6189 6190 6191 6192
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
6193 6194
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6195 6196
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

6197 6198
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
6199 6200 6201 6202 6203

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
6204
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
6205
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
6206
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
6207 6208 6209 6210 6211 6212 6213
          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 已提交
6214

dengyihao's avatar
dengyihao 已提交
6215
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6216 6217 6218 6219
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6220
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6221

6222 6223
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6224
      }
D
dapan1121 已提交
6225 6226 6227 6228 6229 6230 6231

      if (pExprs[i].base.filterNum > 0) {
        int32_t ret = cloneExprFilterInfo(&pExprs[i].pFilter, pExprMsg[i]->filterInfo, pExprMsg[i]->filterNum);
        if (ret) {
          return ret;
        }
      }
6232 6233
    }

S
TD-1057  
Shengliang Guan 已提交
6234
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
H
Haojun Liao 已提交
6235 6236
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6237 6238 6239 6240
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

6241
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
6242
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6243
      tfree(pExprs);
6244
      return TSDB_CODE_QRY_INVALID_MSG;
6245 6246
    }

6247
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
6248
      tagLen += pExprs[i].bytes;
6249
    }
6250

6251
    assert(isValidDataType(pExprs[i].type));
6252 6253
  }

H
Haojun Liao 已提交
6254 6255
  // the tag length is affected by other tag columns, so this should be update.
  updateOutputBufForTopBotQuery(pQueryMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6256

6257
  *pExprInfo = pExprs;
6258 6259 6260
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6261 6262 6263 6264 6265 6266 6267 6268 6269 6270
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 已提交
6271
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294

  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 已提交
6295 6296
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312
    }

    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 已提交
6313
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6314 6315 6316 6317 6318
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6319
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6320
  if (pGroupbyExpr == NULL) {
6321
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6322 6323 6324 6325 6326 6327 6328
    return NULL;
  }

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

6329 6330 6331 6332
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6333

6334 6335 6336
  return pGroupbyExpr;
}

H
Haojun Liao 已提交
6337
static int32_t createFilterInfo(SQuery *pQuery, uint64_t qId) {
6338
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
6339
    if (pQuery->colList[i].numOfFilters > 0) {
6340 6341 6342 6343 6344 6345 6346 6347 6348
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
6349 6350 6351
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6352 6353

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
6354
    if (pQuery->colList[i].numOfFilters > 0) {
6355 6356
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
6357
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
6358
      pFilterInfo->info = pQuery->colList[i];
6359

6360
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
6361
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
6362 6363 6364
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6365 6366 6367

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
6368
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
6369 6370 6371 6372

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
H
Haojun Liao 已提交
6373
          qError("QInfo:%"PRIu64" invalid filter info", qId);
6374
          return TSDB_CODE_QRY_INVALID_MSG;
6375 6376
        }

6377 6378
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
H
Haojun Liao 已提交
6379
          qError("QInfo:%"PRIu64" invalid filter info", qId);
6380
          return TSDB_CODE_QRY_INVALID_MSG;
6381 6382
        }

6383
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
6384 6385 6386 6387 6388 6389 6390 6391 6392
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6393
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
6394
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
6395

6396
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
6397
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
6398
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6399 6400
      continue;
    }
6401

6402
    // todo opt performance
H
Haojun Liao 已提交
6403
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6404
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6405 6406
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
6407 6408
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
6409 6410 6411
          break;
        }
      }
H
Haojun Liao 已提交
6412 6413

      assert(f < pQuery->numOfCols);
6414 6415
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6416 6417 6418
    } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      pColIndex->colIndex = 0;// only one source column, so it must be 0;
      assert(pQuery->numOfOutput == 1);
6419
    } else {
6420 6421
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
6422 6423
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
6424 6425
          break;
        }
6426
      }
6427

Y
yihaoDeng 已提交
6428
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6429 6430 6431 6432
    }
  }
}

H
Haojun Liao 已提交
6433 6434 6435 6436 6437 6438 6439 6440
void setResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo) {
  const int32_t DEFAULT_RESULT_MSG_SIZE = 1024 * (1024 + 512);

  // the minimum number of rows for projection query
  const int32_t MIN_ROWS_FOR_PRJ_QUERY = 8192;
  const int32_t DEFAULT_MIN_ROWS = 4096;

  const float THRESHOLD_RATIO = 0.85f;
H
Haojun Liao 已提交
6441

6442
  if (isProjQuery(pQuery)) {
H
Haojun Liao 已提交
6443 6444 6445
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQuery->resultRowSize;
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6446
    }
H
Haojun Liao 已提交
6447

H
Haojun Liao 已提交
6448
    pResultInfo->capacity  = numOfRes;
6449
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6450
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6451
  }
H
Haojun Liao 已提交
6452 6453 6454

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

D
fix bug  
dapan1121 已提交
6457 6458 6459 6460
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6461 6462
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery,
D
dapan1121 已提交
6463
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6464 6465 6466
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6467 6468
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6469
    goto _cleanup_qinfo;
6470
  }
6471

D
dapan1121 已提交
6472 6473
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6474 6475
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6476
  SQuery* pQuery = &pQInfo->query;
6477 6478
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
6479
  pQuery->tableGroupInfo  = *pTableGroupInfo;
6480
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
6481
  pQuery->numOfOutput     = numOfOutput;
6482 6483 6484
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
6485
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
6486
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
6487 6488
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
6489
  pQuery->pGroupbyExpr    = pGroupbyExpr;
6490
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
6491
  pQuery->fillType        = pQueryMsg->fillType;
6492
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
6493
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
6494 6495
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
6496
  pQuery->sw              = pQueryMsg->sw;
6497
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
6498
  if (pQuery->colList == NULL) {
6499
    goto _cleanup;
6500
  }
6501

6502 6503
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
6504
  for (int16_t i = 0; i < numOfCols; ++i) {
6505
    pQuery->colList[i] = pQueryMsg->colList[i];
6506
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
6507 6508 6509 6510 6511

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
6512
  }
6513

6514
  // calculate the result row size
6515 6516
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
6517 6518 6519 6520 6521 6522
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
D
dapan1121 已提交
6523 6524 6525 6526

    if (pExprs[col].pFilter) {
      ++pQuery->havingNum;
    }
6527
  }
6528

6529
  doUpdateExprColumnIndex(pQuery);
H
Haojun Liao 已提交
6530
  int32_t ret = createFilterInfo(pQuery, pQInfo->qId);
6531
  if (ret != TSDB_CODE_SUCCESS) {
6532
    goto _cleanup;
6533 6534
  }

6535
  if (pQuery->fillType != TSDB_FILL_NONE) {
6536 6537
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
6538
      goto _cleanup;
6539 6540 6541
    }

    // the first column is the timestamp
6542
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
6543 6544
  }

dengyihao's avatar
dengyihao 已提交
6545 6546 6547
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6548
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6549

6550 6551 6552
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6553
  }
H
Haojun Liao 已提交
6554

H
Haojun Liao 已提交
6555
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6556 6557 6558 6559
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6560
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6561
  pQInfo->rspContext = NULL;
6562
  pQInfo->sql = sql;
6563
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6564
  tsem_init(&pQInfo->ready, 0, 0);
6565 6566 6567 6568

  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
6569
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6570 6571
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

6572
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
6573

H
Haojun Liao 已提交
6574
  int32_t index = 0;
H
hjxilinx 已提交
6575
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6576
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
6577

H
Haojun Liao 已提交
6578
    size_t s = taosArrayGetSize(pa);
6579
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6580 6581 6582
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6583

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

H
hjxilinx 已提交
6586
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6587
      STableKeyInfo* info = taosArrayGet(pa, j);
6588
      window.skey = info->lastKey;
6589 6590

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
6591
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
6592 6593 6594
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6595

6596
      item->groupIndex = i;
H
hjxilinx 已提交
6597
      taosArrayPush(p1, &item);
6598 6599

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6600
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6601
      index += 1;
H
hjxilinx 已提交
6602 6603
    }
  }
6604

H
Haojun Liao 已提交
6605
  colIdCheck(pQuery, pQInfo->qId);
6606

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

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

B
Bomin Zhang 已提交
6613
_cleanup_qinfo:
H
Haojun Liao 已提交
6614
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6615

6616 6617 6618 6619
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6620

S
TD-1848  
Shengliang Guan 已提交
6621
  tfree(pTagCols);
B
Bomin Zhang 已提交
6622 6623 6624
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6625 6626
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6627
    }
D
dapan1121 已提交
6628 6629 6630 6631

    if (pExprInfo->pFilter) {
      freeColumnFilterInfo(pExprInfo->pFilter, pExprInfo->base.filterNum);
    }
B
Bomin Zhang 已提交
6632
  }
H
Haojun Liao 已提交
6633

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

6636
_cleanup:
dengyihao's avatar
dengyihao 已提交
6637
  freeQInfo(pQInfo);
6638 6639 6640
  return NULL;
}

H
Haojun Liao 已提交
6641
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6642 6643 6644 6645
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6646

H
hjxilinx 已提交
6647 6648 6649 6650
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6651
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6652 6653 6654
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6655
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
6656
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6657 6658

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6659 6660 6661
  pRuntimeEnv->qinfo = pQInfo;

  SQuery *pQuery = pRuntimeEnv->pQuery;
6662

6663
  STSBuf *pTsBuf = NULL;
6664
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
6665
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
6666
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
6667

6668 6669
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
6670

dengyihao's avatar
dengyihao 已提交
6671
    UNUSED(ret);
H
hjxilinx 已提交
6672
  }
6673

6674 6675 6676
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
D
dapan1121 已提交
6677 6678
    
    pRuntimeEnv->prevResult = prevResult;    
6679 6680
  }

Y
TD-1665  
yihaoDeng 已提交
6681
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
6682

6683 6684
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
H
Haojun Liao 已提交
6685
    qDebug("QInfo:%"PRIu64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQuery->window.skey,
6686
           pQuery->window.ekey, pQuery->order.order);
H
Haojun Liao 已提交
6687
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6688
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6689
    // todo free memory
6690 6691
    return TSDB_CODE_SUCCESS;
  }
6692

H
Haojun Liao 已提交
6693
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
6694
    qDebug("QInfo:%"PRIu64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
6695
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6696 6697
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6698 6699

  // filter the qualified
D
dapan1121 已提交
6700
  if ((code = doInitQInfo(pQInfo, pTsBuf, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6701 6702
    goto _error;
  }
6703

H
hjxilinx 已提交
6704 6705 6706 6707
  return code;

_error:
  // table query ref will be decrease during error handling
6708
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6709 6710 6711
  return code;
}

H
Haojun Liao 已提交
6712
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6713
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6714 6715
      return;
    }
H
Haojun Liao 已提交
6716

B
Bomin Zhang 已提交
6717
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
6718
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
6719 6720 6721
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6722

B
Bomin Zhang 已提交
6723 6724 6725
    free(pFilter);
}

H
Haojun Liao 已提交
6726 6727
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6728
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749
    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 已提交
6750 6751 6752 6753 6754 6755 6756 6757
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 已提交
6758
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6759
    }
D
dapan1121 已提交
6760 6761 6762 6763

    if (pExprInfo[i].pFilter) {
      freeColumnFilterInfo(pExprInfo[i].pFilter, pExprInfo[i].base.filterNum);
    }
H
Haojun Liao 已提交
6764 6765 6766 6767 6768 6769
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6770
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6771 6772 6773
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6774

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

H
Haojun Liao 已提交
6777
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6778
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
6779 6780 6781

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);

6782
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6783

H
Haojun Liao 已提交
6784 6785 6786
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
6787
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
6788
    }
6789

H
Haojun Liao 已提交
6790 6791 6792
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
6793
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
6794
      }
H
hjxilinx 已提交
6795
    }
6796

H
Haojun Liao 已提交
6797 6798
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
6799

S
TD-1848  
Shengliang Guan 已提交
6800 6801
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
6802 6803 6804 6805 6806 6807

    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 已提交
6808
      tfree(pQuery->colList);
H
Haojun Liao 已提交
6809 6810
    }

H
Haojun Liao 已提交
6811 6812 6813 6814
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
6815
  }
6816

H
Haojun Liao 已提交
6817

S
TD-1848  
Shengliang Guan 已提交
6818
  tfree(pQInfo->pBuf);
6819 6820
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
6821
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
6822

H
Haojun Liao 已提交
6823
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
6824
  pQInfo->signature = 0;
6825

H
Haojun Liao 已提交
6826
  qDebug("QInfo:%"PRIu64" QInfo is freed", pQInfo->qId);
6827

S
TD-1848  
Shengliang Guan 已提交
6828
  tfree(pQInfo);
H
hjxilinx 已提交
6829 6830
}

H
Haojun Liao 已提交
6831
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
6832
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
6833
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
hjxilinx 已提交
6834
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6835

H
hjxilinx 已提交
6836
  // load data from file to msg buffer
H
Haojun Liao 已提交
6837
  if (isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
6838 6839
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
6840

H
hjxilinx 已提交
6841
    // make sure file exist
D
fix bug  
dapan1121 已提交
6842 6843
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
6844
      assert(s == pRuntimeEnv->outputBuf->info.rows);
6845

H
Haojun Liao 已提交
6846
      qDebug("QInfo:%"PRIu64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
6847 6848
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
6849
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
6850
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
6851 6852
          assert(0);
        }
H
Haojun Liao 已提交
6853
      } else {
6854
        UNUSED(s);
D
dapan1121 已提交
6855 6856 6857 6858
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
6859
      // dump error info
D
dapan1121 已提交
6860 6861 6862
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
6863
      }
H
Haojun Liao 已提交
6864

D
fix bug  
dapan1121 已提交
6865
      fclose(f);
H
hjxilinx 已提交
6866
    }
6867

H
hjxilinx 已提交
6868
    // all data returned, set query over
H
Haojun Liao 已提交
6869 6870
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
6871
    }
H
hjxilinx 已提交
6872
  } else {
H
Haojun Liao 已提交
6873
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
6874
  }
6875

H
Haojun Liao 已提交
6876
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
6877
  qDebug("QInfo:%"PRIu64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
6878
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
6879

H
Haojun Liao 已提交
6880
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
6881
    qDebug("QInfo:%"PRIu64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQuery->limit.limit);
H
Haojun Liao 已提交
6882
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
6883
  }
6884

H
hjxilinx 已提交
6885
  return TSDB_CODE_SUCCESS;
6886 6887
}

H
Haojun Liao 已提交
6888
bool doBuildResCheck(SQInfo* pQInfo) {
6889 6890 6891 6892 6893
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
6894
  buildRes = needBuildResAfterQueryComplete(pQInfo);
6895

H
Haojun Liao 已提交
6896 6897
  // 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 已提交
6898
  assert(pQInfo->owner == taosGetSelfPthreadId());
6899
  pQInfo->owner = 0;
H
Haojun Liao 已提交
6900

H
Haojun Liao 已提交
6901
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
6902

6903
  // used in retrieve blocking model.
H
Haojun Liao 已提交
6904
  tsem_post(&pQInfo->ready);
6905 6906 6907
  return buildRes;
}

H
Haojun Liao 已提交
6908 6909 6910 6911
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
6912 6913
  }

6914 6915 6916
  if (IS_VAR_DATA_TYPE(type)) {
    // Binary data overflows for sort of unknown reasons. Let trim the overflow data
    if (varDataTLen(val) > bytes) {
H
Haojun Liao 已提交
6917
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
6918 6919 6920 6921 6922
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
6923
  } else {
H
Haojun Liao 已提交
6924
    memcpy(output, val, bytes);
6925 6926 6927
  }
}

H
Haojun Liao 已提交
6928
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
6929 6930 6931 6932
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
6933
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
6934 6935
}

H
Haojun Liao 已提交
6936
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
6937
  int64_t t = getQuerySupportBufSize(numOfTables);
6938
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6939
    return TSDB_CODE_SUCCESS;
6940
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
6941 6942

    while(1) {
6943
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
6944 6945
      int64_t remain = s - t;
      if (remain >= 0) {
6946
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958
          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 已提交
6959
void releaseQueryBuf(size_t numOfTables) {
6960
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6961 6962 6963 6964 6965 6966
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
6967
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
6968
}