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

H
Haojun Liao 已提交
20
#include "exception.h"
21
#include "hash.h"
H
Haojun Liao 已提交
22
#include "texpr.h"
H
Haojun Liao 已提交
23 24 25
#include "qExecutor.h"
#include "qResultbuf.h"
#include "qUtil.h"
S
slguan 已提交
26
#include "queryLog.h"
27
#include "tlosertree.h"
28
#include "ttype.h"
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

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

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

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

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

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

S
Shengliang Guan 已提交
130
  mon = (int)(mon + interval);
131 132 133 134 135 136 137 138 139 140 141
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->ekey = mktime(&tm) * 1000L;

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

H
Haojun Liao 已提交
142
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
143
static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
144
    int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
145

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

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

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

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

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

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

H
Haojun Liao 已提交
165 166
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 已提交
167
static SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
H
Haojun Liao 已提交
168

H
Haojun Liao 已提交
169
static SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
170 171 172
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 已提交
173
static SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
174
static SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
175 176 177
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 已提交
178
static SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput);
H
Haojun Liao 已提交
179
static SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
H
Haojun Liao 已提交
180

H
Haojun Liao 已提交
181 182 183 184
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 已提交
185
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
186
static void destroyOperatorInfo(SOperatorInfo* pOperator);
H
Haojun Liao 已提交
187

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

H
Haojun Liao 已提交
190
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock);
H
Haojun Liao 已提交
191
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 已提交
192

H
Haojun Liao 已提交
193 194
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 已提交
195
static bool isPointInterpoQuery(SQuery *pQuery);
H
Haojun Liao 已提交
196 197 198
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);
199 200 201
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
202

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

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

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

    idata.pData = calloc(1, MAX(idata.info.bytes * numOfRows, minSize));  // at least to hold a pointer on x64 platform
218

H
Haojun Liao 已提交
219 220
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
221 222

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

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

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

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

sangshuduo's avatar
sangshuduo 已提交
242
int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
243 244 245
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);

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

    /*
     * 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 已提交
254
    if (hasMainFunction && (id == TSDB_FUNC_TS || id == TSDB_FUNC_TAG || id == TSDB_FUNC_TAGPRJ)) {
H
Haojun Liao 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267
      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 已提交
268
static void clearNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
269 270 271 272 273 274
  for (int32_t j = 0; j < numOfOutput; ++j) {
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    pResInfo->numOfRes = 0;
  }
}

H
Haojun Liao 已提交
275
static bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) {
276 277 278
  if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) {
    return false;
  }
279

280
  for (int32_t i = 0; i < pGroupbyExpr->numOfGroupCols; ++i) {
281
    SColIndex *pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, i);
Y
TD-1230  
yihaoDeng 已提交
282
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
283
      //make sure the normal column locates at the second position if tbname exists in group by clause
284
      if (pGroupbyExpr->numOfGroupCols > 1) {
285
        assert(pColIndex->colIndex > 0);
286
      }
287

288 289 290
      return true;
    }
  }
291

292 293 294
  return false;
}

H
Haojun Liao 已提交
295
static bool isStabledev(SQuery* pQuery) {
296 297 298 299 300 301 302 303 304 305
  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 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
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);
}
324

H
Haojun Liao 已提交
325
static bool isProjQuery(SQuery *pQuery) {
326
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
327
    int32_t functId = pQuery->pExpr1[i].base.functionId;
328 329 330 331 332 333 334 335
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

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

338
static bool isTopBottomQuery(SQuery *pQuery) {
339
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
340
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
341 342 343
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
344

345 346 347 348
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      return true;
    }
  }
349

350 351 352
  return false;
}

353 354 355
static bool timeWindowInterpoRequired(SQuery *pQuery) {
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
356
    if (functionId == TSDB_FUNC_TWA || functionId == TSDB_FUNC_INTERP) {
357 358 359 360 361 362 363
      return true;
    }
  }

  return false;
}

H
Haojun Liao 已提交
364
static bool hasTagValOutput(SQuery* pQuery) {
H
Haojun Liao 已提交
365
  SExprInfo *pExprInfo = &pQuery->pExpr1[0];
H
Haojun Liao 已提交
366 367 368 369
  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 已提交
370
      SExprInfo *pLocalExprInfo = &pQuery->pExpr1[idx];
H
Haojun Liao 已提交
371 372 373 374 375 376 377 378 379 380 381

      // 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 已提交
382 383 384 385 386 387 388 389 390 391 392 393
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;
}

394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
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 已提交
420
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
421
                                             int16_t bytes, bool masterscan, uint64_t uid) {
422
  bool existed = false;
H
Haojun Liao 已提交
423
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

  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;
        }
      }
    }
443
  } else {
444 445
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
446
    }
447
  }
448

449
  if (!existed) {
450
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
451

452 453 454 455 456 457 458 459 460 461 462 463 464
    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;
465
    }
H
Haojun Liao 已提交
466

467
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
468
    pResultRowInfo->curIndex = pResultRowInfo->size++;
469
  }
470

471
  // too many time window in query
H
Haojun Liao 已提交
472
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
473 474 475
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
476
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
477 478 479
}

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

H
Haojun Liao 已提交
483 484
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
   if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
485 486 487 488 489 490
     if (QUERY_IS_ASC_QUERY(pQuery)) {
       getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, &w);
     } else { // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
       getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, &w);
     }

H
Haojun Liao 已提交
491
     pResultRowInfo->prevSKey = w.skey;
H
Haojun Liao 已提交
492
   } else {
H
Haojun Liao 已提交
493
    w.skey = pResultRowInfo->prevSKey;
H
Haojun Liao 已提交
494 495
   }

496
    if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
497
      w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
498
    } else {
499
      w.ekey = w.skey + pQuery->interval.interval - 1;
500
    }
501
  } else {
H
Haojun Liao 已提交
502 503
    int32_t slot = curTimeWindowIndex(pResultRowInfo);
    SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot);
504
    w = pWindowRes->win;
505
  }
506

507
  if (w.skey > ts || w.ekey < ts) {
508 509 510
    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;
511 512
    } else {
      int64_t st = w.skey;
513

514
      if (st > ts) {
515
        st -= ((st - ts + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
516
      }
517

518
      int64_t et = st + pQuery->interval.interval - 1;
519
      if (et < ts) {
520
        st += ((ts - et + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
521
      }
522

523
      w.skey = st;
524
      w.ekey = w.skey + pQuery->interval.interval - 1;
525
    }
526
  }
527

528 529 530 531 532 533 534
  /*
   * 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;
  }
535

536 537 538
  return w;
}

H
Haojun Liao 已提交
539 540
// 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) {
541
  if (pWindowRes->pageId != -1) {
542 543
    return 0;
  }
544

545
  tFilePage *pData = NULL;
546

547 548
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
549
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
550

H
Haojun Liao 已提交
551
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
552
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
553
  } else {
H
Haojun Liao 已提交
554 555 556
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
557

H
Haojun Liao 已提交
558
    if (pData->num + size > pResultBuf->pageSize) {
H
Haojun Liao 已提交
559 560
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
561
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
562
      if (pData != NULL) {
563
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
564 565 566
      }
    }
  }
567

568 569 570
  if (pData == NULL) {
    return -1;
  }
571

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

H
Haojun Liao 已提交
577
    pData->num += size;
578
    assert(pWindowRes->pageId >= 0);
579
  }
580

581 582 583
  return 0;
}

584
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
585
                                       bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
586
                                       int32_t numOfOutput, int32_t* rowCellInfoOffset) {
587 588
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
589

590
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
591
  if (pResultRow == NULL) {
592 593
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
594
  }
595

596
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
597
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
598
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQuery->intermediateResultRowSize);
H
Haojun Liao 已提交
599
    if (ret != TSDB_CODE_SUCCESS) {
600 601 602
      return -1;
    }
  }
603

604
  // set time window for current result
H
Haojun Liao 已提交
605
  pResultRow->win = (*win);
606
  *pResult = pResultRow;
H
Haojun Liao 已提交
607
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
608

609 610 611
  return TSDB_CODE_SUCCESS;
}

612 613 614 615 616 617 618 619 620
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 已提交
621
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
622 623 624 625 626 627 628 629
  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 已提交
630
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
631 632
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
633

H
Haojun Liao 已提交
634 635 636 637
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
638

H
Haojun Liao 已提交
639 640 641 642 643 644 645 646 647 648 649 650
      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;
      }
651 652
    }
  }
653

H
Haojun Liao 已提交
654
  assert(forwardStep > 0);
655 656 657
  return forwardStep;
}

658
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
659
  int64_t skey = TSKEY_INITIAL_VAL;
660 661 662
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
663
    if (pResult->closed) {
664
      break;
H
Haojun Liao 已提交
665 666
    }

667
    // new closed result rows
668 669 670 671 672 673 674 675 676 677
    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 已提交
678
    } else {
679 680 681 682 683
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
684 685 686
    }
  }

687
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
688
  if (skey == TSKEY_INITIAL_VAL) {
689
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
690 691
  } else {

692 693 694 695 696
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
697
    }
698

D
fix bug  
dapan1121 已提交
699
    if (i == pResultRowInfo->size - 1) {
700
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
701 702 703 704
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

705
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
706
  }
707
}
708

H
Haojun Liao 已提交
709 710 711
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))) {
712 713 714
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
715
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
716
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQuery->timeWindowInterpo);
717
  }
718 719 720
}

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

H
Haojun Liao 已提交
724
  int32_t num   = -1;
725
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
726
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
727

H
hjxilinx 已提交
728
  STableQueryInfo* item = pQuery->current;
729

730 731
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (ekey < pDataBlockInfo->window.ekey) {
732
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
733 734
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
735 736
      }
    } else {
737
      num = pDataBlockInfo->rows - startPos;
738
      if (updateLastKey) {
H
hjxilinx 已提交
739
        item->lastKey = pDataBlockInfo->window.ekey + step;
740 741 742 743
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
744
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
745 746
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
747 748 749 750
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
751
        item->lastKey = pDataBlockInfo->window.skey + step;
752 753 754
      }
    }
  }
755

H
Haojun Liao 已提交
756
  assert(num > 0);
757 758 759
  return num;
}

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

765
  for (int32_t k = 0; k < numOfOutput; ++k) {
766
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
767
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
768

769
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
770 771

    int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1);
772 773
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
774 775 776 777 778
    }

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

H
Haojun Liao 已提交
780
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
781

782 783 784 785 786
    // 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 已提交
787

788 789
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
790
    }
791 792 793

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
794
    pCtx[k].pInput = start;
795 796 797 798
  }
}


H
Haojun Liao 已提交
799
static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
800
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
801
  getNextTimeWindow(pQuery, pNext);
802

H
Haojun Liao 已提交
803
  // next time window is not in current block
H
Haojun Liao 已提交
804 805
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
806 807
    return -1;
  }
808

H
Haojun Liao 已提交
809 810
  TSKEY startKey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
811
    startKey = pNext->skey;
H
Haojun Liao 已提交
812 813
    if (startKey < pQuery->window.skey) {
      startKey = pQuery->window.skey;
814
    }
H
Haojun Liao 已提交
815
  } else {
H
Haojun Liao 已提交
816
    startKey = pNext->ekey;
H
Haojun Liao 已提交
817 818
    if (startKey > pQuery->window.skey) {
      startKey = pQuery->window.skey;
819
    }
H
Haojun Liao 已提交
820
  }
821

H
Haojun Liao 已提交
822
  int32_t startPos = 0;
H
Haojun Liao 已提交
823

H
Haojun Liao 已提交
824
  // tumbling time window query, a special case of sliding time window query
825
  if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) {
H
Haojun Liao 已提交
826 827 828
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
829
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
830
      startPos = 0;
H
Haojun Liao 已提交
831
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
832 833 834 835
      startPos = pDataBlockInfo->rows - 1;
    } else {
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order);
    }
H
Haojun Liao 已提交
836
  }
837

H
Haojun Liao 已提交
838 839 840 841
  /*
   * 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 已提交
842 843 844
  if (primaryKeys == NULL) {
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
845
    } else {
H
Haojun Liao 已提交
846
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
847
    }
H
Haojun Liao 已提交
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
  } 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;
      }
867
    }
868
  }
869

H
Haojun Liao 已提交
870
  return startPos;
871 872
}

H
Haojun Liao 已提交
873
static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
874 875 876 877 878 879 880 881 882 883 884 885
  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;
    }
  }
886

887 888 889
  return ekey;
}

H
Haojun Liao 已提交
890 891 892 893 894 895 896 897 898 899 900 901
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;
    }
  }
}

902
// window start key interpolation
H
Haojun Liao 已提交
903

904

H
Haojun Liao 已提交
905
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
906
    int32_t rowIndex) {
907 908 909 910 911 912 913
  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 已提交
914
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
915 916 917
  }
}

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

H
Haojun Liao 已提交
921
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
922
  if (tsCols == NULL) {
H
Haojun Liao 已提交
923
    ts = ascQuery? win->skey : win->ekey;
924
  } else {
H
Haojun Liao 已提交
925
    int32_t offset = ascQuery? 0:rows-1;
926 927 928 929 930 931
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
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 已提交
955
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
956
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
957

H
Haojun Liao 已提交
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
    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 已提交
982
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
983
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
984 985 986 987 988 989 990

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

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

H
Haojun Liao 已提交
999
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
1000
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
1001
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1002
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
1003
        }
H
Haojun Liao 已提交
1004 1005 1006 1007 1008
      }
    }
  }
}

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

H
Haojun Liao 已提交
1012
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1013
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1014
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
1015
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
1016 1017 1018 1019 1020
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

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

H
Haojun Liao 已提交
1024
  for (int32_t k = 0; k < numOfOutput; ++k) {
1025 1026
    pCtx[k].startTs = pQuery->window.skey;
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
1027 1028 1029
  }
}

H
Haojun Liao 已提交
1030 1031
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 已提交
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
  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 已提交
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
    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 已提交
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084

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

H
Haojun Liao 已提交
1090 1091
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

H
Haojun Liao 已提交
1092 1093 1094 1095 1096
  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 已提交
1097
  TSKEY key = ascQuery? win->skey:win->ekey;
H
Haojun Liao 已提交
1098 1099 1100 1101 1102
  if (key == curTs) {
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1103
  if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
H
Haojun Liao 已提交
1104 1105 1106 1107 1108
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

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

H
Haojun Liao 已提交
1111 1112
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1113 1114 1115 1116
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1117
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
  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 已提交
1143 1144
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
  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 已提交
1166
        tsCols, win);
H
Haojun Liao 已提交
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
    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 已提交
1194 1195 1196
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
  STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info;

H
Haojun Liao 已提交
1197 1198 1199
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
  SQuery*           pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1200 1201

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

H
Haojun Liao 已提交
1204
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1205

H
Haojun Liao 已提交
1206 1207 1208
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1209
    tsCols = (int64_t*) pColDataInfo->pData;
H
Haojun Liao 已提交
1210 1211
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1212 1213
  }

H
Haojun Liao 已提交
1214
  int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1);
H
Haojun Liao 已提交
1215
  TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1216 1217

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

H
Haojun Liao 已提交
1220 1221 1222
  SResultRow* pResult = NULL;
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                        numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1223
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1224
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1225 1226 1227
  }

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1228 1229
  TSKEY   ekey = reviseWindowEkey(pQuery, &win);
  forwardStep =
H
Haojun Liao 已提交
1230
      getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1231 1232

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1233
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1234 1235
  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 已提交
1236
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1237
      if (pRes->closed) {
H
Haojun Liao 已提交
1238 1239
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1240
        continue;
H
Haojun Liao 已提交
1241
      }
H
Haojun Liao 已提交
1242 1243

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1244 1245
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1246 1247 1248 1249 1250
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

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

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

H
Haojun Liao 已提交
1255
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1256
      setNotInterpoWindowKey(pInfo->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1257

H
Haojun Liao 已提交
1258
      doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &w, startPos, 0, tsCols, pSDataBlock->info.rows,
H
Haojun Liao 已提交
1259
                                   numOfOutput);
H
Haojun Liao 已提交
1260 1261
    }

H
Haojun Liao 已提交
1262
    // restore current time window
H
Haojun Liao 已提交
1263 1264
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1265 1266 1267
    if (ret != TSDB_CODE_SUCCESS) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
H
Haojun Liao 已提交
1268 1269 1270
  }

  // window start key interpolation
H
Haojun Liao 已提交
1271
  doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
H
Haojun Liao 已提交
1272
  doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows,
H
Haojun Liao 已提交
1273
                               numOfOutput);
H
Haojun Liao 已提交
1274 1275 1276 1277

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1278
    startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1279 1280
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1281 1282
    }

H
Haojun Liao 已提交
1283
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1284 1285
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1286
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1287
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1288 1289
    }

H
Haojun Liao 已提交
1290
    ekey = reviseWindowEkey(pQuery, &nextWin);
H
Haojun Liao 已提交
1291 1292
    forwardStep =
        getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1293 1294

    // window start(end) key interpolation
H
Haojun Liao 已提交
1295
    doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &nextWin, startPos, forwardStep);
H
Haojun Liao 已提交
1296
    doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &nextWin, startPos, forwardStep, tsCols,
H
Haojun Liao 已提交
1297
                                 pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1298
  }
H
Haojun Liao 已提交
1299 1300

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

H
Haojun Liao 已提交
1305
  updateResultRowInfoActiveIndex(pResultRowInfo, pQuery, pQuery->current->lastKey);
H
Haojun Liao 已提交
1306 1307
}

H
Haojun Liao 已提交
1308 1309 1310
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  STableQueryInfo*  item = pRuntimeEnv->pQuery->current;
H
Haojun Liao 已提交
1311

H
Haojun Liao 已提交
1312
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1313 1314 1315 1316 1317 1318 1319
  int16_t          bytes = pColInfoData->info.bytes;
  int16_t          type = pColInfoData->info.type;

  if (type == TSDB_DATA_TYPE_FLOAT || type == TSDB_DATA_TYPE_DOUBLE) {
    qError("QInfo:%p group by not supported on double/float columns, abort", pRuntimeEnv->qinfo);
    return;
  }
H
Haojun Liao 已提交
1320

H
Haojun Liao 已提交
1321
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
sangshuduo's avatar
sangshuduo 已提交
1322
    char* val = ((char*)pColInfoData->pData) + bytes * j;
H
Haojun Liao 已提交
1323
    if (isNull(val, type)) {
H
Haojun Liao 已提交
1324 1325 1326
      continue;
    }

H
Haojun Liao 已提交
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
    if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) {
      if (pInfo->prevData == NULL) {
        pInfo->prevData = malloc(bytes);
      }

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

      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 已提交
1339 1340
    }

H
Haojun Liao 已提交
1341
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1342
      pInfo->binfo.pCtx[k].size = 1;
H
Haojun Liao 已提交
1343 1344
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1345
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1346 1347 1348 1349 1350
      }
    }
  }
}

H
Haojun Liao 已提交
1351
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
  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 已提交
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
}

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

H
Haojun Liao 已提交
1385
  setResultRowKey(pResultRow, pData, type);
H
Haojun Liao 已提交
1386
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
1387
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
H
Haojun Liao 已提交
1388 1389 1390 1391 1392
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1393 1394
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1395 1396
  return TSDB_CODE_SUCCESS;
}
1397

H
Haojun Liao 已提交
1398
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
  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 已提交
1416
  return -1;
H
Haojun Liao 已提交
1417 1418
}

1419
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1420
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
hjxilinx 已提交
1421
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1422 1423 1424 1425 1426

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

1428 1429 1430
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1431

1432
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
hjxilinx 已提交
1433 1434
    return QUERY_IS_ASC_QUERY(pQuery);
  }
1435

H
Haojun Liao 已提交
1436
  // denote the order type
1437
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
1438
    return pCtx->param[0].i64 == pQuery->order.order;
1439 1440
  }

1441 1442 1443
  // 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)) {
1444 1445
    return false;
  }
1446

1447 1448 1449
  return true;
}

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

H
Haojun Liao 已提交
1453 1454 1455 1456
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1457 1458 1459 1460 1461 1462
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1463
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1464 1465

  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1466
  if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
1467
    pCtx->preAggVals.isSet  = true;
H
Haojun Liao 已提交
1468 1469
    pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey;
    pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey;
H
Haojun Liao 已提交
1470
  }
H
Haojun Liao 已提交
1471 1472
}

H
Haojun Liao 已提交
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
// 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;
}
1514

H
Haojun Liao 已提交
1515
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1516
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1517 1518
  SQuery* pQuery = pRuntimeEnv->pQuery;

1519 1520
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1521
    return NULL;
1522 1523
  }

H
Haojun Liao 已提交
1524
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1525 1526 1527 1528
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1529

H
Haojun Liao 已提交
1530 1531
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base;
1532
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1533

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

Y
TD-1230  
yihaoDeng 已提交
1536
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1537 1538
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1539
    } else {
1540 1541
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1542

H
Haojun Liao 已提交
1543 1544
    pCtx->inputBytes = pSqlFuncMsg->colBytes;
    pCtx->inputType  = pSqlFuncMsg->colType;
H
Haojun Liao 已提交
1545

1546
    pCtx->ptsOutputBuf = NULL;
1547

H
Haojun Liao 已提交
1548 1549
    pCtx->outputBytes  = pExpr[i].bytes;
    pCtx->outputType   = pExpr[i].type;
1550

1551
    pCtx->order        = pQuery->order.order;
H
Haojun Liao 已提交
1552
    pCtx->functionId   = pSqlFuncMsg->functionId;
H
Haojun Liao 已提交
1553
    pCtx->stableQuery  = pQuery->stableQuery;
H
Haojun Liao 已提交
1554
    pCtx->interBufBytes = pExpr[i].interBytes;
1555 1556
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1557

H
Haojun Liao 已提交
1558
    pCtx->numOfParams  = pSqlFuncMsg->numOfParams;
1559 1560 1561
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
      int16_t type = pSqlFuncMsg->arg[j].argType;
      int16_t bytes = pSqlFuncMsg->arg[j].argBytes;
1562 1563 1564 1565
      if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) {
        continue;
      }

1566
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
1567
        tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type);
1568 1569 1570 1571
      } else {
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type);
      }
    }
1572

1573 1574
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1575

1576
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1577
      int32_t f = pExpr[0].base.functionId;
1578
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1579

H
Haojun Liao 已提交
1580
      pCtx->param[2].i64 = pQuery->order.order;
1581
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1582
      pCtx->param[3].i64 = functionId;
1583
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1584

1585
      pCtx->param[1].i64 = pQuery->order.orderColId;
H
Haojun Liao 已提交
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
    } 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) {
1598
      pCtx->param[0].i64 = pQuery->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1599 1600 1601 1602 1603 1604 1605 1606
      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];
1607
    }
H
Haojun Liao 已提交
1608
  }
1609

H
Haojun Liao 已提交
1610
  for(int32_t i = 1; i < numOfOutput; ++i) {
sangshuduo's avatar
sangshuduo 已提交
1611 1612
    (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) +
        pExpr[i - 1].interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
1613
  }
1614

H
Haojun Liao 已提交
1615 1616
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1617
  return pFuncCtx;
H
Haojun Liao 已提交
1618 1619
}

H
Haojun Liao 已提交
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
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 已提交
1638
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables) {
H
Haojun Liao 已提交
1639
  qDebug("QInfo:%p setup runtime env", pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
  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 已提交
1650 1651
  pRuntimeEnv->currentOffset = pQuery->limit.offset;

H
Haojun Liao 已提交
1652 1653 1654
  // 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 已提交
1655 1656
  pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport));

H
Haojun Liao 已提交
1657 1658
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1659 1660 1661
    goto _clean;
  }

H
Haojun Liao 已提交
1662 1663 1664 1665 1666 1667
  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 已提交
1668

H
Haojun Liao 已提交
1669 1670
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1671

H
Haojun Liao 已提交
1672
  qDebug("QInfo:%p init runtime environment completed", pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
1673 1674

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

  } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
1679
    if (pQuery->stableQuery) {
H
Haojun Liao 已提交
1680 1681
      pRuntimeEnv->proot = createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner,
                                                                    pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1682
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1683
    } else {
H
Haojun Liao 已提交
1684 1685
      pRuntimeEnv->proot =
          createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1686
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1687

H
Haojun Liao 已提交
1688
      if (pQuery->pExpr2 != NULL) {
H
Haojun Liao 已提交
1689 1690
        pRuntimeEnv->proot =
            createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1691
      }
H
Haojun Liao 已提交
1692

H
Haojun Liao 已提交
1693
      if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
1694 1695
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
H
Haojun Liao 已提交
1696
      }
H
Haojun Liao 已提交
1697
    }
H
Haojun Liao 已提交
1698

H
Haojun Liao 已提交
1699 1700 1701 1702
  } else if (pQuery->groupbyColumn) {
    pRuntimeEnv->proot =
        createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1703

H
Haojun Liao 已提交
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
    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);
    }
1715

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

H
Haojun Liao 已提交
1718 1719
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1720
    }
H
Haojun Liao 已提交
1721 1722 1723 1724 1725 1726
  } 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 已提交
1727
    }
H
Haojun Liao 已提交
1728
  }
H
Haojun Liao 已提交
1729

H
Haojun Liao 已提交
1730 1731 1732
  if (pQuery->limit.offset > 0) {
    pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }
H
Haojun Liao 已提交
1733

H
Haojun Liao 已提交
1734 1735 1736 1737 1738
  if (pQuery->limit.limit > 0) {
    pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }

  return TSDB_CODE_SUCCESS;
1739

1740
_clean:
1741
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1742 1743 1744 1745
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1746

1747
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1748 1749
}

H
Haojun Liao 已提交
1750
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1751
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1752 1753 1754 1755

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

H
Haojun Liao 已提交
1756
  SMemRef* pMemRef = &pQuery->memRef;
H
Haojun Liao 已提交
1757 1758 1759
  assert(pMemRef->ref == 0 && pMemRef->imem == NULL && pMemRef->mem == NULL);
}

H
Haojun Liao 已提交
1760
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
1761
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1762
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1763

1764
  qDebug("QInfo:%p teardown runtime env", pQInfo);
1765

1766 1767 1768
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1769
      tfree(pRuntimeEnv->sasArray[i].colList);
1770 1771 1772 1773 1774
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1775
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1776
  doFreeQueryHandle(pRuntimeEnv);
1777

H
Haojun Liao 已提交
1778
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1779

S
TD-1848  
Shengliang Guan 已提交
1780
  tfree(pRuntimeEnv->keyBuf);
1781
  tfree(pRuntimeEnv->prevRow);
1782 1783
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1784 1785
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1786

H
Haojun Liao 已提交
1787
  pRuntimeEnv->pool = destroyResultRowPool(pRuntimeEnv->pool);
1788 1789
  taosArrayDestroyEx(pRuntimeEnv->prevResult, freeInterResult);
  pRuntimeEnv->prevResult = NULL;
H
Haojun Liao 已提交
1790

H
Haojun Liao 已提交
1791 1792 1793
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1794
  destroyOperatorInfo(pRuntimeEnv->proot);
1795 1796
}

1797 1798 1799 1800
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1801
bool isQueryKilled(SQInfo *pQInfo) {
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
  if (IS_QUERY_KILLED(pQInfo)) {
    return true;
  }

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

    assert(pQInfo->startExecTs != 0);
    qDebug("QInfo:%p retrieve not arrive beyond %d sec, abort current query execution, start:%"PRId64", current:%d", pQInfo, 1,
           pQInfo->startExecTs, taosGetTimestampSec());
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
1822
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
1823
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
1824 1825
    return false;
  }
1826

1827
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1828
  if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) {
1829 1830
    return true;
  }
1831

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

1835 1836
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
1837
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
1838 1839
      continue;
    }
1840

1841 1842 1843
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
1844

H
Haojun Liao 已提交
1845
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
1846 1847 1848
      return true;
    }
  }
1849

1850 1851 1852
  return false;
}

1853
// todo refactor with isLastRowQuery
1854
bool isPointInterpoQuery(SQuery *pQuery) {
1855
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1856 1857
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
1858 1859 1860
      return true;
    }
  }
1861

1862 1863 1864 1865
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
1866
static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) {
1867
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1868
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1869 1870 1871
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
1872

1873 1874 1875 1876 1877
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
1878

1879 1880 1881
  return false;
}

H
hjxilinx 已提交
1882
static bool isFirstLastRowQuery(SQuery *pQuery) {
1883
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1884
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
1885 1886 1887 1888
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
1889

1890 1891 1892
  return false;
}

H
hjxilinx 已提交
1893
static bool needReverseScan(SQuery *pQuery) {
1894
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1895
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1896 1897 1898
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
1899

1900
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
1901 1902
      return true;
    }
1903 1904

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
1905
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
1906
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
1907 1908 1909
      if (order != pQuery->order.order) {
        return true;
      }
1910
    }
1911
  }
1912

1913 1914
  return false;
}
H
hjxilinx 已提交
1915

H
Haojun Liao 已提交
1916 1917 1918 1919
/**
 * 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 已提交
1920
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
1921
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1922
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
1923 1924

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
1925 1926 1927 1928

    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 已提交
1929
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
1930 1931 1932
      return false;
    }
  }
1933

H
hjxilinx 已提交
1934 1935 1936
  return true;
}

1937 1938
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
1939
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
1940 1941
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
1942 1943

  /*
1944
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
1945 1946
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
1947 1948
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
1949
    win->ekey = INT64_MAX;
1950 1951
  } 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 已提交
1952
  } else {
1953
    win->ekey = win->skey + pQuery->interval.interval - 1;
1954 1955 1956 1957 1958
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
1959
    pQuery->checkResultBuf = 0;
1960
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
1961
    pQuery->checkResultBuf = 0;
1962 1963
  } else {
    bool hasMultioutput = false;
1964
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1965
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
1966 1967 1968
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
1969

H
Haojun Liao 已提交
1970
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
1971 1972 1973 1974
      if (!hasMultioutput) {
        break;
      }
    }
1975

H
Haojun Liao 已提交
1976
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
1977 1978 1979 1980 1981 1982
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
1983
bool colIdCheck(SQuery *pQuery, void* qinfo) {
1984 1985
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
1986
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
H
Haojun Liao 已提交
1987
      qError("QInfo:%p invalid data load column for query", qinfo);
1988 1989 1990
      return false;
    }
  }
1991

1992 1993 1994 1995 1996 1997
  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) {
1998
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1999
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2000

2001 2002 2003 2004
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2005

2006 2007 2008 2009
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2010

2011 2012 2013 2014 2015 2016 2017
  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); }

2018
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2019 2020
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2021
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2022
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2023 2024 2025

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

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

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

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

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

H
Haojun Liao 已提交
2048
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2049 2050 2051
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2052

2053 2054
    return;
  }
2055

2056
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2057
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2058 2059 2060
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2061

2062
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2063 2064 2065
    return;
  }

2066
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2067
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2068
      qDebug(msg, pQInfo, "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);
H
Haojun Liao 已提交
2069 2070
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2071

2072
    pQuery->order.order = TSDB_ORDER_ASC;
2073 2074
    return;
  }
2075

2076
  if (pQuery->interval.interval == 0) {
2077 2078
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2079
        qDebug(msg, pQInfo, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2080 2081
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2082
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2083
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2084
      }
2085

2086
      pQuery->order.order = TSDB_ORDER_ASC;
2087 2088
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2089
        qDebug(msg, pQInfo, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2090 2091
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2092
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2093
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2094
      }
2095

2096
      pQuery->order.order = TSDB_ORDER_DESC;
2097
    }
2098

2099
  } else {  // interval query
2100
    if (stableQuery) {
2101 2102
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2103
          qDebug(msg, pQInfo, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2104 2105
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2106
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2107
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2108
        }
2109

2110
        pQuery->order.order = TSDB_ORDER_ASC;
2111 2112
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2113
          qDebug(msg, pQInfo, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2114 2115
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2116
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2117
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2118
        }
2119

2120
        pQuery->order.order = TSDB_ORDER_DESC;
2121 2122 2123 2124 2125
      }
    }
  }
}

2126 2127
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2128
  int32_t MIN_ROWS_PER_PAGE = 4;
2129

H
Haojun Liao 已提交
2130
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2131 2132 2133 2134
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2139 2140
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2141 2142
}

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

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

H
Haojun Liao 已提交
2148
  if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) {
2149 2150 2151 2152 2153
    return true;
  }

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

H
Haojun Liao 已提交
2155 2156 2157 2158 2159 2160 2161 2162
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2163
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2164
    if (index == -1) {
H
Haojun Liao 已提交
2165
      return true;
2166
    }
2167

2168
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2169
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2170
      return true;
2171
    }
2172

2173
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2174
    if (pDataStatis[index].numOfNull == numOfRows) {
2175 2176 2177 2178

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2179
        if (pFilterElem->fp == isNullOperator) {
2180 2181 2182 2183
          return true;
        }
      }

2184 2185
      continue;
    }
2186

H
Haojun Liao 已提交
2187 2188 2189
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2193
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2194
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2195 2196 2197 2198 2199
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2200
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2201 2202 2203 2204 2205
          return true;
        }
      }
    }
  }
2206

H
Haojun Liao 已提交
2207
  return false;
2208 2209
}

H
Haojun Liao 已提交
2210 2211 2212 2213 2214 2215 2216 2217
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 已提交
2218
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2219

H
Haojun Liao 已提交
2220
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2221 2222 2223 2224
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2225
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2226
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2227 2228 2229
        break;
      }

H
Haojun Liao 已提交
2230 2231
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2232 2233 2234 2235 2236
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2237 2238 2239
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2240 2241 2242 2243
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2244
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2245 2246 2247 2248
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2249 2250
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2251 2252 2253 2254 2255 2256 2257 2258
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
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;
}
2284

H
Haojun Liao 已提交
2285
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
H
Haojun Liao 已提交
2286
                        SSDataBlock* pBlock, STSBuf* pTsBuf, bool ascQuery) {
H
Haojun Liao 已提交
2287 2288 2289 2290 2291
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315
  if (pTsBuf != NULL) {
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

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

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

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

H
Haojun Liao 已提交
2320 2321 2322
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2323

H
Haojun Liao 已提交
2324 2325 2326 2327 2328 2329 2330 2331
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2332
          } else {
H
Haojun Liao 已提交
2333 2334 2335 2336 2337 2338
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2339
          }
H
Haojun Liao 已提交
2340 2341

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2342 2343 2344 2345 2346
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2347
        if (!qualified) {
H
Haojun Liao 已提交
2348 2349 2350 2351
          break;
        }
      }

H
Haojun Liao 已提交
2352
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2353
      if (!qualified) {
H
Haojun Liao 已提交
2354
        all = false;
H
Haojun Liao 已提交
2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
      }
    }
  }

  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 已提交
2372
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2373 2374 2375
          }

          start += len;
2376
          len = 0;
H
Haojun Liao 已提交
2377 2378 2379 2380
        }
      }
    }

2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
    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 已提交
2394 2395 2396 2397
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

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

H
Haojun Liao 已提交
2402 2403
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
H
Haojun Liao 已提交
2404 2405 2406 2407 2408 2409
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2410 2411 2412
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 已提交
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449
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 已提交
2450 2451
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2452
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2453
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2454
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2455

H
Haojun Liao 已提交
2456
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2457
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
2458
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQuery);
H
Haojun Liao 已提交
2459

H
Haojun Liao 已提交
2460
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2461 2462
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2463
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2464
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2465

H
Haojun Liao 已提交
2466
    if (pQuery->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2467 2468 2469 2470 2471 2472 2473
      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 已提交
2474
      setTimestampListJoinInfo(pRuntimeEnv, &t, pQuery->current);
H
Haojun Liao 已提交
2475 2476 2477 2478 2479 2480

      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 已提交
2481 2482 2483
    }
  }

H
Haojun Liao 已提交
2484 2485 2486 2487 2488 2489
  // 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.
  if (pQuery->numOfFilterCols > 0 || pQuery->groupbyColumn ||
      (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info))) {
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2490

H
Haojun Liao 已提交
2491 2492 2493 2494 2495 2496
  // 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 已提交
2497

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

H
Haojun Liao 已提交
2501 2502 2503 2504 2505
      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 已提交
2506
      }
2507 2508 2509 2510
    } else if (pQuery->stableQuery) { // stable aggregate, not interval aggregate or normal column aggregate
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
                               pQuery->current->groupIndex);
H
Haojun Liao 已提交
2511
    }
H
Haojun Liao 已提交
2512 2513

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

H
Haojun Liao 已提交
2516
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2517
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
2518
    qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2519
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2520 2521 2522 2523
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2524
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2525

H
Haojun Liao 已提交
2526
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2527
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2528
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2529 2530 2531 2532 2533 2534
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

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

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2556
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2557
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2558 2559
      qDebug("QInfo:%p data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo, pBlockInfo->window.skey,
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2560
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2561
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2562 2563 2564 2565
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2566
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2567
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2568 2569
      return terrno;
    }
H
Haojun Liao 已提交
2570

H
Haojun Liao 已提交
2571
    doSetFilterColumnInfo(pQuery, pBlock);
H
Haojun Liao 已提交
2572
    if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2573
      filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, pRuntimeEnv->pTsBuf,
H
Haojun Liao 已提交
2574
                            ascQuery);
H
Haojun Liao 已提交
2575
    }
H
Haojun Liao 已提交
2576 2577 2578 2579 2580
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2581
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2582
  int32_t midPos = -1;
H
Haojun Liao 已提交
2583
  int32_t numOfRows;
2584

2585 2586 2587
  if (num <= 0) {
    return -1;
  }
2588

2589
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2590 2591

  TSKEY * keyList = (TSKEY *)pValue;
2592
  int32_t firstPos = 0;
2593
  int32_t lastPos = num - 1;
2594

2595
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2596 2597 2598 2599 2600
    // 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;
2601

H
Haojun Liao 已提交
2602 2603
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2604

H
hjxilinx 已提交
2605 2606 2607 2608 2609 2610 2611 2612
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2613

H
hjxilinx 已提交
2614 2615 2616 2617 2618
  } 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;
2619

H
hjxilinx 已提交
2620 2621 2622 2623 2624 2625 2626
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2627

H
Haojun Liao 已提交
2628
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2629
      midPos = (numOfRows >> 1u) + firstPos;
2630

H
hjxilinx 已提交
2631 2632 2633 2634 2635 2636 2637 2638 2639
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2640

H
hjxilinx 已提交
2641 2642 2643
  return midPos;
}

H
Haojun Liao 已提交
2644 2645 2646 2647 2648 2649
/*
 * 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);
2650

H
Haojun Liao 已提交
2651
  char* val = NULL;
H
Haojun Liao 已提交
2652
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2653
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2654 2655
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2656 2657
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2658

H
Haojun Liao 已提交
2659 2660 2661 2662
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2663

H
Haojun Liao 已提交
2664 2665 2666 2667
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
    tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2668
  }
2669 2670
}

2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
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 已提交
2683
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2684
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2685

H
Haojun Liao 已提交
2686 2687 2688 2689
  SExprInfo *pExpr  = pOperatorInfo->pExpr;
  SQuery    *pQuery = pRuntimeEnv->pQuery;

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

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

2696
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2697
    return;
H
Haojun Liao 已提交
2698 2699 2700 2701
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
H
Haojun Liao 已提交
2702

H
Haojun Liao 已提交
2703 2704 2705 2706 2707 2708 2709 2710 2711
    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 已提交
2712 2713
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type,
                           pLocalExprInfo->bytes);
H
Haojun Liao 已提交
2714 2715 2716 2717

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
2718
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2719 2720 2721 2722 2723
      }

      offset += pLocalExprInfo->bytes;
    }

H
Haojun Liao 已提交
2724
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2725
    if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2726
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2727
    }
H
Haojun Liao 已提交
2728
  }
H
Haojun Liao 已提交
2729

H
Haojun Liao 已提交
2730 2731 2732
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2733 2734
  }
}
2735

2736
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804
  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);
  }
}

2805
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
2806
  SQuery* pQuery = pRuntimeEnv->pQuery;
2807
  int32_t numOfCols = pQuery->numOfOutput;
2808
  printf("super table query intermediate result, total:%d\n", numOfRows);
2809

2810 2811
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2812

H
Haojun Liao 已提交
2813
      switch (pQuery->pExpr1[i].type) {
2814
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2815 2816
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
2817 2818 2819 2820 2821
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2822
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2823 2824
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2825
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2826 2827
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2828
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2829 2830
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2831
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2832 2833 2834 2835 2836 2837 2838
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2839
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2840
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2841
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2842 2843

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2844
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2845 2846 2847
    // 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 已提交
2848
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2849 2850 2851 2852
        return;
      }
    }

H
Haojun Liao 已提交
2853
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2854 2855

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2856
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2857 2858
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2859
        break;
H
Haojun Liao 已提交
2860 2861 2862
      }
    }

H
Haojun Liao 已提交
2863 2864 2865 2866
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2867
    }
H
Haojun Liao 已提交
2868

H
Haojun Liao 已提交
2869 2870
}

2871 2872 2873 2874
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
2875

2876 2877
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
2878

2879 2880
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
2881

H
Haojun Liao 已提交
2882
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
2883
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
2884 2885
}

H
Haojun Liao 已提交
2886 2887
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2888

H
Haojun Liao 已提交
2889
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
2890 2891 2892
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2893

H
Haojun Liao 已提交
2894 2895 2896 2897
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
2898

H
Haojun Liao 已提交
2899 2900 2901 2902
      // 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 已提交
2903

H
Haojun Liao 已提交
2904
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
2905
    }
H
Haojun Liao 已提交
2906 2907
  }
}
H
Haojun Liao 已提交
2908

H
Haojun Liao 已提交
2909 2910 2911
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
2912 2913 2914
  }
}

H
Haojun Liao 已提交
2915 2916 2917 2918 2919 2920
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
2921

H
Haojun Liao 已提交
2922 2923 2924 2925 2926 2927 2928 2929
/*
 * 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 已提交
2930 2931 2932 2933 2934 2935
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 已提交
2936 2937
  int32_t tid = 0;
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
2938

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

H
Haojun Liao 已提交
2942 2943 2944 2945 2946 2947 2948 2949 2950 2951
    /*
     * 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);
2952

H
Haojun Liao 已提交
2953 2954 2955 2956 2957
    // 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;
    }
2958
  }
2959

H
Haojun Liao 已提交
2960
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
2961
}
2962

H
Haojun Liao 已提交
2963 2964 2965
void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) {
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
  SSDataBlock* pDataBlock = pBInfo->pRes;
2966

H
Haojun Liao 已提交
2967 2968 2969 2970 2971 2972 2973
  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;
2974

H
Haojun Liao 已提交
2975 2976 2977 2978 2979
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        pInfo->bufCapacity = newSize;
      } else {
        // longjmp
2980 2981
      }
    }
H
Haojun Liao 已提交
2982
  }
2983

H
Haojun Liao 已提交
2984 2985 2986
  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;
2987

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

H
Haojun Liao 已提交
2996
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
2997 2998 2999 3000
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3001 3002
    }

H
Haojun Liao 已提交
3003
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3004
  }
H
Haojun Liao 已提交
3005
}
3006

H
Haojun Liao 已提交
3007
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3008
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3009
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3010 3011
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3012 3013
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3014 3015
  }
}
3016

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

H
Haojun Liao 已提交
3020 3021 3022 3023
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3024
  }
3025

H
Haojun Liao 已提交
3026 3027 3028 3029
  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3030
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3031

H
Haojun Liao 已提交
3032
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3033
  SWITCH_ORDER(pQuery->order.order);
H
Haojun Liao 已提交
3034 3035

  setupQueryRangeForReverseScan(pRuntimeEnv);
3036 3037
}

H
Haojun Liao 已提交
3038
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3039
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3040
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3041 3042

  int32_t numOfOutput = pOperator->numOfOutput;
H
Haojun Liao 已提交
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery)) {
    // for each group result, call the finalize function for each column
    if (pQuery->groupbyColumn) {
      closeAllResultRows(pResultRowInfo);
    }

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

H
Haojun Liao 已提交
3055
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3056 3057 3058 3059 3060 3061 3062 3063 3064

      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 已提交
3065
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3066 3067 3068 3069 3070 3071 3072 3073 3074
    }

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

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

3079 3080 3081 3082
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3083

3084 3085 3086
  return false;
}

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

H
hjxilinx 已提交
3090 3091
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3092

3093
  pTableQueryInfo->pTable = pTable;
3094
  pTableQueryInfo->cur.vgroupIndex = -1;
3095

H
Haojun Liao 已提交
3096
  // set more initial size of interval/groupby query
3097
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
3098
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3099
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3100 3101 3102
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3103
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3104 3105
  }

3106 3107 3108
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3109
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3110 3111 3112
  if (pTableQueryInfo == NULL) {
    return;
  }
3113

H
Haojun Liao 已提交
3114
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3115
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3116 3117
}

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

H
Haojun Liao 已提交
3123
  int16_t offset = 0;
3124
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3125
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3126 3127 3128

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3129
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3130 3131
      continue;
    }
3132

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

3136
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3137
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3138
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3139
    }
3140

3141
    if (!pResInfo->initialized) {
3142
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3143 3144 3145 3146
    }
  }
}

3147 3148
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3149
  int64_t uid = 0;
H
Haojun Liao 已提交
3150
  SResultRow* pResultRow =
3151
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3152
  assert (pResultRow != NULL);
3153

3154 3155 3156 3157 3158
  /*
   * 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) {
3159 3160
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
    if (ret != TSDB_CODE_SUCCESS) {
3161
      return;
3162 3163 3164
    }
  }

3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
  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);

3180 3181
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3182 3183
}

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

H
Haojun Liao 已提交
3189
  int16_t offset = 0;
3190
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3191 3192
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, page, pResult->offset, offset);
    offset += pCtx[i].outputBytes;
3193

3194 3195 3196
    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;
3197 3198
    }

3199 3200 3201 3202
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3203
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3204 3205 3206
  }
}

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

H
Haojun Liao 已提交
3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
  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) {
      qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%s", pRuntimeEnv->qinfo,
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz);
    } else {
      qDebug("QInfo:%p set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, pRuntimeEnv->qinfo,
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64);
    }
  }
}

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

H
Haojun Liao 已提交
3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268
  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) {
        qError("QInfo:%p failed to find tag:%s in ts_comp", pRuntimeEnv->qinfo, pTag->pz);
      } else {
        qError("QInfo:%p failed to find tag:%" PRId64 " in ts_comp", pRuntimeEnv->qinfo, pTag->i64);
      }

      return -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) {
      qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
    } else {
      qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
      qDebug("QInfo:%p find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
    } else {
      qDebug("QInfo:%p find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", pRuntimeEnv->qinfo, pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
    }
H
Haojun Liao 已提交
3269 3270
  }

H
Haojun Liao 已提交
3271 3272 3273 3274 3275 3276
  return 0;
}

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

H
Haojun Liao 已提交
3277 3278 3279
  int32_t numOfExprs = pQuery->numOfOutput;
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SExprInfo* pExprInfo = &(pExpr[i]);
H
Haojun Liao 已提交
3280
    if (pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3281 3282 3283 3284 3285 3286
      continue;
    }

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3290 3291 3292
    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 已提交
3293
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
H
Haojun Liao 已提交
3294 3295
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3307

3308 3309 3310 3311 3312 3313 3314 3315 3316
/*
 * 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 已提交
3317
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3318 3319 3320
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3321

H
Haojun Liao 已提交
3322 3323 3324
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3325

H
Haojun Liao 已提交
3326 3327
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
3328

H
Haojun Liao 已提交
3329 3330 3331 3332 3333 3334
  /**
   * 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 已提交
3335
  STimeWindow w = TSWINDOW_INITIALIZER;
3336

H
Haojun Liao 已提交
3337 3338 3339
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
3340

H
Haojun Liao 已提交
3341 3342 3343
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
3344
    }
H
Haojun Liao 已提交
3345

H
Haojun Liao 已提交
3346
    pWindowResInfo->prevSKey = w.skey;
3347
  }
H
Haojun Liao 已提交
3348 3349

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3350 3351 3352
}

/**
H
Haojun Liao 已提交
3353
 * copyToOutputBuf support copy data in ascending/descending order
3354 3355 3356 3357 3358 3359 3360
 * 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 已提交
3361

H
Haojun Liao 已提交
3362
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3363 3364 3365
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3366
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391

  int32_t start = 0;
  int32_t step = -1;

  qDebug("QInfo:%p start to copy data from windowResInfo to output buf", pRuntimeEnv->qinfo);
  if (orderType == TSDB_ORDER_ASC) {
    start = pGroupResInfo->index;
    step = 1;
  } else {  // desc order copy all data
    start = numOfRows - pGroupResInfo->index - 1;
    step = -1;
  }

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

    int32_t numOfRowsToCopy = pRow->numOfRows;

    pGroupResInfo->index += 1;

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

    int16_t offset = 0;
H
Haojun Liao 已提交
3394 3395 3396 3397 3398
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, j);
      int32_t bytes = pColInfoData->info.bytes;

      char *out = pColInfoData->pData + numOfResult * bytes;
H
Haojun Liao 已提交
3399
      char *in  = getPosInResultPage(pQuery, page, pRow->offset, offset);
H
Haojun Liao 已提交
3400
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3401 3402

      offset += bytes;
H
Haojun Liao 已提交
3403 3404 3405
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3406
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417
      break;
    }
  }

  qDebug("QInfo:%p copy data to query buf completed", pRuntimeEnv->qinfo);
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3419
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3420
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3421 3422 3423 3424 3425
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3426
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3427 3428 3429

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

H
Haojun Liao 已提交
3430 3431 3432
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3433
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3434
  }
3435 3436
}

H
Haojun Liao 已提交
3437
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv *pRuntimeEnv,
H
Haojun Liao 已提交
3438
    SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
3439
  SQuery *pQuery = pRuntimeEnv->pQuery;
3440

3441
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3442 3443 3444
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
3445

3446 3447
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3448

3449 3450
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3451 3452
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3453
      }
H
Haojun Liao 已提交
3454

H
Haojun Liao 已提交
3455
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3456
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3457 3458 3459 3460 3461
    }
  }
}

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

H
Haojun Liao 已提交
3465
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3466

H
Haojun Liao 已提交
3467
  if (pQuery->pExpr2 == NULL) {
H
Haojun Liao 已提交
3468 3469 3470 3471
    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 已提交
3472 3473 3474
    }
  } else {
    for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3475 3476 3477
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3478
    }
3479
  }
3480

H
Haojun Liao 已提交
3481
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3482 3483
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3484

3485
  int32_t total = 0;
H
Haojun Liao 已提交
3486
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3487

3488
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3489
    STableIdInfo* pDst = (STableIdInfo*)data;
3490 3491 3492 3493
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3494
    data += sizeof(STableIdInfo);
3495 3496 3497
    total++;

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

3501
  qDebug("QInfo:%p set %d subscribe info", pQInfo, total);
H
Haojun Liao 已提交
3502
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3503 3504
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3505
  }
3506 3507
}

H
Haojun Liao 已提交
3508
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3509 3510 3511 3512 3513 3514
  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 已提交
3515
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3516
  tfree(p);
H
Haojun Liao 已提交
3517 3518
  return pOutput->info.rows;
}
3519

H
Haojun Liao 已提交
3520
void queryCostStatis(SQInfo *pQInfo) {
3521
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3522
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3523

H
Haojun Liao 已提交
3524
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3525
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3526 3527
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3528 3529 3530
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3531
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3532 3533 3534 3535 3536 3537 3538
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3539

H
Haojun Liao 已提交
3540 3541 3542
  qDebug("QInfo:%p :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, "
         "load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64,
         pQInfo, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
H
Haojun Liao 已提交
3543
         pSummary->loadBlocks, pSummary->totalRows, pSummary->totalCheckedRows);
3544

3545
  qDebug("QInfo:%p :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo, pSummary->winInfoSize/1024.0,
H
Haojun Liao 已提交
3546
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3547 3548
}

3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580
//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 已提交
3581
//  qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, pRuntimeEnv->qinfo,
3582 3583
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3584

3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599
//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 已提交
3600
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
//      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 已提交
3611
//      qDebug("QInfo:%p skip rows:%d, offset:%" PRId64, pRuntimeEnv->qinfo, blockInfo.rows,
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622
//             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 已提交
3623

3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
//  assert(pQuery->limit.offset == 0);
//  STimeWindow tw = *win;
//  getNextTimeWindow(pQuery, &tw);
//
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
//
//    // load the data block and check data remaining in current data block
//    // TODO optimize performance
//    SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//    SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//    tw = *win;
//    int32_t startPos =
//        getNextQualifiedWindow(pQuery, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
//    assert(startPos >= 0);
//
//    // set the abort info
//    pQuery->pos = startPos;
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
//    pQuery->window.skey = pTableQueryInfo->win.skey;
//    TSKEY key = pTableQueryInfo->win.skey;
//
//    pWindowResInfo->prevSKey = tw.skey;
//    int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
//
//    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//    pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
//
//    qDebug("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
H
Haojun Liao 已提交
3660
//           pRuntimeEnv->qinfo, pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783
//           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;
//}
3784

H
Haojun Liao 已提交
3785 3786
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

B
Bomin Zhang 已提交
3787
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
3788
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
3789 3790
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
Haojun Liao 已提交
3791
  // TODO set the tags scan handle
B
Bomin Zhang 已提交
3792
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
3793
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3794 3795
  }

H
Haojun Liao 已提交
3796
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
3797 3798 3799
  if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3800

B
Bomin Zhang 已提交
3801
  if (!isSTableQuery
H
Haojun Liao 已提交
3802
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3803
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3804
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
3805
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
3806
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
3807
  ) {
H
Haojun Liao 已提交
3808
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3809 3810
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3811
  }
B
Bomin Zhang 已提交
3812

B
Bomin Zhang 已提交
3813
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3814
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
3815
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
3816

H
Haojun Liao 已提交
3817 3818
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
3819
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3820
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3821
    } else {
H
Haojun Liao 已提交
3822
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3823
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3824
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3825

H
Haojun Liao 已提交
3826 3827 3828
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3829

H
Haojun Liao 已提交
3830 3831 3832
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
3833 3834
      }
    }
3835
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
3836
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
3837
  } else {
H
Haojun Liao 已提交
3838
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo, &pQuery->memRef);
H
Haojun Liao 已提交
3839
  }
3840

B
Bomin Zhang 已提交
3841
  return terrno;
B
Bomin Zhang 已提交
3842 3843
}

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

H
Haojun Liao 已提交
3847
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
3848 3849 3850 3851
  if (pFillCol == NULL) {
    return NULL;
  }

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

3855
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
3856
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
3857
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
3858
    pFillCol[i].tagIndex   = -2;
3859 3860
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
3861
    pFillCol[i].fillVal.i  = fillVal[i];
3862

3863 3864
    offset += pExprInfo->bytes;
  }
3865

3866 3867 3868
  return pFillCol;
}

3869
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, SArray* prevResult, void *tsdb, int32_t vgId, bool isSTableQuery) {
3870 3871 3872
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

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

H
Haojun Liao 已提交
3875 3876
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
3877
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
H
Haojun Liao 已提交
3878
  pQuery->stabledev = isStabledev(pQuery);
H
Haojun Liao 已提交
3879

3880
  pRuntimeEnv->prevResult = prevResult;
H
Haojun Liao 已提交
3881
  pRuntimeEnv->qinfo = pQInfo;
3882

3883
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
3884

H
Haojun Liao 已提交
3885
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
3886 3887 3888
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
3889

H
Haojun Liao 已提交
3890
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
3891
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
3892 3893
  pQuery->stableQuery = isSTableQuery;
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);
H
Haojun Liao 已提交
3894
  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);
H
Haojun Liao 已提交
3895

sangshuduo's avatar
sangshuduo 已提交
3896
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
3897 3898

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
3899
  pRuntimeEnv->pTsBuf = pTsBuf;
3900
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
3901
  setResultBufSize(pQuery, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
3902

3903
  if (onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
3904
    pRuntimeEnv->resultInfo.capacity = 4096;
H
Haojun Liao 已提交
3905
    pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
3906 3907
  } else if (pQuery->queryBlockDist) {
    pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
3908
  } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
3909
    pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
3910
  } else if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
3911
    pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
3912
  } else {
H
Haojun Liao 已提交
3913
    pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
3914 3915
  }

H
Haojun Liao 已提交
3916
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
3917 3918
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
3919 3920
  }

3921
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
3922
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize);
3923

H
Haojun Liao 已提交
3924 3925 3926 3927
  int32_t TENMB = 1024*1024*10;
  code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo);
  if (code != TSDB_CODE_SUCCESS) {
    return code;
3928 3929
  }

H
Haojun Liao 已提交
3930
  // create runtime environment
sangshuduo's avatar
sangshuduo 已提交
3931
  int32_t numOfTables = (int32_t)pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
3932
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
3933
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables);
H
Haojun Liao 已提交
3934 3935 3936 3937
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
3938
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
3939
  return TSDB_CODE_SUCCESS;
3940 3941
}

H
Haojun Liao 已提交
3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955
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 已提交
3956
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
3957 3958 3959 3960
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
H
Haojun Liao 已提交
3961
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
3962
      .loadExternalRows = false,
3963 3964
  };

H
Haojun Liao 已提交
3965
  TIME_WINDOW_COPY(cond.twindow, *win);
3966 3967 3968
  return cond;
}

H
Haojun Liao 已提交
3969
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
3970
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
3971
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
3972 3973 3974

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
3975
  tidInfo.key = pTableQueryInfo->lastKey;
3976 3977 3978 3979

  return tidInfo;
}

H
Haojun Liao 已提交
3980 3981 3982
static void updateTableIdInfo(STableQueryInfo* pTableQueryInfo, SHashObj* pTableIdInfo) {
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
3983 3984 3985 3986 3987 3988 3989 3990
  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 已提交
3991 3992 3993 3994
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);
3995

H
Haojun Liao 已提交
3996 3997 3998 3999
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4000 4001
    }
  }
4002 4003
}

H
Haojun Liao 已提交
4004 4005 4006 4007
static SSDataBlock* doTableScanImpl(void* param) {
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4008
  SSDataBlock*     pBlock = &pTableScanInfo->block;
H
Haojun Liao 已提交
4009 4010
  SQuery*          pQuery = pOperator->pRuntimeEnv->pQuery;
  STableGroupInfo* pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4011

H
Haojun Liao 已提交
4012
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4013 4014 4015
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4016

4017
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4018
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4019

4020
    // todo opt
H
Haojun Liao 已提交
4021
    if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4022 4023
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4024 4025 4026 4027 4028 4029 4030 4031
      if (pTableQueryInfo == NULL) {
        break;
      }

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

H
Haojun Liao 已提交
4032
    // this function never returns error?
H
Haojun Liao 已提交
4033
    uint32_t status;
H
Haojun Liao 已提交
4034
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4035
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4036
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4037
    }
H
Haojun Liao 已提交
4038

H
Haojun Liao 已提交
4039
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4040
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4041
      continue;
H
Haojun Liao 已提交
4042 4043 4044 4045
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4046 4047

  return NULL;
H
Haojun Liao 已提交
4048 4049 4050
}

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

H
Haojun Liao 已提交
4053
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4054
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4055
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4056

H
Haojun Liao 已提交
4057 4058
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;

H
Haojun Liao 已提交
4059
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4060
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4061 4062
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4063 4064
    }

H
Haojun Liao 已提交
4065
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4066 4067 4068 4069 4070
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4071
    }
H
Haojun Liao 已提交
4072

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

H
Haojun Liao 已提交
4077
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4078
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4079

H
Haojun Liao 已提交
4080 4081 4082 4083 4084
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

H
Haojun Liao 已提交
4085 4086 4087
    pResultRowInfo->curIndex = 0;
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;

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

H
Haojun Liao 已提交
4092
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4093
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4094

H
Haojun Liao 已提交
4095
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4096
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4097

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

H
Haojun Liao 已提交
4101 4102
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4103 4104
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4105 4106
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4107

H
Haojun Liao 已提交
4108 4109 4110 4111
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4112

H
Haojun Liao 已提交
4113
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4114 4115
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4116 4117
    }
  }
H
Haojun Liao 已提交
4118

H
Haojun Liao 已提交
4119 4120 4121
  return NULL;
}

H
Haojun Liao 已提交
4122 4123
static SSDataBlock* doBlockInfoScan(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4124 4125 4126
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4127 4128 4129 4130

  STableScanInfo *pTableScanInfo = pOperator->info;

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

H
Haojun Liao 已提交
4134
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4135
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4136 4137 4138 4139 4140

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

H
Haojun Liao 已提交
4141 4142 4143 4144 4145 4146
  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 已提交
4147

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

H
Haojun Liao 已提交
4151
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4152

H
Haojun Liao 已提交
4153 4154 4155 4156 4157
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
  pOperator->pRuntimeEnv->pQuery->current = taosArrayGetP(g, 0);

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

H
Haojun Liao 已提交
4160
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4161 4162
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4163 4164
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4165
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4166
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4167 4168
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->current      = 0;
H
Haojun Liao 已提交
4169

H
Haojun Liao 已提交
4170
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4171
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4172
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4173 4174
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4175
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4176
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4177
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4178 4179 4180 4181

  return pOperator;
}

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

H
Haojun Liao 已提交
4185 4186 4187 4188 4189
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
  pInfo->order            = pRuntimeEnv->pQuery->order.order;
  pInfo->current          = 0;
H
Haojun Liao 已提交
4190 4191

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4192 4193
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4194 4195 4196 4197
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4198 4199
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4200

H
Haojun Liao 已提交
4201 4202 4203
  return pOperator;
}

H
Haojun Liao 已提交
4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228
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 已提交
4229 4230 4231
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4232 4233 4234
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4235
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4236
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4237

H
Haojun Liao 已提交
4238 4239 4240
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4241
  } else if (pDownstream->operatorType == OP_TimeInterval) {
H
Haojun Liao 已提交
4242
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4243 4244 4245

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

H
Haojun Liao 已提交
4248
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4249
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4250

H
Haojun Liao 已提交
4251 4252 4253
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4254

H
Haojun Liao 已提交
4255
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4256
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4257

4258 4259
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4260 4261
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4262
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4263
    SArithOperatorInfo *pInfo = pDownstream->info;
4264

H
Haojun Liao 已提交
4265 4266 4267
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4268 4269 4270
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4271 4272
}

H
Haojun Liao 已提交
4273
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4274 4275 4276 4277
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4278
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4279
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4280 4281
  pInfo->current      = 0;
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
H
Haojun Liao 已提交
4282 4283

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4284 4285
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4286
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4287 4288 4289
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4290 4291

  return pOptr;
H
Haojun Liao 已提交
4292 4293
}

H
Haojun Liao 已提交
4294
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4295 4296 4297
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4298
// this is a blocking operator
H
Haojun Liao 已提交
4299
static SSDataBlock* doAggregate(void* param) {
H
Haojun Liao 已提交
4300
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4301
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4302 4303
    return NULL;
  }
H
Haojun Liao 已提交
4304

H
Haojun Liao 已提交
4305
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4306 4307
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4308
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4309

H
Haojun Liao 已提交
4310
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4311
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
4312

H
Haojun Liao 已提交
4313
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4314

H
Haojun Liao 已提交
4315
  while(1) {
H
Haojun Liao 已提交
4316
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4317 4318 4319 4320
    if (pBlock == NULL) {
      break;
    }

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

H
Haojun Liao 已提交
4323
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4324
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4325 4326 4327
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4328
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4329 4330
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4331 4332
  }

H
Haojun Liao 已提交
4333
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4334
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4335

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

H
Haojun Liao 已提交
4339
  return pInfo->pRes;
H
Haojun Liao 已提交
4340 4341
}

H
Haojun Liao 已提交
4342
static SSDataBlock* doSTableAggregate(void* param) {
H
Haojun Liao 已提交
4343
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4344
  if (pOperator->status == OP_EXEC_DONE) {
4345 4346
    return NULL;
  }
H
Haojun Liao 已提交
4347

H
Haojun Liao 已提交
4348
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4349 4350
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4351
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4352

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

H
Haojun Liao 已提交
4356 4357
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4358 4359
    }

H
Haojun Liao 已提交
4360
    return pInfo->pRes;
4361
  }
H
Haojun Liao 已提交
4362

H
Haojun Liao 已提交
4363
  SQuery* pQuery = pRuntimeEnv->pQuery;
4364 4365 4366 4367 4368 4369 4370 4371 4372 4373
  int32_t order = pQuery->order.order;

  SOperatorInfo* upstream = pOperator->upstream;

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

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

H
Haojun Liao 已提交
4376
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4377
      STableScanInfo* pScanInfo = upstream->info;
4378 4379 4380 4381
      order = getTableScanOrder(pScanInfo);
    }

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

4384 4385
    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 已提交
4386
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
4387
  }
H
Haojun Liao 已提交
4388

H
Haojun Liao 已提交
4389 4390
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4391

H
Haojun Liao 已提交
4392
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4393
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4394

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

H
Haojun Liao 已提交
4397 4398 4399
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4400 4401
  }

H
Haojun Liao 已提交
4402
  return pInfo->pRes;
4403 4404 4405 4406 4407
}

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

H
Haojun Liao 已提交
4408 4409
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4410
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4411

H
Haojun Liao 已提交
4412
  pInfo->pRes->info.rows = 0;
H
Haojun Liao 已提交
4413

H
Haojun Liao 已提交
4414
  while(1) {
H
Haojun Liao 已提交
4415
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4416
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4417
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4418
      break;
H
Haojun Liao 已提交
4419 4420
    }

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

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

H
Haojun Liao 已提交
4428
    pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4429 4430
    updateTableIdInfo(pRuntimeEnv->pQuery->current, pRuntimeEnv->pTableRetrieveTsMap);

H
Haojun Liao 已提交
4431
    if (pInfo->pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4432 4433 4434 4435
      break;
    }
  }

H
Haojun Liao 已提交
4436
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4437
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4438 4439 4440 4441
}

static SSDataBlock* doLimit(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4442
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4443
    return NULL;
H
Haojun Liao 已提交
4444 4445
  }

H
Haojun Liao 已提交
4446
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4447

H
Haojun Liao 已提交
4448
  SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4449
  if (pBlock == NULL) {
H
Haojun Liao 已提交
4450
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4451
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4452 4453 4454 4455
    return NULL;
  }

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

H
Haojun Liao 已提交
4458 4459
    pInfo->total = pInfo->limit;

H
Haojun Liao 已提交
4460
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4461
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4462 4463
  } else {
    pInfo->total += pBlock->info.rows;
H
Haojun Liao 已提交
4464 4465 4466 4467 4468
  }

  return pBlock;
}

H
Haojun Liao 已提交
4469
// TODO add log
H
Haojun Liao 已提交
4470 4471
static SSDataBlock* doOffset(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
H
Haojun Liao 已提交
4472
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4473 4474
    return NULL;
  }
H
Haojun Liao 已提交
4475

H
Haojun Liao 已提交
4476
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4477 4478

  while (1) {
H
Haojun Liao 已提交
4479
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4480
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4481
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4482
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4483 4484 4485
      return NULL;
    }

H
Haojun Liao 已提交
4486
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4487
      return pBlock;
H
Haojun Liao 已提交
4488 4489
    } else if (pRuntimeEnv->currentOffset > pBlock->info.rows) {
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4490
    } else {
sangshuduo's avatar
sangshuduo 已提交
4491
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4492 4493 4494 4495 4496 4497
      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 已提交
4498
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4499 4500
      }

H
Haojun Liao 已提交
4501
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4502 4503 4504 4505 4506
      return pBlock;
    }
  }
}

H
Haojun Liao 已提交
4507
static SSDataBlock* doIntervalAgg(void* param) {
H
Haojun Liao 已提交
4508
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4509
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4510 4511 4512
    return NULL;
  }

H
Haojun Liao 已提交
4513
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4514

H
Haojun Liao 已提交
4515
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4516
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4517 4518
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4519
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4520
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4521 4522 4523 4524
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4527
  int32_t order = pQuery->order.order;
4528
  STimeWindow win = pQuery->window;
H
Haojun Liao 已提交
4529

H
Haojun Liao 已提交
4530
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4531 4532 4533 4534 4535 4536 4537 4538

  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 已提交
4539
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
H
Haojun Liao 已提交
4540
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4541 4542
  }

4543 4544 4545 4546
  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

H
Haojun Liao 已提交
4547
  pOperator->status = OP_RES_TO_RETURN;
4548
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4549
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4550
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4551

H
Haojun Liao 已提交
4552
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4553
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4554

H
Haojun Liao 已提交
4555
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4556
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4557 4558
  }

H
Haojun Liao 已提交
4559
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4560 4561
}

H
Haojun Liao 已提交
4562
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
4563
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4564
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4565 4566 4567
    return NULL;
  }

H
Haojun Liao 已提交
4568
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4569
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4570

H
Haojun Liao 已提交
4571
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4572
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4573
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4574
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4575 4576 4577 4578 4579
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
4580 4581 4582
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
4583
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4584 4585

  while(1) {
H
Haojun Liao 已提交
4586
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4587
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4588
      break;
H
Haojun Liao 已提交
4589 4590
    }

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

H
Haojun Liao 已提交
4594
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4595
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
4596
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
4597

H
Haojun Liao 已提交
4598
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
4599
  }
H
Haojun Liao 已提交
4600

H
Haojun Liao 已提交
4601
  pOperator->status = OP_RES_TO_RETURN;
4602 4603
  pQuery->order.order = order;   // TODO : restore the order
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
4604
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4605

H
Haojun Liao 已提交
4606
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4607
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4608
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4609 4610 4611 4612
  }

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

H
Haojun Liao 已提交
4614
static SSDataBlock* hashGroupbyAggregate(void* param) {
H
Haojun Liao 已提交
4615
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4616
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4617 4618 4619
    return NULL;
  }

H
Haojun Liao 已提交
4620
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
4621

H
Haojun Liao 已提交
4622
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4623
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4624
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4625 4626

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

H
Haojun Liao 已提交
4630
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641
  }

  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 已提交
4642
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
H
Haojun Liao 已提交
4643
    setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4644
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
4645
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
4646 4647
    }

H
Haojun Liao 已提交
4648
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
4649 4650
  }

H
Haojun Liao 已提交
4651
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
4652
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4653
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
4654

H
Haojun Liao 已提交
4655
  if (!pRuntimeEnv->pQuery->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
4656 4657 4658
    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);
4659 4660
  }

H
Haojun Liao 已提交
4661
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4662
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4663

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

H
Haojun Liao 已提交
4668
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4669 4670
}

H
Haojun Liao 已提交
4671 4672
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4673
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4674 4675 4676
    return NULL;
  }

H
Haojun Liao 已提交
4677 4678
  SFillOperatorInfo *pInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4679

H
Haojun Liao 已提交
4680
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
sangshuduo's avatar
sangshuduo 已提交
4681
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4682 4683 4684 4685 4686 4687
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4688
      if (pInfo->totalInputRows == 0) {
H
Haojun Liao 已提交
4689
        pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4690 4691 4692
        return NULL;
      }

H
Haojun Liao 已提交
4693
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
H
Haojun Liao 已提交
4694
    } else {
H
Haojun Liao 已提交
4695 4696
      pInfo->totalInputRows += pBlock->info.rows;

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

H
Haojun Liao 已提交
4699 4700
      taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
H
Haojun Liao 已提交
4701 4702
    }

H
Haojun Liao 已提交
4703
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4704
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4705 4706
  }
}
H
Haojun Liao 已提交
4707

H
Haojun Liao 已提交
4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719
// 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 已提交
4720 4721 4722 4723 4724
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
4725
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
4726
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
4727 4728
  }

H
Haojun Liao 已提交
4729
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
4730
  tfree(pOperator->info);
H
Haojun Liao 已提交
4731 4732 4733
  tfree(pOperator);
}

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

H
Haojun Liao 已提交
4737 4738 4739 4740
  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 已提交
4741
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
4742

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

H
Haojun Liao 已提交
4745
  pInfo->seed = rand();
H
Haojun Liao 已提交
4746
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed);
H
Haojun Liao 已提交
4747

H
Haojun Liao 已提交
4748
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4749
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
4750
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
4751
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4752
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4753
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4754
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4755 4756 4757
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
4758

H
Haojun Liao 已提交
4759 4760
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
4761 4762 4763
  return pOperator;
}

H
Haojun Liao 已提交
4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780
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 已提交
4781
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
4782 4783 4784 4785
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
4786
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
4787
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
4788
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
4789 4790 4791 4792 4793 4794 4795
}

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

H
Haojun Liao 已提交
4796 4797 4798 4799 4800
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

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

H
Haojun Liao 已提交
4804
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
4805

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

4810
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4811 4812
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
4813
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4814
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4815
  pOperator->info         = pInfo;
4816
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4817 4818 4819
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4820

H
Haojun Liao 已提交
4821 4822 4823
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
4824
  return pOperator;
H
Haojun Liao 已提交
4825 4826
}

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

H
Haojun Liao 已提交
4830
  pInfo->seed = rand();
H
Haojun Liao 已提交
4831
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
4832

H
Haojun Liao 已提交
4833
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
4834
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
4835 4836 4837
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
4838
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed);
H
Haojun Liao 已提交
4839 4840

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4841 4842
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
4843
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4844
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4845
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4846
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4847 4848 4849
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
4850

H
Haojun Liao 已提交
4851 4852 4853
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
4854 4855 4856
  return pOperator;
}

H
Haojun Liao 已提交
4857
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
4858 4859 4860 4861 4862
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;

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

H
Haojun Liao 已提交
4863 4864
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
4865
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4866
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4867
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4868
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
4869 4870
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4871 4872 4873 4874

  return pOperator;
}

H
Haojun Liao 已提交
4875
SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
4876 4877 4878 4879 4880
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

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

H
Haojun Liao 已提交
4881 4882
  pOperator->name         = "OffsetOperator";
  pOperator->operatorType = OP_Offset;
H
Haojun Liao 已提交
4883
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4884
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4885
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4886
  pOperator->exec         = doOffset;
H
Haojun Liao 已提交
4887 4888
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4889 4890 4891 4892

  return pOperator;
}

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

H
Haojun Liao 已提交
4896
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4897
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4898
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
4899 4900 4901

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

H
Haojun Liao 已提交
4902 4903
  pOperator->name         = "TimeIntervalAggOperator";
  pOperator->operatorType = OP_TimeInterval;
H
Haojun Liao 已提交
4904
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4905
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4906
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4907 4908 4909 4910
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4911
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
4912 4913
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
4914 4915 4916
  return pOperator;
}

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

H
Haojun Liao 已提交
4920
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4921
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4922
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
4923 4924

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4925 4926
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
4927
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4928
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4929
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4930 4931
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
4932 4933
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4934

H
Haojun Liao 已提交
4935 4936 4937
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
4938 4939 4940
  return pOperator;
}

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

H
Haojun Liao 已提交
4945
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
4946
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4947
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
4948 4949

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4950
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
4951
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4952 4953
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
4954
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4955 4956 4957 4958
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4959
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
4960 4961
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
4962 4963
  return pOperator;
}
H
Haojun Liao 已提交
4964

H
Haojun Liao 已提交
4965
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
H
Haojun Liao 已提交
4966
    int32_t numOfOutput) {
H
Haojun Liao 已提交
4967
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982
  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 已提交
4983 4984 4985

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

H
Haojun Liao 已提交
4986
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
4987
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4988 4989 4990
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
4991
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4992 4993 4994 4995
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4996

H
Haojun Liao 已提交
4997 4998 4999
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5000 5001 5002
  return pOperator;
}

5003 5004
static SSDataBlock* doTagScan(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5005
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5006 5007
    return NULL;
  }
5008

H
Haojun Liao 已提交
5009
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5010

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

H
Haojun Liao 已提交
5013 5014
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
5015 5016

  int32_t count = 0;
H
Haojun Liao 已提交
5017 5018 5019 5020 5021
  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;
5022 5023 5024 5025
    assert(pQuery->numOfOutput == 1);

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
    int32_t rsize = pExprInfo->bytes;
H
Haojun Liao 已提交
5026

5027 5028 5029
    count = 0;

    int16_t bytes = pExprInfo->bytes;
H
Haojun Liao 已提交
5030
    int16_t type  = pExprInfo->type;
5031 5032 5033 5034 5035 5036 5037 5038 5039

    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 已提交
5040 5041 5042 5043
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5046
      char *output = pColInfo->pData + count * rsize;
5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063
      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 已提交
5064
      char* data = NULL;
5065
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5066
        data = tsdbGetTableName(item->pTable);
5067
      } else {
H
Haojun Liao 已提交
5068
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5069 5070
      }

H
Haojun Liao 已提交
5071
      doSetTagValueToResultBuf(output, data, type, bytes);
5072 5073 5074 5075
      count += 1;
    }

    qDebug("QInfo:%p create (tableId, tag) info completed, rows:%d", pRuntimeEnv->qinfo, count);
H
Haojun Liao 已提交
5076 5077 5078
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5079
    count = 1;
H
Haojun Liao 已提交
5080 5081

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

H
Haojun Liao 已提交
5086 5087 5088
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099

      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 已提交
5100
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5101 5102
        type  = pExprInfo[j].type;
        bytes = pExprInfo[j].bytes;
5103 5104 5105 5106 5107 5108 5109

        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 已提交
5110
        dst  = pColInfo->pData + count * pExprInfo[j].bytes;
5111 5112
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5113

5114 5115 5116
      count += 1;
    }

H
Haojun Liao 已提交
5117 5118 5119 5120
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

5121 5122 5123
    qDebug("QInfo:%p create tag values results completed, rows:%d", pRuntimeEnv->qinfo, count);
  }

H
Haojun Liao 已提交
5124
  pRes->info.rows = count;
H
Haojun Liao 已提交
5125
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5126 5127
}

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

H
Haojun Liao 已提交
5132 5133 5134 5135 5136 5137
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5138
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5139
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5140
  pOperator->operatorType = OP_TagScan;
5141
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5142
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5143 5144
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5145 5146
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5147
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5148
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5149

5150 5151
  return pOperator;
}
H
Haojun Liao 已提交
5152

5153
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
5154
  int32_t j = 0;
5155

5156
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
5157
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5158
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
5159 5160
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5161
    }
Y
yihaoDeng 已提交
5162
    
H
Haojun Liao 已提交
5163

5164 5165 5166 5167
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
5168

5169 5170
      j += 1;
    }
5171

Y
TD-1230  
yihaoDeng 已提交
5172
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5173
    return TSDB_UD_COLUMN_INDEX;
5174 5175 5176 5177 5178
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
5179

5180
      j += 1;
5181 5182
    }
  }
5183 5184

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5185 5186
}

5187 5188
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
5189
  return j != INT32_MIN;
5190 5191
}

5192
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5193 5194
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5195
    return false;
5196 5197
  }

H
hjxilinx 已提交
5198
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5199
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5200
    return false;
5201 5202
  }

H
hjxilinx 已提交
5203
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5204
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5205
    return false;
5206 5207
  }

5208 5209
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5210
    return false;
5211 5212
  }

5213 5214 5215
  return true;
}

5216
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5217 5218 5219 5220
  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;
5221 5222 5223
  }

  if (numOfTotal == 0) {
5224
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
5225 5226 5227 5228
      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 已提交
5229 5230
          (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (pFuncMsg->functionId == TSDB_FUNC_BLKINFO)) {
5231
        continue;
5232
      }
5233

5234
      return false;
5235 5236
    }
  }
5237

5238 5239 5240 5241 5242 5243
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5244
  return true;
5245 5246
}

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

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

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

5255
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5256 5257
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5258

H
hjxilinx 已提交
5259 5260 5261
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5262

H
hjxilinx 已提交
5263 5264
  return pMsg;
}
5265

5266
/**
H
hjxilinx 已提交
5267
 * pQueryMsg->head has been converted before this function is called.
5268
 *
H
hjxilinx 已提交
5269
 * @param pQueryMsg
5270 5271 5272 5273
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5274
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5275 5276
  int32_t code = TSDB_CODE_SUCCESS;

5277 5278 5279 5280
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5281 5282 5283 5284
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5285 5286 5287
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5288 5289
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5290
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5291

5292 5293
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5294
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5295
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5296 5297

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5298
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5299
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5300 5301 5302
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
5303
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
5304
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
5305
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5306
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5307
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5308
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5309
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5310

5311
  // query msg safety check
5312
  if (!validateQueryMsg(pQueryMsg)) {
5313 5314
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5315 5316
  }

H
hjxilinx 已提交
5317 5318
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
5319 5320
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
5321
    pColInfo->colId = htons(pColInfo->colId);
5322
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
5323 5324
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
5325

5326 5327 5328 5329 5330
    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;
    }
5331

H
hjxilinx 已提交
5332
    int32_t numOfFilters = pColInfo->numOfFilters;
5333
    if (numOfFilters > 0) {
H
hjxilinx 已提交
5334
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
5335 5336 5337 5338
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
5339 5340 5341
    }

    for (int32_t f = 0; f < numOfFilters; ++f) {
5342
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pMsg;
5343

5344 5345
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
5346 5347 5348

      pMsg += sizeof(SColumnFilterInfo);

5349 5350
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
5351

5352
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
5353 5354 5355 5356 5357
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

5358
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
5359
        pMsg += (pColFilter->len + 1);
5360
      } else {
5361 5362
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
5363 5364
      }

5365 5366
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
5367 5368 5369
    }
  }

5370 5371
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
5372 5373 5374 5375
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

5376
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
5377

5378
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5379
    param->pExprMsg[i] = pExprMsg;
5380

5381
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
5382
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5383
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5384 5385 5386
    pExprMsg->colType       = htons(pExprMsg->colType);
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5387 5388 5389
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
5390

5391
    pMsg += sizeof(SSqlFuncMsg);
5392 5393

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
5394
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
5395 5396 5397 5398
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
5399
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
5400 5401 5402 5403 5404
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
5405 5406
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
5407
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
5408 5409
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
5410 5411 5412
      }
    }

5413
    pExprMsg = (SSqlFuncMsg *)pMsg;
5414
  }
5415

H
Haojun Liao 已提交
5416 5417
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
5418
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
5419

H
Haojun Liao 已提交
5420
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
5421
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
5422 5423 5424

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5425
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5426 5427 5428
      pExprMsg->colType       = htons(pExprMsg->colType);
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457
      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;
    }
  }

5458
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
5459

H
hjxilinx 已提交
5460
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
5461 5462
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
5463 5464 5465
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5466 5467

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

5471 5472
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
5473

5474 5475
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
5476

5477 5478
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
5479
    }
5480

H
hjxilinx 已提交
5481 5482
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
5483 5484
  }

5485 5486
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
5487
    pQueryMsg->fillVal = (uint64_t)(pMsg);
5488 5489

    int64_t *v = (int64_t *)pMsg;
5490
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5491 5492
      v[i] = htobe64(v[i]);
    }
5493

5494
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
5495
  }
5496

5497
  if (pQueryMsg->numOfTags > 0) {
5498 5499
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
5500 5501 5502 5503
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5504 5505
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
5506

5507 5508 5509 5510
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
5511

5512
      param->pTagColumnInfo[i] = *pTagCol;
5513
      pMsg += sizeof(SColumnInfo);
5514
    }
H
hjxilinx 已提交
5515
  }
5516

5517 5518
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
5519 5520
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
5521 5522 5523
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5524 5525

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
5526 5527
    pMsg += pQueryMsg->tagCondLen;
  }
5528

5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539
  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 已提交
5540
  if (pQueryMsg->tbnameCondLen > 0) {
5541 5542
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
5543 5544 5545 5546
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5547
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5548
    pMsg += pQueryMsg->tbnameCondLen;
5549 5550
  }

D
dapan1121 已提交
5551 5552 5553 5554 5555
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

5556
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
5557

5558
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
5559 5560
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
5561
  }
5562

5563
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
5564 5565
         "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,
5566
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
5567
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
5568

5569
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
5570
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
5571 5572

_cleanup:
5573
  freeParam(param);
5574
  return code;
5575 5576
}

H
Haojun Liao 已提交
5577 5578
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
5579 5580

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
5581
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
5582 5583 5584
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
5585
    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 已提交
5586 5587 5588
    return code;
  } END_TRY

H
hjxilinx 已提交
5589
  if (pExprNode == NULL) {
5590
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
5591
    return TSDB_CODE_QRY_APP_ERROR;
5592
  }
5593

5594
  pArithExprInfo->pExpr = pExprNode;
5595 5596 5597
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5598
static int32_t updateOutputBufForTopBotQuery(SQueryTableMsg* pQueryMsg, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617
  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 已提交
5618
// TODO tag length should be passed from client
H
Haojun Liao 已提交
5619 5620
int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                   SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5621
  *pExprInfo = NULL;
H
hjxilinx 已提交
5622
  int32_t code = TSDB_CODE_SUCCESS;
5623

H
Haojun Liao 已提交
5624
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
5625
  if (pExprs == NULL) {
5626
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
5627 5628 5629 5630 5631
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
5632
  for (int32_t i = 0; i < numOfOutput; ++i) {
5633
    pExprs[i].base = *pExprMsg[i];
5634
    pExprs[i].bytes = 0;
5635 5636 5637 5638

    int16_t type = 0;
    int16_t bytes = 0;

5639
    // parse the arithmetic expression
5640
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
5641
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
5642

5643
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5644
        tfree(pExprs);
5645
        return code;
5646 5647
      }

5648
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
5649
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
5650
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
5651 5652 5653
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
5654 5655 5656 5657
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
5658 5659
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
5660 5661
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

5662 5663
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
5664 5665 5666 5667 5668

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
5669
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
5670
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
5671
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
5672 5673 5674 5675 5676 5677 5678
          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 已提交
5679

dengyihao's avatar
dengyihao 已提交
5680
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
5681 5682 5683 5684
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
5685
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
5686

5687 5688
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
5689
      }
5690 5691
    }

S
TD-1057  
Shengliang Guan 已提交
5692
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
H
Haojun Liao 已提交
5693 5694
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
5695 5696 5697 5698
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

5699
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
5700
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5701
      tfree(pExprs);
5702
      return TSDB_CODE_QRY_INVALID_MSG;
5703 5704
    }

5705
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
5706
      tagLen += pExprs[i].bytes;
5707
    }
5708

5709
    assert(isValidDataType(pExprs[i].type));
5710 5711
  }

H
Haojun Liao 已提交
5712 5713
  // the tag length is affected by other tag columns, so this should be update.
  updateOutputBufForTopBotQuery(pQueryMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
5714

5715
  *pExprInfo = pExprs;
5716 5717 5718
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5719 5720 5721 5722 5723 5724 5725 5726 5727 5728
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 已提交
5729
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752

  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 已提交
5753 5754
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770
    }

    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 已提交
5771
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
5772 5773 5774 5775 5776
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
5777
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
5778
  if (pGroupbyExpr == NULL) {
5779
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
5780 5781 5782 5783 5784 5785 5786
    return NULL;
  }

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

5787 5788 5789 5790
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
5791

5792 5793 5794
  return pGroupbyExpr;
}

5795
static int32_t createFilterInfo(void *pQInfo, SQuery *pQuery) {
5796
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
5797
    if (pQuery->colList[i].numOfFilters > 0) {
5798 5799 5800 5801 5802 5803 5804 5805 5806
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
5807 5808 5809
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
5810 5811

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
5812
    if (pQuery->colList[i].numOfFilters > 0) {
5813 5814
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
5815
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
5816
      pFilterInfo->info = pQuery->colList[i];
5817

5818
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
5819
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
5820 5821 5822
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
5823 5824 5825

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
5826
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
5827 5828 5829 5830

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
S
slguan 已提交
5831
          qError("QInfo:%p invalid filter info", pQInfo);
5832
          return TSDB_CODE_QRY_INVALID_MSG;
5833 5834
        }

5835 5836 5837
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
          qError("QInfo:%p invalid filter info", pQInfo);
5838
          return TSDB_CODE_QRY_INVALID_MSG;
5839 5840
        }

5841
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
5842 5843 5844 5845 5846 5847 5848 5849 5850
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

5851
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
5852
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
5853

5854
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
5855
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
5856
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
5857 5858
      continue;
    }
5859

5860
    // todo opt performance
H
Haojun Liao 已提交
5861
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
5862
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
5863 5864
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
5865 5866
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
5867 5868 5869
          break;
        }
      }
H
Haojun Liao 已提交
5870 5871

      assert(f < pQuery->numOfCols);
5872 5873
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
5874 5875 5876
    } 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);
5877
    } else {
5878 5879
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
5880 5881
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
5882 5883
          break;
        }
5884
      }
5885

Y
yihaoDeng 已提交
5886
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
5887 5888 5889 5890
    }
  }
}

H
Haojun Liao 已提交
5891 5892 5893 5894 5895 5896 5897 5898
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 已提交
5899

5900
  if (isProjQuery(pQuery)) {
H
Haojun Liao 已提交
5901 5902 5903
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQuery->resultRowSize;
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
5904
    }
H
Haojun Liao 已提交
5905

H
Haojun Liao 已提交
5906
    pResultInfo->capacity  = numOfRes;
5907
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
5908
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
5909
  }
H
Haojun Liao 已提交
5910 5911 5912

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

H
Haojun Liao 已提交
5915 5916 5917
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery,
                        char* sql) {
B
Bomin Zhang 已提交
5918 5919 5920
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

5921 5922
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
5923
    goto _cleanup_qinfo;
5924
  }
5925

B
Bomin Zhang 已提交
5926 5927
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
5928
  SQuery* pQuery = &pQInfo->query;
5929 5930
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
5931
  pQuery->tableGroupInfo  = *pTableGroupInfo;
5932
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
5933
  pQuery->numOfOutput     = numOfOutput;
5934 5935 5936
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
5937
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
5938
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
5939 5940
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
5941
  pQuery->pGroupbyExpr    = pGroupbyExpr;
5942
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
5943
  pQuery->fillType        = pQueryMsg->fillType;
5944
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
5945
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
5946 5947
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
H
Haojun Liao 已提交
5948

5949
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
5950
  if (pQuery->colList == NULL) {
5951
    goto _cleanup;
5952
  }
5953

5954 5955
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
5956
  for (int16_t i = 0; i < numOfCols; ++i) {
5957
    pQuery->colList[i] = pQueryMsg->colList[i];
5958
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
5959 5960 5961 5962 5963

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
5964
  }
5965

5966
  // calculate the result row size
5967 5968
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
5969 5970 5971 5972 5973 5974
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
5975
  }
5976

5977
  doUpdateExprColumnIndex(pQuery);
5978
  int32_t ret = createFilterInfo(pQInfo, pQuery);
5979
  if (ret != TSDB_CODE_SUCCESS) {
5980
    goto _cleanup;
5981 5982
  }

5983
  if (pQuery->fillType != TSDB_FILL_NONE) {
5984 5985
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
5986
      goto _cleanup;
5987 5988 5989
    }

    // the first column is the timestamp
5990
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
5991 5992
  }

dengyihao's avatar
dengyihao 已提交
5993 5994 5995
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
5996
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
5997

5998 5999 6000
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6001
  }
H
Haojun Liao 已提交
6002

H
Haojun Liao 已提交
6003
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6004 6005 6006 6007
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6008
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6009
  pQInfo->rspContext = NULL;
6010
  pQInfo->sql = sql;
6011
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6012
  tsem_init(&pQInfo->ready, 0, 0);
6013 6014 6015 6016

  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
6017 6018
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
  pQuery->queryWindowIdentical = true;
6019 6020
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

6021
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
6022

H
Haojun Liao 已提交
6023
  int32_t index = 0;
H
hjxilinx 已提交
6024
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6025
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
6026

H
Haojun Liao 已提交
6027
    size_t s = taosArrayGetSize(pa);
6028
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6029 6030 6031
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6032

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

H
hjxilinx 已提交
6035
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6036
      STableKeyInfo* info = taosArrayGet(pa, j);
6037

6038
      window.skey = info->lastKey;
6039
      if (info->lastKey != pQuery->window.skey) {
H
Haojun Liao 已提交
6040
        pQInfo->query.queryWindowIdentical = false;
6041 6042 6043
      }

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
6044
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
6045 6046 6047
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6048

6049
      item->groupIndex = i;
H
hjxilinx 已提交
6050
      taosArrayPush(p1, &item);
6051 6052

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6053
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6054
      index += 1;
H
hjxilinx 已提交
6055 6056
    }
  }
6057

H
Haojun Liao 已提交
6058
  colIdCheck(pQuery, pQInfo);
6059

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

6063
  qDebug("qmsg:%p QInfo:%p created", pQueryMsg, pQInfo);
6064 6065
  return pQInfo;

B
Bomin Zhang 已提交
6066
_cleanup_qinfo:
H
Haojun Liao 已提交
6067
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6068

6069 6070 6071 6072
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6073

S
TD-1848  
Shengliang Guan 已提交
6074
  tfree(pTagCols);
B
Bomin Zhang 已提交
6075 6076 6077
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6078 6079
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6080 6081
    }
  }
H
Haojun Liao 已提交
6082

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

6085
_cleanup:
dengyihao's avatar
dengyihao 已提交
6086
  freeQInfo(pQInfo);
6087 6088 6089
  return NULL;
}

H
Haojun Liao 已提交
6090
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6091 6092 6093 6094
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6095

H
hjxilinx 已提交
6096 6097 6098 6099
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6100
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6101 6102 6103
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6104
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
6105
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6106 6107

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6108
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6109

6110
  STSBuf *pTsBuf = NULL;
6111
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
6112
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
6113
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
6114

6115 6116
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
6117

dengyihao's avatar
dengyihao 已提交
6118
    UNUSED(ret);
H
hjxilinx 已提交
6119
  }
6120

6121 6122 6123 6124 6125
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
  }

Y
TD-1665  
yihaoDeng 已提交
6126
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
6127

6128 6129
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
6130
    qDebug("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey,
6131
           pQuery->window.ekey, pQuery->order.order);
H
Haojun Liao 已提交
6132
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6133
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6134
    // todo free memory
6135 6136
    return TSDB_CODE_SUCCESS;
  }
6137

H
Haojun Liao 已提交
6138
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
6139
    qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo);
H
Haojun Liao 已提交
6140
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6141 6142
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6143 6144

  // filter the qualified
6145
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6146 6147
    goto _error;
  }
6148

H
hjxilinx 已提交
6149 6150 6151 6152
  return code;

_error:
  // table query ref will be decrease during error handling
6153
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6154 6155 6156
  return code;
}

H
Haojun Liao 已提交
6157
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6158
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6159 6160
      return;
    }
H
Haojun Liao 已提交
6161

B
Bomin Zhang 已提交
6162 6163 6164 6165 6166
    for (int32_t i = 0; i < numOfFilters; i++) {
      if (pFilter[i].filterstr) {
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6167

B
Bomin Zhang 已提交
6168 6169 6170
    free(pFilter);
}

H
Haojun Liao 已提交
6171 6172
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6173
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194
    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 已提交
6195 6196 6197 6198 6199 6200 6201 6202
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 已提交
6203
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6204 6205 6206 6207 6208 6209 6210
    }
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6211
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6212 6213 6214
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6215

6216
  qDebug("QInfo:%p start to free QInfo", pQInfo);
6217

H
Haojun Liao 已提交
6218
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6219
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
6220
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6221

H
Haojun Liao 已提交
6222 6223 6224
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
6225
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
6226
    }
6227

H
Haojun Liao 已提交
6228 6229 6230
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
6231
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
6232
      }
H
hjxilinx 已提交
6233
    }
6234

H
Haojun Liao 已提交
6235 6236
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
6237

S
TD-1848  
Shengliang Guan 已提交
6238 6239
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
6240 6241 6242 6243 6244 6245

    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 已提交
6246
      tfree(pQuery->colList);
H
Haojun Liao 已提交
6247 6248
    }

H
Haojun Liao 已提交
6249 6250 6251 6252
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
6253
  }
6254

H
Haojun Liao 已提交
6255
  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
H
Haojun Liao 已提交
6256

S
TD-1848  
Shengliang Guan 已提交
6257
  tfree(pQInfo->pBuf);
6258 6259
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
6260
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
6261

H
Haojun Liao 已提交
6262
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
6263
  pQInfo->signature = 0;
6264

6265
  qDebug("QInfo:%p QInfo is freed", pQInfo);
6266

S
TD-1848  
Shengliang Guan 已提交
6267
  tfree(pQInfo);
H
hjxilinx 已提交
6268 6269
}

H
Haojun Liao 已提交
6270
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
6271
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
6272
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
hjxilinx 已提交
6273
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6274

H
hjxilinx 已提交
6275
  // load data from file to msg buffer
H
Haojun Liao 已提交
6276
  if (isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
6277 6278
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
6279

H
hjxilinx 已提交
6280
    // make sure file exist
D
fix bug  
dapan1121 已提交
6281 6282
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
6283
      assert(s == pRuntimeEnv->outputBuf->info.rows);
6284

D
fix bug  
dapan1121 已提交
6285
      qDebug("QInfo:%p ts comp data return, file:%p, size:%"PRId64, pQInfo, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
6286 6287
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
6288
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
6289
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
6290 6291
          assert(0);
        }
H
Haojun Liao 已提交
6292
      } else {
6293
        UNUSED(s);
D
dapan1121 已提交
6294 6295 6296 6297
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
6298
      // dump error info
D
dapan1121 已提交
6299 6300 6301
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
6302
      }
H
Haojun Liao 已提交
6303

D
fix bug  
dapan1121 已提交
6304
      fclose(f);
H
hjxilinx 已提交
6305
    }
6306

H
hjxilinx 已提交
6307
    // all data returned, set query over
H
Haojun Liao 已提交
6308 6309
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
6310
    }
H
hjxilinx 已提交
6311
  } else {
H
Haojun Liao 已提交
6312
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
6313
  }
6314

H
Haojun Liao 已提交
6315 6316 6317
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
  qDebug("QInfo:%p current numOfRes rows:%d, total:%" PRId64, pQInfo,
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
6318

H
Haojun Liao 已提交
6319
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) {
6320
    qDebug("QInfo:%p results limitation reached, limitation:%"PRId64, pQInfo, pQuery->limit.limit);
H
Haojun Liao 已提交
6321
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
6322
  }
6323

H
hjxilinx 已提交
6324
  return TSDB_CODE_SUCCESS;
6325 6326
}

H
Haojun Liao 已提交
6327
bool doBuildResCheck(SQInfo* pQInfo) {
6328 6329 6330 6331 6332
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
6333
  buildRes = needBuildResAfterQueryComplete(pQInfo);
6334

H
Haojun Liao 已提交
6335 6336
  // 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 已提交
6337
  assert(pQInfo->owner == taosGetSelfPthreadId());
6338
  pQInfo->owner = 0;
H
Haojun Liao 已提交
6339

H
Haojun Liao 已提交
6340
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
6341

6342
  // used in retrieve blocking model.
H
Haojun Liao 已提交
6343
  tsem_post(&pQInfo->ready);
6344 6345 6346
  return buildRes;
}

H
Haojun Liao 已提交
6347 6348 6349 6350
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
6351 6352
  }

6353
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
6354
    memcpy(output, val, varDataTLen(val));
6355
  } else {
H
Haojun Liao 已提交
6356
    memcpy(output, val, bytes);
6357 6358 6359
  }
}

H
Haojun Liao 已提交
6360
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
6361 6362 6363 6364
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
6365
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
6366 6367
}

H
Haojun Liao 已提交
6368
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
6369
  int64_t t = getQuerySupportBufSize(numOfTables);
6370
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6371
    return TSDB_CODE_SUCCESS;
6372
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
6373 6374

    while(1) {
6375
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
6376 6377
      int64_t remain = s - t;
      if (remain >= 0) {
6378
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390
          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 已提交
6391
void releaseQueryBuf(size_t numOfTables) {
6392
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6393 6394 6395 6396 6397 6398
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
6399
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
6400
}