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

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

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
83 84 85 86 87 88 89 90 91
static UNUSED_FUNC void* u_realloc(void* p, size_t __size) {
  uint32_t v = rand();
  if (v % 5 <= 1) {
    return NULL;
  } else {
    return realloc(p, __size);
  }
}

H
Haojun Liao 已提交
92
#define calloc  u_calloc
H
Haojun Liao 已提交
93
#define malloc  u_malloc
H
Haojun Liao 已提交
94
#define realloc u_realloc
H
Haojun Liao 已提交
95
#endif
H
Haojun Liao 已提交
96

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

101

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

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

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

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

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

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

S
Shengliang Guan 已提交
133
  mon = (int)(mon + interval);
134 135 136 137 138 139 140 141 142 143 144
  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 已提交
145
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
146
static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
147
    int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
148

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
185 186 187 188
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 已提交
189
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
190
static void destroyOperatorInfo(SOperatorInfo* pOperator);
H
Haojun Liao 已提交
191

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

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

H
Haojun Liao 已提交
197 198
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 已提交
199
static bool isPointInterpoQuery(SQuery *pQuery);
H
Haojun Liao 已提交
200 201 202
static void setResultBufSize(SQuery* pQuery, SRspResultInfo* pResultInfo);
static void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable);
static void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr);
D
fix bug  
dapan1121 已提交
203
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
204 205 206
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
207

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

H
Haojun Liao 已提交
212
  SSDataBlock *res = calloc(1, sizeof(SSDataBlock));
H
Haojun Liao 已提交
213
  res->info.numOfCols = numOfOutput;
H
Haojun Liao 已提交
214

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

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

  return res;
H
Haojun Liao 已提交
227 228
}

H
Haojun Liao 已提交
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
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 已提交
246
int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
247 248 249
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);

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

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

H
Haojun Liao 已提交
279
static bool isGroupbyColumn(SSqlGroupbyExpr *pGroupbyExpr) {
280 281 282
  if (pGroupbyExpr == NULL || pGroupbyExpr->numOfGroupCols == 0) {
    return false;
  }
283

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

292 293 294
      return true;
    }
  }
295

296 297 298
  return false;
}

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

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

  return true;
}

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

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

349 350 351 352
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
      return true;
    }
  }
353

354 355 356
  return false;
}

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

  return false;
}

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

      // 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 已提交
386 387 388 389 390 391 392 393 394 395 396 397
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;
}

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

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

453
  if (!existed) {
454
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
455

456 457 458 459 460 461 462 463 464 465 466 467 468
    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;
469
    }
H
Haojun Liao 已提交
470

471
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
472
    pResultRowInfo->curIndex = pResultRowInfo->size++;
473
  }
474

475
  // too many time window in query
H
Haojun Liao 已提交
476
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
477 478 479
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
480
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
481 482
}

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
static void getInitialStartTimeWindow(SQuery* pQuery, TSKEY ts, STimeWindow* w) {
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    getAlignQueryTimeWindow(pQuery, ts, ts, pQuery->window.ekey, w);
  } else {
    // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
    getAlignQueryTimeWindow(pQuery, ts, pQuery->window.ekey, ts, w);

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

      if (key >= ts) {
        break;
      }

      w->skey = key;
    }
  }
}

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

H
Haojun Liao 已提交
511
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
512 513 514 515 516 517
    if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
      getInitialStartTimeWindow(pQuery, ts, &w);
      pResultRowInfo->prevSKey = w.skey;
    } else {
      w.skey = pResultRowInfo->prevSKey;
    }
H
Haojun Liao 已提交
518

519
    if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') {
520
      w.ekey = taosTimeAdd(w.skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1;
521
    } else {
522
      w.ekey = w.skey + pQuery->interval.interval - 1;
523
    }
524
  } else {
H
Haojun Liao 已提交
525 526
    int32_t slot = curTimeWindowIndex(pResultRowInfo);
    SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot);
527
    w = pWindowRes->win;
528
  }
529

530
  if (w.skey > ts || w.ekey < ts) {
531 532 533
    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;
534 535
    } else {
      int64_t st = w.skey;
536

537
      if (st > ts) {
538
        st -= ((st - ts + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
539
      }
540

541
      int64_t et = st + pQuery->interval.interval - 1;
542
      if (et < ts) {
543
        st += ((ts - et + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding;
544
      }
545

546
      w.skey = st;
547
      w.ekey = w.skey + pQuery->interval.interval - 1;
548
    }
549
  }
550

551 552 553 554 555 556 557
  /*
   * 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;
  }
558

559 560 561
  return w;
}

H
Haojun Liao 已提交
562 563
// 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) {
564
  if (pWindowRes->pageId != -1) {
565 566
    return 0;
  }
567

568
  tFilePage *pData = NULL;
569

570 571
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
572
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
573

H
Haojun Liao 已提交
574
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
575
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
576
  } else {
H
Haojun Liao 已提交
577 578 579
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
580

H
Haojun Liao 已提交
581
    if (pData->num + size > pResultBuf->pageSize) {
H
Haojun Liao 已提交
582 583
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
584
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
585
      if (pData != NULL) {
586
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
587 588 589
      }
    }
  }
590

591 592 593
  if (pData == NULL) {
    return -1;
  }
594

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

H
Haojun Liao 已提交
600
    pData->num += size;
601
    assert(pWindowRes->pageId >= 0);
602
  }
603

604 605 606
  return 0;
}

607
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
608
                                       bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
609
                                       int32_t numOfOutput, int32_t* rowCellInfoOffset) {
610 611
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
612

613
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
614
  if (pResultRow == NULL) {
615 616
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
617
  }
618

619
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
620
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
621
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQuery->intermediateResultRowSize);
H
Haojun Liao 已提交
622
    if (ret != TSDB_CODE_SUCCESS) {
623 624 625
      return -1;
    }
  }
626

627
  // set time window for current result
H
Haojun Liao 已提交
628
  pResultRow->win = (*win);
629
  *pResult = pResultRow;
H
Haojun Liao 已提交
630
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
631

632 633 634
  return TSDB_CODE_SUCCESS;
}

635 636 637 638 639 640 641 642 643
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 已提交
644
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
645 646 647 648 649 650 651 652
  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 已提交
653
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
654 655
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
656

H
Haojun Liao 已提交
657 658 659 660
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
661

H
Haojun Liao 已提交
662 663 664 665 666 667 668 669 670 671 672 673
      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;
      }
674 675
    }
  }
676

H
Haojun Liao 已提交
677
  assert(forwardStep > 0);
678 679 680
  return forwardStep;
}

681
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
682
  int64_t skey = TSKEY_INITIAL_VAL;
683 684 685
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
686
    if (pResult->closed) {
687
      break;
H
Haojun Liao 已提交
688 689
    }

690
    // new closed result rows
691 692 693 694 695 696 697 698 699 700
    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 已提交
701
    } else {
702 703 704 705 706
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
707 708 709
    }
  }

710
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
711
  if (skey == TSKEY_INITIAL_VAL) {
712
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
713 714
  } else {

715 716 717 718 719
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
720
    }
721

D
fix bug  
dapan1121 已提交
722
    if (i == pResultRowInfo->size - 1) {
723
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
724 725 726 727
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

728
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
729
  }
730
}
731

H
Haojun Liao 已提交
732 733 734
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))) {
735 736 737
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
738
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
739
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQuery->timeWindowInterpo);
740
  }
741 742 743
}

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

H
Haojun Liao 已提交
747
  int32_t num   = -1;
748
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
749
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
750

H
hjxilinx 已提交
751
  STableQueryInfo* item = pQuery->current;
752

753 754
  if (QUERY_IS_ASC_QUERY(pQuery)) {
    if (ekey < pDataBlockInfo->window.ekey) {
755
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
756 757
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
758 759
      }
    } else {
760
      num = pDataBlockInfo->rows - startPos;
761
      if (updateLastKey) {
H
hjxilinx 已提交
762
        item->lastKey = pDataBlockInfo->window.ekey + step;
763 764 765 766
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
767
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
768 769
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
770 771 772 773
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
774
        item->lastKey = pDataBlockInfo->window.skey + step;
775 776 777
      }
    }
  }
778

H
Haojun Liao 已提交
779
  assert(num > 0);
780 781 782
  return num;
}

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

788
  for (int32_t k = 0; k < numOfOutput; ++k) {
789
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
790
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
791

792
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
793 794

    int32_t pos = (QUERY_IS_ASC_QUERY(pQuery)) ? offset : offset - (forwardStep - 1);
795 796
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
797 798 799 800 801
    }

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

H
Haojun Liao 已提交
803
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
804

805 806 807 808 809
    // 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 已提交
810

811 812
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
813
    }
814 815 816

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
817
    pCtx[k].pInput = start;
818 819 820 821
  }
}


H
Haojun Liao 已提交
822
static int32_t getNextQualifiedWindow(SQuery* pQuery, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
823
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
824
  getNextTimeWindow(pQuery, pNext);
825

H
Haojun Liao 已提交
826
  // next time window is not in current block
H
Haojun Liao 已提交
827 828
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
H
Haojun Liao 已提交
829 830
    return -1;
  }
831

H
Haojun Liao 已提交
832 833
  TSKEY startKey = -1;
  if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
834
    startKey = pNext->skey;
H
Haojun Liao 已提交
835 836
    if (startKey < pQuery->window.skey) {
      startKey = pQuery->window.skey;
837
    }
H
Haojun Liao 已提交
838
  } else {
H
Haojun Liao 已提交
839
    startKey = pNext->ekey;
H
Haojun Liao 已提交
840 841
    if (startKey > pQuery->window.skey) {
      startKey = pQuery->window.skey;
842
    }
H
Haojun Liao 已提交
843
  }
844

H
Haojun Liao 已提交
845
  int32_t startPos = 0;
H
Haojun Liao 已提交
846

H
Haojun Liao 已提交
847
  // tumbling time window query, a special case of sliding time window query
848
  if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) {
H
Haojun Liao 已提交
849 850 851
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
852
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
853
      startPos = 0;
H
Haojun Liao 已提交
854
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
855 856 857 858
      startPos = pDataBlockInfo->rows - 1;
    } else {
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order);
    }
H
Haojun Liao 已提交
859
  }
860

H
Haojun Liao 已提交
861 862 863 864
  /*
   * 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 已提交
865 866 867
  if (primaryKeys == NULL) {
    if (QUERY_IS_ASC_QUERY(pQuery)) {
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
868
    } else {
H
Haojun Liao 已提交
869
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
870
    }
H
Haojun Liao 已提交
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
  } 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;
      }
890
    }
891
  }
892

H
Haojun Liao 已提交
893
  return startPos;
894 895
}

H
Haojun Liao 已提交
896
static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
897 898 899 900 901 902 903 904 905 906 907 908
  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;
    }
  }
909

910 911 912
  return ekey;
}

H
Haojun Liao 已提交
913 914 915 916 917 918 919 920 921 922 923 924
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;
    }
  }
}

925
// window start key interpolation
H
Haojun Liao 已提交
926

927

H
Haojun Liao 已提交
928
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
929
    int32_t rowIndex) {
930 931 932 933 934 935 936
  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 已提交
937
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
938 939 940
  }
}

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

H
Haojun Liao 已提交
944
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
945
  if (tsCols == NULL) {
H
Haojun Liao 已提交
946
    ts = ascQuery? win->skey : win->ekey;
947
  } else {
H
Haojun Liao 已提交
948
    int32_t offset = ascQuery? 0:rows-1;
949 950 951 952 953 954
    ts = tsCols[offset];
  }

  return ts;
}

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

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

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

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

H
Haojun Liao 已提交
1022
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
1023
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
1024
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1025
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
1026
        }
H
Haojun Liao 已提交
1027 1028 1029 1030 1031
      }
    }
  }
}

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

H
Haojun Liao 已提交
1035
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1036
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
1037
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
1038
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
1039 1040 1041 1042 1043
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

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

H
Haojun Liao 已提交
1047
  for (int32_t k = 0; k < numOfOutput; ++k) {
1048 1049
    pCtx[k].startTs = pQuery->window.skey;
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
1050 1051 1052
  }
}

H
Haojun Liao 已提交
1053 1054
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 已提交
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
  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 已提交
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
    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 已提交
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107

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

H
Haojun Liao 已提交
1113 1114
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

H
Haojun Liao 已提交
1115 1116 1117 1118 1119
  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 已提交
1120
  TSKEY key = ascQuery? win->skey:win->ekey;
H
Haojun Liao 已提交
1121 1122 1123 1124 1125
  if (key == curTs) {
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1126
  if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
H
Haojun Liao 已提交
1127 1128 1129 1130 1131
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

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

H
Haojun Liao 已提交
1134 1135
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1136 1137 1138 1139
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1140
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
  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 已提交
1166 1167
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
  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 已提交
1189
        tsCols, win);
H
Haojun Liao 已提交
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
    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 已提交
1217 1218 1219
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
  STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info;

H
Haojun Liao 已提交
1220 1221 1222
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
  SQuery*           pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1223 1224

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

H
Haojun Liao 已提交
1227
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1228

H
Haojun Liao 已提交
1229 1230 1231
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1232
    tsCols = (int64_t*) pColDataInfo->pData;
H
Haojun Liao 已提交
1233 1234
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1235 1236
  }

H
Haojun Liao 已提交
1237
  int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1);
H
Haojun Liao 已提交
1238
  TSKEY ts = getStartTsKey(pQuery, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1239 1240

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

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

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1251 1252
  TSKEY   ekey = reviseWindowEkey(pQuery, &win);
  forwardStep =
H
Haojun Liao 已提交
1253
      getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1254 1255

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1256
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1257 1258
  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 已提交
1259
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1260
      if (pRes->closed) {
H
Haojun Liao 已提交
1261 1262
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1263
        continue;
H
Haojun Liao 已提交
1264
      }
H
Haojun Liao 已提交
1265 1266

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1267 1268
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1269 1270 1271 1272 1273
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

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

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

H
Haojun Liao 已提交
1278
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1279
      setNotInterpoWindowKey(pInfo->pCtx, pQuery->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1280

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

H
Haojun Liao 已提交
1284
    // restore current time window
H
Haojun Liao 已提交
1285 1286
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1287 1288 1289
    if (ret != TSDB_CODE_SUCCESS) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
H
Haojun Liao 已提交
1290 1291 1292
  }

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

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1299
    startPos = getNextQualifiedWindow(pQuery, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1300 1301
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1302 1303
    }

H
Haojun Liao 已提交
1304
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1305 1306
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1307
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1308
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1309 1310
    }

H
Haojun Liao 已提交
1311
    ekey = reviseWindowEkey(pQuery, &nextWin);
1312
    forwardStep = getNumOfRowsInTimeWindow(pQuery, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1313 1314

    // window start(end) key interpolation
H
Haojun Liao 已提交
1315
    doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &nextWin, startPos, forwardStep);
1316
    doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &nextWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1317
  }
H
Haojun Liao 已提交
1318 1319

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

H
Haojun Liao 已提交
1324
  updateResultRowInfoActiveIndex(pResultRowInfo, pQuery, pQuery->current->lastKey);
H
Haojun Liao 已提交
1325 1326
}

H
Haojun Liao 已提交
1327 1328 1329
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  STableQueryInfo*  item = pRuntimeEnv->pQuery->current;
H
Haojun Liao 已提交
1330

H
Haojun Liao 已提交
1331
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1332 1333
  int16_t          bytes = pColInfoData->info.bytes;
  int16_t          type = pColInfoData->info.type;
D
fix bug  
dapan1121 已提交
1334
  SQuery    *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1335 1336

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

H
Haojun Liao 已提交
1341
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
sangshuduo's avatar
sangshuduo 已提交
1342
    char* val = ((char*)pColInfoData->pData) + bytes * j;
H
Haojun Liao 已提交
1343
    if (isNull(val, type)) {
H
Haojun Liao 已提交
1344 1345 1346
      continue;
    }

1347
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1348 1349 1350 1351 1352 1353 1354
    if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) {
      if (pInfo->prevData == NULL) {
        pInfo->prevData = malloc(bytes);
      }

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

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

H
Haojun Liao 已提交
1359 1360 1361 1362 1363
      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 已提交
1364 1365
    }

H
Haojun Liao 已提交
1366
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1367
      pInfo->binfo.pCtx[k].size = 1;
H
Haojun Liao 已提交
1368 1369
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1370
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1371 1372 1373 1374 1375
      }
    }
  }
}

1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSWindowOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
  STableQueryInfo*  item = pRuntimeEnv->pQuery->current;

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

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

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

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

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

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

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

  SResultRow* pResult = NULL;

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

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

H
Haojun Liao 已提交
1436
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
  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 已提交
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
}

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

H
Haojun Liao 已提交
1470
  setResultRowKey(pResultRow, pData, type);
H
Haojun Liao 已提交
1471
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
1472
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
H
Haojun Liao 已提交
1473 1474 1475 1476 1477
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1478 1479
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1480 1481
  return TSDB_CODE_SUCCESS;
}
1482

H
Haojun Liao 已提交
1483
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
  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 已提交
1501
  return -1;
H
Haojun Liao 已提交
1502 1503
}

1504
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1505
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
hjxilinx 已提交
1506
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1507 1508 1509 1510 1511

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

1513 1514 1515
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1516

1517
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
hjxilinx 已提交
1518 1519
    return QUERY_IS_ASC_QUERY(pQuery);
  }
1520

H
Haojun Liao 已提交
1521
  // denote the order type
1522
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
1523
    return pCtx->param[0].i64 == pQuery->order.order;
1524 1525
  }

1526 1527 1528
  // 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)) {
1529 1530
    return false;
  }
1531

1532 1533 1534
  return true;
}

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

H
Haojun Liao 已提交
1538 1539 1540 1541
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1542 1543 1544 1545 1546 1547
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1548
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1549 1550

  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1551
  if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
1552
    pCtx->preAggVals.isSet  = true;
H
Haojun Liao 已提交
1553 1554
    pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey;
    pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey;
H
Haojun Liao 已提交
1555
  }
H
Haojun Liao 已提交
1556 1557
}

H
Haojun Liao 已提交
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
// 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;
}
1599

H
Haojun Liao 已提交
1600
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1601
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1602 1603
  SQuery* pQuery = pRuntimeEnv->pQuery;

1604 1605
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1606
    return NULL;
1607 1608
  }

H
Haojun Liao 已提交
1609
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1610 1611 1612 1613
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1614

H
Haojun Liao 已提交
1615 1616
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SSqlFuncMsg *pSqlFuncMsg = &pExpr[i].base;
1617
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1618

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

Y
TD-1230  
yihaoDeng 已提交
1621
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1622 1623
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1624
    } else {
1625 1626
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1627

H
Haojun Liao 已提交
1628 1629
    pCtx->inputBytes = pSqlFuncMsg->colBytes;
    pCtx->inputType  = pSqlFuncMsg->colType;
H
Haojun Liao 已提交
1630

1631
    pCtx->ptsOutputBuf = NULL;
1632

H
Haojun Liao 已提交
1633 1634
    pCtx->outputBytes  = pExpr[i].bytes;
    pCtx->outputType   = pExpr[i].type;
1635

1636
    pCtx->order        = pQuery->order.order;
H
Haojun Liao 已提交
1637
    pCtx->functionId   = pSqlFuncMsg->functionId;
H
Haojun Liao 已提交
1638
    pCtx->stableQuery  = pQuery->stableQuery;
H
Haojun Liao 已提交
1639
    pCtx->interBufBytes = pExpr[i].interBytes;
1640 1641
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1642

H
Haojun Liao 已提交
1643
    pCtx->numOfParams  = pSqlFuncMsg->numOfParams;
1644 1645 1646
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
      int16_t type = pSqlFuncMsg->arg[j].argType;
      int16_t bytes = pSqlFuncMsg->arg[j].argBytes;
1647 1648 1649 1650
      if (pSqlFuncMsg->functionId == TSDB_FUNC_STDDEV_DST) {
        continue;
      }

1651
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
1652
        tVariantCreateFromBinary(&pCtx->param[j], pSqlFuncMsg->arg[j].argValue.pz, bytes, type);
1653 1654 1655 1656
      } else {
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlFuncMsg->arg[j].argValue.i64, bytes, type);
      }
    }
1657

1658 1659
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1660

1661
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1662
      int32_t f = pExpr[0].base.functionId;
1663
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1664

H
Haojun Liao 已提交
1665
      pCtx->param[2].i64 = pQuery->order.order;
1666
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1667
      pCtx->param[3].i64 = functionId;
1668
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1669

1670
      pCtx->param[1].i64 = pQuery->order.orderColId;
H
Haojun Liao 已提交
1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
    } 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) {
1683
      pCtx->param[0].i64 = pQuery->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1684 1685 1686 1687 1688 1689 1690 1691
      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];
1692
    }
H
Haojun Liao 已提交
1693
  }
1694

H
Haojun Liao 已提交
1695
  for(int32_t i = 1; i < numOfOutput; ++i) {
sangshuduo's avatar
sangshuduo 已提交
1696 1697
    (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) +
        pExpr[i - 1].interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
1698
  }
1699

H
Haojun Liao 已提交
1700 1701
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1702
  return pFuncCtx;
H
Haojun Liao 已提交
1703 1704
}

H
Haojun Liao 已提交
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722
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 已提交
1723
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables) {
H
Haojun Liao 已提交
1724
  qDebug("QInfo:%"PRIu64" setup runtime env", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
  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 已提交
1735 1736
  pRuntimeEnv->currentOffset = pQuery->limit.offset;

H
Haojun Liao 已提交
1737 1738 1739
  // 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 已提交
1740 1741
  pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport));

H
Haojun Liao 已提交
1742 1743
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1744 1745 1746
    goto _clean;
  }

H
Haojun Liao 已提交
1747 1748 1749 1750 1751 1752
  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 已提交
1753

H
Haojun Liao 已提交
1754 1755
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1756

H
Haojun Liao 已提交
1757
  qDebug("QInfo:%"PRIu64" init runtime environment completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1758 1759

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

  } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
H
Haojun Liao 已提交
1764
    if (pQuery->stableQuery) {
H
Haojun Liao 已提交
1765 1766
      pRuntimeEnv->proot = createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner,
                                                                    pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1767
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1768
    } else {
H
Haojun Liao 已提交
1769 1770
      pRuntimeEnv->proot =
          createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
1771
      setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1772

H
Haojun Liao 已提交
1773
      if (pQuery->pExpr2 != NULL) {
H
Haojun Liao 已提交
1774 1775
        pRuntimeEnv->proot =
            createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1776
      }
H
Haojun Liao 已提交
1777

H
Haojun Liao 已提交
1778
      if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
1779 1780
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
H
Haojun Liao 已提交
1781
      }
H
Haojun Liao 已提交
1782
    }
H
Haojun Liao 已提交
1783

H
Haojun Liao 已提交
1784 1785 1786 1787
  } else if (pQuery->groupbyColumn) {
    pRuntimeEnv->proot =
        createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1788

1789 1790 1791 1792 1793 1794 1795
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
    }
  } else if (pQuery->sw.gap > 0) {
    pRuntimeEnv->proot = createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->pTableScanner, pQuery->pExpr1, pQuery->numOfOutput);
    setTableScanFilterOperatorInfo(pRuntimeEnv->pTableScanner->info, pRuntimeEnv->proot);

H
Haojun Liao 已提交
1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
    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);
    }
1807

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

H
Haojun Liao 已提交
1810 1811
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1812
    }
H
Haojun Liao 已提交
1813 1814 1815 1816 1817 1818
  } 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 已提交
1819
    }
H
Haojun Liao 已提交
1820
  }
H
Haojun Liao 已提交
1821

H
Haojun Liao 已提交
1822 1823 1824
  if (pQuery->limit.offset > 0) {
    pRuntimeEnv->proot = createOffsetOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }
H
Haojun Liao 已提交
1825

H
Haojun Liao 已提交
1826 1827 1828 1829 1830
  if (pQuery->limit.limit > 0) {
    pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
  }

  return TSDB_CODE_SUCCESS;
1831

1832
_clean:
1833
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1834 1835 1836 1837
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1838

1839
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1840 1841
}

H
Haojun Liao 已提交
1842
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1843
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1844 1845 1846 1847

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

H
Haojun Liao 已提交
1848
  SMemRef* pMemRef = &pQuery->memRef;
1849
  assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
H
Haojun Liao 已提交
1850 1851
}

H
Haojun Liao 已提交
1852
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
1853
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1854
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1855

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

1858 1859 1860
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1861
      tfree(pRuntimeEnv->sasArray[i].colList);
1862 1863 1864 1865 1866
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1867
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1868
  doFreeQueryHandle(pRuntimeEnv);
1869

H
Haojun Liao 已提交
1870
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1871

S
TD-1848  
Shengliang Guan 已提交
1872
  tfree(pRuntimeEnv->keyBuf);
1873
  tfree(pRuntimeEnv->prevRow);
1874 1875
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1876 1877
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1878

H
Haojun Liao 已提交
1879 1880 1881
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1882
  destroyOperatorInfo(pRuntimeEnv->proot);
D
dapan1121 已提交
1883 1884 1885 1886 1887

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

1888 1889
}

1890 1891 1892 1893
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1894
bool isQueryKilled(SQInfo *pQInfo) {
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904
  if (IS_QUERY_KILLED(pQInfo)) {
    return true;
  }

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

    assert(pQInfo->startExecTs != 0);
H
Haojun Liao 已提交
1905 1906
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1907 1908 1909 1910 1911 1912
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
1915
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
1916
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
1917 1918
    return false;
  }
1919

1920
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1921
  if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) {
1922 1923
    return true;
  }
1924

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

1928 1929
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
1930
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
1931 1932
      continue;
    }
1933

1934 1935 1936
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
1937

H
Haojun Liao 已提交
1938
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
1939 1940 1941
      return true;
    }
  }
1942

1943 1944 1945
  return false;
}

1946
// todo refactor with isLastRowQuery
1947
bool isPointInterpoQuery(SQuery *pQuery) {
1948
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1949 1950
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
1951 1952 1953
      return true;
    }
  }
1954

1955 1956 1957 1958
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
1959
static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) {
1960
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1961
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1962 1963 1964
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
1965

1966 1967 1968 1969 1970
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
1971

1972 1973 1974
  return false;
}

H
hjxilinx 已提交
1975
static bool isFirstLastRowQuery(SQuery *pQuery) {
1976
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1977
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
1978 1979 1980 1981
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
1982

1983 1984 1985
  return false;
}

H
hjxilinx 已提交
1986
static bool needReverseScan(SQuery *pQuery) {
1987
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1988
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
1989 1990 1991
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
1992

1993
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
1994 1995
      return true;
    }
1996 1997

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
1998
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
1999
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
2000 2001 2002
      if (order != pQuery->order.order) {
        return true;
      }
2003
    }
2004
  }
2005

2006 2007
  return false;
}
H
hjxilinx 已提交
2008

H
Haojun Liao 已提交
2009 2010 2011 2012
/**
 * 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 已提交
2013
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
2014
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2015
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
2016 2017

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
2018 2019 2020 2021

    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 已提交
2022
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
2023 2024 2025
      return false;
    }
  }
2026

H
hjxilinx 已提交
2027 2028 2029
  return true;
}

2030 2031
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2032
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
2033 2034
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
2035 2036

  /*
2037
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
2038 2039
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
2040 2041
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
2042
    win->ekey = INT64_MAX;
2043 2044
  } 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 已提交
2045
  } else {
2046
    win->ekey = win->skey + pQuery->interval.interval - 1;
2047 2048 2049 2050 2051
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
2052
    pQuery->checkResultBuf = 0;
2053
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
2054
    pQuery->checkResultBuf = 0;
2055 2056
  } else {
    bool hasMultioutput = false;
2057
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2058
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
2059 2060 2061
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
2062

H
Haojun Liao 已提交
2063
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
2064 2065 2066 2067
      if (!hasMultioutput) {
        break;
      }
    }
2068

H
Haojun Liao 已提交
2069
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
2070 2071 2072 2073 2074 2075
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2076
bool colIdCheck(SQuery *pQuery, uint64_t qId) {
2077 2078
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
2079
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
H
Haojun Liao 已提交
2080
      qError("QInfo:%"PRIu64" invalid data load column for query", qId);
2081 2082 2083
      return false;
    }
  }
2084

2085 2086 2087 2088 2089 2090
  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) {
2091
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2092
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2093

2094 2095 2096 2097
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2098

2099 2100 2101 2102
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2103

2104 2105 2106 2107 2108 2109 2110
  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); }

2111
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2112 2113
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2114
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2115
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2116 2117 2118

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

2121 2122 2123 2124
      // 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 已提交
2125 2126 2127 2128
    }
  }
}

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

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

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

H
Haojun Liao 已提交
2141
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2142 2143 2144
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2145

2146 2147
    return;
  }
2148

2149
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2150
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2151 2152 2153
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2154

2155
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2156 2157 2158
    return;
  }

2159
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2160
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2161
      qDebug(msg, pQInfo->qId, "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);
H
Haojun Liao 已提交
2162 2163
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2164

2165
    pQuery->order.order = TSDB_ORDER_ASC;
2166 2167
    return;
  }
2168

2169
  if (pQuery->interval.interval == 0) {
2170 2171
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2172
        qDebug(msg, pQInfo->qId, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2173 2174
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2175
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2176
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2177
      }
2178

2179
      pQuery->order.order = TSDB_ORDER_ASC;
2180 2181
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2182
        qDebug(msg, pQInfo->qId, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2183 2184
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2185
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2186
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2187
      }
2188

2189
      pQuery->order.order = TSDB_ORDER_DESC;
2190
    }
2191

2192
  } else {  // interval query
2193
    if (stableQuery) {
2194 2195
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2196
          qDebug(msg, pQInfo->qId, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2197 2198
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2199
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2200
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2201
        }
2202

2203
        pQuery->order.order = TSDB_ORDER_ASC;
2204 2205
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2206
          qDebug(msg, pQInfo->qId, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2207 2208
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2209
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2210
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2211
        }
2212

2213
        pQuery->order.order = TSDB_ORDER_DESC;
2214 2215 2216 2217 2218
      }
    }
  }
}

2219 2220
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2221
  int32_t MIN_ROWS_PER_PAGE = 4;
2222

H
Haojun Liao 已提交
2223
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2224 2225 2226 2227
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2232 2233
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2234 2235
}

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

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

H
Haojun Liao 已提交
2241
  if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) {
2242 2243 2244 2245 2246
    return true;
  }

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

H
Haojun Liao 已提交
2248 2249 2250 2251 2252 2253 2254 2255
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2256
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2257
    if (index == -1) {
H
Haojun Liao 已提交
2258
      return true;
2259
    }
2260

2261
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2262
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2263
      return true;
2264
    }
2265

2266
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2267
    if (pDataStatis[index].numOfNull == numOfRows) {
2268 2269 2270 2271

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2272
        if (pFilterElem->fp == isNullOperator) {
2273 2274 2275 2276
          return true;
        }
      }

2277 2278
      continue;
    }
2279

H
Haojun Liao 已提交
2280 2281 2282
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2286
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2287
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2288 2289 2290 2291 2292
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2293
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2294 2295 2296 2297 2298
          return true;
        }
      }
    }
  }
2299

H
Haojun Liao 已提交
2300
  return false;
2301 2302
}

H
Haojun Liao 已提交
2303 2304 2305 2306 2307 2308 2309 2310
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 已提交
2311
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2312

H
Haojun Liao 已提交
2313
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2314 2315 2316 2317
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2318
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2319
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2320 2321 2322
        break;
      }

H
Haojun Liao 已提交
2323 2324
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2325 2326 2327 2328 2329
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2330 2331 2332
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2333 2334 2335 2336
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2337
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2338 2339 2340 2341
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2342 2343
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2344 2345 2346 2347 2348 2349 2350 2351
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376
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;
}
2377

H
Haojun Liao 已提交
2378
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
H
Haojun Liao 已提交
2379
                        SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2380 2381 2382 2383 2384
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2385
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

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

      if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) {
        break;
      }
    }
H
Haojun Liao 已提交
2406 2407 2408

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

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

H
Haojun Liao 已提交
2416 2417 2418
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2419

H
Haojun Liao 已提交
2420 2421 2422 2423 2424 2425 2426 2427
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2428
          } else {
H
Haojun Liao 已提交
2429 2430 2431 2432 2433 2434
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2435
          }
H
Haojun Liao 已提交
2436 2437

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2438 2439 2440 2441 2442
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2443
        if (!qualified) {
H
Haojun Liao 已提交
2444 2445 2446 2447
          break;
        }
      }

H
Haojun Liao 已提交
2448
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2449
      if (!qualified) {
H
Haojun Liao 已提交
2450
        all = false;
H
Haojun Liao 已提交
2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467
      }
    }
  }

  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 已提交
2468
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2469 2470 2471
          }

          start += len;
2472
          len = 0;
H
Haojun Liao 已提交
2473 2474 2475 2476
        }
      }
    }

2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489
    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 已提交
2490 2491 2492 2493
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

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

H
Haojun Liao 已提交
2498 2499
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
H
Haojun Liao 已提交
2500 2501 2502 2503 2504 2505
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2506 2507 2508
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 已提交
2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
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 已提交
2546 2547
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2548
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2549
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2550
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2551

H
Haojun Liao 已提交
2552
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2553
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
2554
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQuery);
H
Haojun Liao 已提交
2555

H
Haojun Liao 已提交
2556
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2557 2558
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2559
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2560
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2561

H
Haojun Liao 已提交
2562
    if (pQuery->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2563 2564 2565 2566 2567 2568 2569
      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 已提交
2570
      setTimestampListJoinInfo(pRuntimeEnv, &t, pQuery->current);
H
Haojun Liao 已提交
2571 2572 2573 2574 2575 2576

      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 已提交
2577 2578 2579
    }
  }

H
Haojun Liao 已提交
2580 2581
  // 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.
2582
  if (pQuery->numOfFilterCols > 0 || pQuery->groupbyColumn || pQuery->sw.gap > 0 ||
H
Haojun Liao 已提交
2583 2584 2585
      (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info))) {
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2586

H
Haojun Liao 已提交
2587 2588 2589 2590 2591 2592
  // 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 已提交
2593

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

H
Haojun Liao 已提交
2597 2598 2599 2600 2601
      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 已提交
2602
      }
H
Haojun Liao 已提交
2603
    } else if (pQuery->stableQuery && (!isTsCompQuery(pQuery))) { // stable aggregate, not interval aggregate or normal column aggregate
2604 2605 2606
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
                               pQuery->current->groupIndex);
H
Haojun Liao 已提交
2607
    }
H
Haojun Liao 已提交
2608 2609

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

H
Haojun Liao 已提交
2612
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2613
  if ((*status) == BLK_DATA_NO_NEEDED) {
H
Haojun Liao 已提交
2614
    qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2615
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2616 2617 2618 2619
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2620
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2621

H
Haojun Liao 已提交
2622
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2623
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2624
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2625 2626 2627 2628 2629 2630
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2633
    if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648
      { // set previous window
        if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
          SResultRow* pResult = NULL;

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

          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQuery);
          if (setWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                      pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                      pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
            longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
          }
        }
      }
H
Haojun Liao 已提交
2649 2650
      bool load = false;
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2651
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2652
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2653 2654
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2655
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2656
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2657
            qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2658
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2659 2660 2661 2662 2663 2664 2665 2666
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2667
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2668
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2669
      qDebug("QInfo:%"PRIu64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2670
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2671
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2672
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2673 2674 2675 2676
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2677
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2678
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2679 2680
      return terrno;
    }
H
Haojun Liao 已提交
2681

H
Haojun Liao 已提交
2682
    doSetFilterColumnInfo(pQuery, pBlock);
H
Haojun Liao 已提交
2683
    if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2684
      filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2685
    }
H
Haojun Liao 已提交
2686 2687 2688 2689 2690
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2691
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2692
  int32_t midPos = -1;
H
Haojun Liao 已提交
2693
  int32_t numOfRows;
2694

2695 2696 2697
  if (num <= 0) {
    return -1;
  }
2698

2699
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2700 2701

  TSKEY * keyList = (TSKEY *)pValue;
2702
  int32_t firstPos = 0;
2703
  int32_t lastPos = num - 1;
2704

2705
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2706 2707 2708 2709 2710
    // 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;
2711

H
Haojun Liao 已提交
2712 2713
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2714

H
hjxilinx 已提交
2715 2716 2717 2718 2719 2720 2721 2722
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2723

H
hjxilinx 已提交
2724 2725 2726 2727 2728
  } 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;
2729

H
hjxilinx 已提交
2730 2731 2732 2733 2734 2735 2736
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2737

H
Haojun Liao 已提交
2738
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2739
      midPos = (numOfRows >> 1u) + firstPos;
2740

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

H
hjxilinx 已提交
2751 2752 2753
  return midPos;
}

H
Haojun Liao 已提交
2754 2755 2756 2757 2758 2759
/*
 * 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);
2760

H
Haojun Liao 已提交
2761
  char* val = NULL;
H
Haojun Liao 已提交
2762
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2763
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2764 2765
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2766 2767
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2768

H
Haojun Liao 已提交
2769 2770 2771 2772
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2773

H
Haojun Liao 已提交
2774
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2775 2776 2777 2778
    int32_t maxLen = bytes - VARSTR_HEADER_SIZE;
    int32_t len = (varDataLen(val) > maxLen)? maxLen:varDataLen(val);
    tVariantCreateFromBinary(tag, varDataVal(val), len, type);
    //tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
H
Haojun Liao 已提交
2779 2780
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2781
  }
2782 2783
}

2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795
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 已提交
2796
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2797
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2798

H
Haojun Liao 已提交
2799 2800 2801 2802
  SExprInfo *pExpr  = pOperatorInfo->pExpr;
  SQuery    *pQuery = pRuntimeEnv->pQuery;

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

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

2809
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2810
    return;
H
Haojun Liao 已提交
2811 2812 2813 2814
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
H
Haojun Liao 已提交
2815

H
Haojun Liao 已提交
2816 2817 2818 2819 2820 2821 2822 2823 2824
    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 已提交
2825 2826
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type,
                           pLocalExprInfo->bytes);
H
Haojun Liao 已提交
2827 2828 2829 2830

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
2831
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2832 2833 2834 2835 2836
      }

      offset += pLocalExprInfo->bytes;
    }

H
Haojun Liao 已提交
2837
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2838
    if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2839
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2840
    }
H
Haojun Liao 已提交
2841
  }
H
Haojun Liao 已提交
2842

H
Haojun Liao 已提交
2843 2844 2845
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2846 2847
  }
}
2848

2849
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
  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);
  }
}

2918
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
2919
  SQuery* pQuery = pRuntimeEnv->pQuery;
2920
  int32_t numOfCols = pQuery->numOfOutput;
2921
  printf("super table query intermediate result, total:%d\n", numOfRows);
2922

2923 2924
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2925

H
Haojun Liao 已提交
2926
      switch (pQuery->pExpr1[i].type) {
2927
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2928 2929
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
2930 2931 2932 2933 2934
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2935
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2936 2937
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2938
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2939 2940
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2941
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2942 2943
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2944
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
2945 2946 2947 2948 2949 2950 2951
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2952
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2953
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2954
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2955 2956

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2957
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2958 2959 2960
    // 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 已提交
2961
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2962 2963 2964 2965
        return;
      }
    }

H
Haojun Liao 已提交
2966
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2967 2968

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2969
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2970 2971
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2972
        break;
H
Haojun Liao 已提交
2973 2974 2975
      }
    }

H
Haojun Liao 已提交
2976 2977 2978 2979
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2980
    }
H
Haojun Liao 已提交
2981

H
Haojun Liao 已提交
2982 2983
}

2984 2985 2986 2987
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
2988

2989 2990
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
2991

2992 2993
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
2994

H
Haojun Liao 已提交
2995
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
2996
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
2997 2998
}

H
Haojun Liao 已提交
2999 3000
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3001

H
Haojun Liao 已提交
3002
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
3003 3004 3005
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
3006

H
Haojun Liao 已提交
3007 3008 3009 3010
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
3011

H
Haojun Liao 已提交
3012 3013 3014 3015
      // 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 已提交
3016

H
Haojun Liao 已提交
3017
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
3018
    }
H
Haojun Liao 已提交
3019 3020
  }
}
H
Haojun Liao 已提交
3021

H
Haojun Liao 已提交
3022 3023 3024
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3025 3026 3027
  }
}

H
Haojun Liao 已提交
3028 3029 3030 3031 3032 3033
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3034

H
Haojun Liao 已提交
3035 3036 3037 3038 3039 3040 3041 3042
/*
 * 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 已提交
3043 3044 3045 3046 3047 3048
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 已提交
3049 3050
  int32_t tid = 0;
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
3051

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

H
Haojun Liao 已提交
3055 3056 3057 3058 3059 3060 3061 3062 3063 3064
    /*
     * 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);
3065

H
Haojun Liao 已提交
3066 3067 3068 3069 3070
    // 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;
    }
3071
  }
3072

H
Haojun Liao 已提交
3073
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3074
}
3075

H
Haojun Liao 已提交
3076 3077 3078
void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) {
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
  SSDataBlock* pDataBlock = pBInfo->pRes;
3079

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

H
Haojun Liao 已提交
3088 3089 3090 3091 3092
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        pInfo->bufCapacity = newSize;
      } else {
        // longjmp
3093 3094
      }
    }
H
Haojun Liao 已提交
3095
  }
3096

H
Haojun Liao 已提交
3097 3098 3099
  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;
3100

H
Haojun Liao 已提交
3101 3102 3103 3104
    // 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 已提交
3105
    }
H
Haojun Liao 已提交
3106 3107
  }
}
3108

H
Haojun Liao 已提交
3109
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3110 3111 3112 3113
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3114 3115
    }

H
Haojun Liao 已提交
3116
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3117
  }
H
Haojun Liao 已提交
3118
}
3119

H
Haojun Liao 已提交
3120
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3121
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3122
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3123 3124
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3125 3126
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3127 3128
  }
}
3129

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

H
Haojun Liao 已提交
3133 3134 3135 3136
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3137
  }
3138

H
Haojun Liao 已提交
3139 3140 3141 3142
  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3143
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3144

H
Haojun Liao 已提交
3145
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3146
  SWITCH_ORDER(pQuery->order.order);
H
Haojun Liao 已提交
3147 3148

  setupQueryRangeForReverseScan(pRuntimeEnv);
3149 3150
}

H
Haojun Liao 已提交
3151
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3152
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3153
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3154 3155

  int32_t numOfOutput = pOperator->numOfOutput;
3156
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || pQuery->sw.gap > 0) {
H
Haojun Liao 已提交
3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167
    // 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 已提交
3168
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3169 3170 3171 3172 3173 3174 3175 3176 3177

      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 已提交
3178
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3179 3180 3181 3182 3183 3184 3185 3186 3187
    }

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

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

3192 3193 3194 3195
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3196

3197 3198 3199
  return false;
}

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

H
hjxilinx 已提交
3203 3204
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3205

3206
  pTableQueryInfo->pTable = pTable;
3207
  pTableQueryInfo->cur.vgroupIndex = -1;
3208

H
Haojun Liao 已提交
3209
  // set more initial size of interval/groupby query
3210
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
3211
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3212
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3213 3214 3215
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3216
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3217 3218
  }

3219 3220 3221
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3222
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3223 3224 3225
  if (pTableQueryInfo == NULL) {
    return;
  }
3226

H
Haojun Liao 已提交
3227
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3228
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3229 3230
}

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

H
Haojun Liao 已提交
3236
  int16_t offset = 0;
3237
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3238
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3239 3240 3241

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3242
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3243 3244
      continue;
    }
3245

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

3249
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3250
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3251
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3252
    }
3253

3254
    if (!pResInfo->initialized) {
3255
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3256 3257 3258 3259
    }
  }
}

3260 3261
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3262
  int64_t uid = 0;
H
Haojun Liao 已提交
3263
  SResultRow* pResultRow =
3264
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3265
  assert (pResultRow != NULL);
3266

3267 3268 3269 3270 3271
  /*
   * 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) {
3272 3273
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
    if (ret != TSDB_CODE_SUCCESS) {
3274
      return;
3275 3276 3277
    }
  }

3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292
  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);

3293 3294
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3295 3296
}

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

H
Haojun Liao 已提交
3302
  int16_t offset = 0;
3303
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3304 3305
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQuery, page, pResult->offset, offset);
    offset += pCtx[i].outputBytes;
3306

3307 3308 3309
    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;
3310 3311
    }

3312 3313 3314 3315
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3316
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3317 3318 3319
  }
}

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

H
Haojun Liao 已提交
3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335
  SSqlFuncMsg* pFuncMsg = &pExprInfo->base;
  if (pQuery->stableQuery && (pRuntimeEnv->pTsBuf != NULL) &&
      (pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) &&
      (pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
    assert(pFuncMsg->numOfParams == 1);

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

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

    int16_t tagType = pCtx[0].tag.nType;
    if (tagType == TSDB_DATA_TYPE_BINARY || tagType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3336
      qDebug("QInfo:%"PRIu64" set tag value for join comparison, colId:%" PRId64 ", val:%s", GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3337 3338
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz);
    } else {
H
Haojun Liao 已提交
3339
      qDebug("QInfo:%"PRIu64" set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3340 3341 3342 3343 3344 3345
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64);
    }
  }
}

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

H
Haojun Liao 已提交
3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358
  assert(pRuntimeEnv->pTsBuf != NULL);

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

    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQuery->vgId, &pTableQueryInfo->tag);

    // failed to find data with the specified tag value and vnodeId
    if (!tsBufIsValidElem(&elem)) {
      if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3359
        qError("QInfo:%"PRIu64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3360
      } else {
H
Haojun Liao 已提交
3361
        qError("QInfo:%"PRIu64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3362 3363 3364 3365 3366 3367 3368 3369
      }

      return -1;
    }

    // Keep the cursor info of current table
    pTableQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3370
      qDebug("QInfo:%"PRIu64" find tag:%s start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->pz, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3371
    } else {
H
Haojun Liao 已提交
3372
      qDebug("QInfo:%"PRIu64" find tag:%"PRId64" start pos in ts_comp, blockIndex:%d, tsIndex:%d", GET_QID(pRuntimeEnv), pTag->i64, pTableQueryInfo->cur.blockIndex, pTableQueryInfo->cur.tsIndex);
H
Haojun Liao 已提交
3373 3374 3375 3376 3377
    }

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

H
Haojun Liao 已提交
3384 3385 3386 3387 3388 3389
  return 0;
}

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

H
Haojun Liao 已提交
3390 3391 3392
  int32_t numOfExprs = pQuery->numOfOutput;
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SExprInfo* pExprInfo = &(pExpr[i]);
H
Haojun Liao 已提交
3393
    if (pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3394 3395 3396 3397 3398 3399
      continue;
    }

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3403 3404 3405
    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 已提交
3406
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
H
Haojun Liao 已提交
3407 3408
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3420

D
fix bug  
dapan1121 已提交
3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456
void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes) {
  SQuery* pQuery = pRuntimeEnv->pQuery;

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

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

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

}



3457 3458 3459 3460 3461 3462 3463 3464 3465
/*
 * 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 已提交
3466
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3467 3468 3469
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3470

H
Haojun Liao 已提交
3471 3472 3473
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3474

H
Haojun Liao 已提交
3475 3476
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
3477

H
Haojun Liao 已提交
3478 3479 3480 3481 3482 3483
  /**
   * 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 已提交
3484
  STimeWindow w = TSWINDOW_INITIALIZER;
3485

H
Haojun Liao 已提交
3486 3487 3488
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
3489

H
Haojun Liao 已提交
3490 3491 3492
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
3493
    }
H
Haojun Liao 已提交
3494

H
Haojun Liao 已提交
3495
    pWindowResInfo->prevSKey = w.skey;
3496
  }
H
Haojun Liao 已提交
3497 3498

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3499 3500 3501
}

/**
H
Haojun Liao 已提交
3502
 * copyToOutputBuf support copy data in ascending/descending order
3503 3504 3505 3506 3507 3508 3509
 * 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 已提交
3510

H
Haojun Liao 已提交
3511
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3512 3513 3514
  SQuery *pQuery = pRuntimeEnv->pQuery;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3515
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3516 3517 3518 3519

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3520
  qDebug("QInfo:%"PRIu64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540
  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 已提交
3541 3542

    int16_t offset = 0;
H
Haojun Liao 已提交
3543 3544 3545 3546 3547
    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 已提交
3548
      char *in  = getPosInResultPage(pQuery, page, pRow->offset, offset);
H
Haojun Liao 已提交
3549
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3550 3551

      offset += bytes;
H
Haojun Liao 已提交
3552 3553 3554
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3555
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3556 3557 3558 3559
      break;
    }
  }

H
Haojun Liao 已提交
3560
  qDebug("QInfo:%"PRIu64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3561 3562 3563 3564 3565 3566
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3568
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3569
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3570 3571 3572 3573 3574
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3575
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3576 3577 3578

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

H
Haojun Liao 已提交
3579 3580 3581
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3582
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3583
  }
3584 3585
}

H
Haojun Liao 已提交
3586
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv *pRuntimeEnv,
H
Haojun Liao 已提交
3587
    SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
3588
  SQuery *pQuery = pRuntimeEnv->pQuery;
3589

3590
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3591 3592 3593
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
3594

3595 3596
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3597

3598 3599
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3600 3601
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3602
      }
H
Haojun Liao 已提交
3603

H
Haojun Liao 已提交
3604
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3605
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3606 3607 3608 3609 3610
    }
  }
}

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

H
Haojun Liao 已提交
3614
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3615

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

H
Haojun Liao 已提交
3630
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3631 3632
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3633

3634
  int32_t total = 0;
H
Haojun Liao 已提交
3635
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3636

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

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

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

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

H
Haojun Liao 已提交
3657
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3658 3659 3660 3661 3662 3663
  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 已提交
3664
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3665
  tfree(p);
H
Haojun Liao 已提交
3666 3667
  return pOutput->info.rows;
}
3668

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

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

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

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

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

H
Haojun Liao 已提交
3694
  qDebug("QInfo:%"PRIu64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0,
H
Haojun Liao 已提交
3695
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
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
//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 已提交
3730
//  qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
3731 3732
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3733

3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
//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 已提交
3749
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759
//      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 已提交
3760
//      qDebug("QInfo:%"PRIu64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771
//             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 已提交
3772

3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
//  SQuery *pQuery = pRuntimeEnv->pQuery;
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
//  assert(pQuery->limit.offset == 0);
//  STimeWindow tw = *win;
//  getNextTimeWindow(pQuery, &tw);
//
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
//
//    // load the data block and check data remaining in current data block
//    // TODO optimize performance
//    SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//    SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
//    tw = *win;
//    int32_t startPos =
//        getNextQualifiedWindow(pQuery, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
//    assert(startPos >= 0);
//
//    // set the abort info
//    pQuery->pos = startPos;
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
//    pQuery->window.skey = pTableQueryInfo->win.skey;
//    TSKEY key = pTableQueryInfo->win.skey;
//
//    pWindowResInfo->prevSKey = tw.skey;
//    int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
//
//    int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//    pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
//
H
Haojun Liao 已提交
3808 3809
//    qDebug("QInfo:%"PRIu64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932
//           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;
//}
3933

H
Haojun Liao 已提交
3934 3935
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

B
Bomin Zhang 已提交
3936
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
3937
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
3938 3939
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
Haojun Liao 已提交
3940
  // TODO set the tags scan handle
B
Bomin Zhang 已提交
3941
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
3942
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3943 3944
  }

H
Haojun Liao 已提交
3945
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
3946 3947 3948
  if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3949

B
Bomin Zhang 已提交
3950
  if (!isSTableQuery
H
Haojun Liao 已提交
3951
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3952
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3953
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
3954
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
3955
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
3956
  ) {
H
Haojun Liao 已提交
3957
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3958 3959
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3960
  }
B
Bomin Zhang 已提交
3961

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

H
Haojun Liao 已提交
3966 3967
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
3968
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3969
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3970
    } else {
H
Haojun Liao 已提交
3971
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3972
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3973
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3974

H
Haojun Liao 已提交
3975 3976 3977
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3978

H
Haojun Liao 已提交
3979 3980 3981
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
3982 3983
      }
    }
3984
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
3985
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
3986
  } else {
H
Haojun Liao 已提交
3987
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
3988
  }
3989

B
Bomin Zhang 已提交
3990
  return terrno;
B
Bomin Zhang 已提交
3991 3992
}

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

H
Haojun Liao 已提交
3996
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
3997 3998 3999 4000
  if (pFillCol == NULL) {
    return NULL;
  }

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

4004
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
4005
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
4006
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
4007
    pFillCol[i].tagIndex   = -2;
4008 4009
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
4010
    pFillCol[i].fillVal.i  = fillVal[i];
4011

4012 4013
    offset += pExprInfo->bytes;
  }
4014

4015 4016 4017
  return pFillCol;
}

D
dapan1121 已提交
4018
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bool isSTableQuery) {
4019 4020 4021
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

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

H
Haojun Liao 已提交
4024 4025
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
4026
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
H
Haojun Liao 已提交
4027
  pQuery->stabledev = isStabledev(pQuery);
H
Haojun Liao 已提交
4028

4029
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
4030

H
Haojun Liao 已提交
4031
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
4032 4033 4034
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
4035

H
Haojun Liao 已提交
4036
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
4037
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
4038 4039
  pQuery->stableQuery = isSTableQuery;
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);
H
Haojun Liao 已提交
4040
  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);
H
Haojun Liao 已提交
4041

sangshuduo's avatar
sangshuduo 已提交
4042
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
4043 4044

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
4045
  pRuntimeEnv->pTsBuf = pTsBuf;
4046
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4047
  setResultBufSize(pQuery, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4048

4049
  if (onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
4050
    pRuntimeEnv->resultInfo.capacity = 4096;
H
Haojun Liao 已提交
4051
    pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
4052 4053
  } else if (pQuery->queryBlockDist) {
    pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4054
  } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4055
    pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
4056
  } else if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
4057
    pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
4058
  } else {
H
Haojun Liao 已提交
4059
    pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
4060 4061
  }

H
Haojun Liao 已提交
4062
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4063 4064
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4065 4066
  }

4067
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
4068
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize);
4069

H
Haojun Liao 已提交
4070
  int32_t TENMB = 1024*1024*10;
H
Haojun Liao 已提交
4071
  code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo->qId);
H
Haojun Liao 已提交
4072 4073
  if (code != TSDB_CODE_SUCCESS) {
    return code;
4074 4075
  }

H
Haojun Liao 已提交
4076
  // create runtime environment
sangshuduo's avatar
sangshuduo 已提交
4077
  int32_t numOfTables = (int32_t)pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4078
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4079
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables);
H
Haojun Liao 已提交
4080 4081 4082 4083
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4084
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4085
  return TSDB_CODE_SUCCESS;
4086 4087
}

H
Haojun Liao 已提交
4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101
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 已提交
4102
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
4103 4104 4105 4106
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
H
Haojun Liao 已提交
4107
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4108
      .loadExternalRows = false,
4109 4110
  };

H
Haojun Liao 已提交
4111
  TIME_WINDOW_COPY(cond.twindow, *win);
4112 4113 4114
  return cond;
}

H
Haojun Liao 已提交
4115
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
4116
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
4117
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
4118 4119 4120

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
4121
  tidInfo.key = pTableQueryInfo->lastKey;
4122 4123 4124 4125

  return tidInfo;
}

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

H
Haojun Liao 已提交
4130 4131
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4132 4133 4134 4135 4136 4137 4138 4139
  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 已提交
4140 4141 4142 4143
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);
4144

H
Haojun Liao 已提交
4145 4146 4147 4148
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4149 4150
    }
  }
4151 4152
}

H
Haojun Liao 已提交
4153 4154 4155 4156
static SSDataBlock* doTableScanImpl(void* param) {
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4157
  SSDataBlock*     pBlock = &pTableScanInfo->block;
H
Haojun Liao 已提交
4158 4159
  SQuery*          pQuery = pOperator->pRuntimeEnv->pQuery;
  STableGroupInfo* pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4160

H
Haojun Liao 已提交
4161
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4162 4163 4164
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4165

4166
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4167
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4168

4169
    // todo opt
H
Haojun Liao 已提交
4170
    if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4171 4172
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4173 4174 4175 4176 4177 4178 4179 4180
      if (pTableQueryInfo == NULL) {
        break;
      }

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

H
Haojun Liao 已提交
4181
    // this function never returns error?
H
Haojun Liao 已提交
4182
    uint32_t status;
H
Haojun Liao 已提交
4183
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4184
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4185
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4186
    }
H
Haojun Liao 已提交
4187

H
Haojun Liao 已提交
4188
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4189
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4190
      continue;
H
Haojun Liao 已提交
4191 4192 4193 4194
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4195 4196

  return NULL;
H
Haojun Liao 已提交
4197 4198 4199
}

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

H
Haojun Liao 已提交
4202
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4203
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4204
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4205

H
Haojun Liao 已提交
4206 4207
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;

H
Haojun Liao 已提交
4208
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4209
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4210 4211
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4212 4213
    }

H
Haojun Liao 已提交
4214
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4215 4216 4217 4218 4219
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4220
    }
H
Haojun Liao 已提交
4221

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

H
Haojun Liao 已提交
4226
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4227
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4228

H
Haojun Liao 已提交
4229 4230 4231 4232 4233
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4234 4235 4236 4237
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4238

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

H
Haojun Liao 已提交
4243
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4244
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4245

H
Haojun Liao 已提交
4246
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4247
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4248

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

H
Haojun Liao 已提交
4252 4253
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4254 4255
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4256 4257
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4258

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

H
Haojun Liao 已提交
4264
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4265 4266
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4267 4268
    }
  }
H
Haojun Liao 已提交
4269

H
Haojun Liao 已提交
4270 4271 4272
  return NULL;
}

H
Haojun Liao 已提交
4273 4274
static SSDataBlock* doBlockInfoScan(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4275 4276 4277
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4278 4279 4280 4281

  STableScanInfo *pTableScanInfo = pOperator->info;

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

H
Haojun Liao 已提交
4285
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4286
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4287 4288 4289 4290 4291

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

H
Haojun Liao 已提交
4292 4293 4294 4295 4296 4297
  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 已提交
4298

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

H
Haojun Liao 已提交
4302
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4303

H
Haojun Liao 已提交
4304 4305 4306 4307 4308
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
  pOperator->pRuntimeEnv->pQuery->current = taosArrayGetP(g, 0);

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

H
Haojun Liao 已提交
4311
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4312 4313
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4314 4315
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4316
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4317
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4318 4319
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->current      = 0;
H
Haojun Liao 已提交
4320

H
Haojun Liao 已提交
4321
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4322
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4323
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4324 4325
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4326
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4327
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4328
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4329 4330 4331 4332

  return pOperator;
}

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

H
Haojun Liao 已提交
4336 4337 4338 4339 4340
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
  pInfo->order            = pRuntimeEnv->pQuery->order.order;
  pInfo->current          = 0;
H
Haojun Liao 已提交
4341 4342

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4343 4344
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4345 4346 4347 4348
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4349 4350
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4351

H
Haojun Liao 已提交
4352 4353 4354
  return pOperator;
}

H
Haojun Liao 已提交
4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379
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 已提交
4380 4381 4382
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4383 4384 4385
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4386
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4387
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4388

H
Haojun Liao 已提交
4389 4390 4391
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
4392
  } else if (pDownstream->operatorType == OP_TimeWindow) {
H
Haojun Liao 已提交
4393
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4394 4395 4396

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

H
Haojun Liao 已提交
4399
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4400
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4401

H
Haojun Liao 已提交
4402 4403 4404
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4405

H
Haojun Liao 已提交
4406
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4407
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4408

4409 4410
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4411 4412
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4413
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4414
    SArithOperatorInfo *pInfo = pDownstream->info;
4415

4416 4417 4418 4419 4420 4421
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
  } else if (pDownstream->operatorType == OP_SessionWindow) {
    SSWindowOperatorInfo* pInfo = pDownstream->info;

H
Haojun Liao 已提交
4422 4423 4424
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4425 4426 4427
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4428 4429
}

H
Haojun Liao 已提交
4430
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4431 4432 4433 4434
  assert(repeatTime > 0);

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

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4441 4442
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4443
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4444 4445 4446
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4447 4448

  return pOptr;
H
Haojun Liao 已提交
4449 4450
}

H
Haojun Liao 已提交
4451
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4452 4453 4454
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4455
// this is a blocking operator
H
Haojun Liao 已提交
4456
static SSDataBlock* doAggregate(void* param) {
H
Haojun Liao 已提交
4457
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4458
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4459 4460
    return NULL;
  }
H
Haojun Liao 已提交
4461

H
Haojun Liao 已提交
4462
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4463 4464
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4465
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4466

H
Haojun Liao 已提交
4467
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4468
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
4469

H
Haojun Liao 已提交
4470
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4471

H
Haojun Liao 已提交
4472
  while(1) {
H
Haojun Liao 已提交
4473
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4474 4475 4476 4477
    if (pBlock == NULL) {
      break;
    }

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

H
Haojun Liao 已提交
4480
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4481
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4482 4483 4484
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4485
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4486 4487
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4488 4489
  }

H
Haojun Liao 已提交
4490
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4491
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4492

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

H
Haojun Liao 已提交
4496
  return pInfo->pRes;
H
Haojun Liao 已提交
4497 4498
}

H
Haojun Liao 已提交
4499
static SSDataBlock* doSTableAggregate(void* param) {
H
Haojun Liao 已提交
4500
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4501
  if (pOperator->status == OP_EXEC_DONE) {
4502 4503
    return NULL;
  }
H
Haojun Liao 已提交
4504

H
Haojun Liao 已提交
4505
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4506 4507
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4508
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4509

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

H
Haojun Liao 已提交
4513 4514
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4515 4516
    }

H
Haojun Liao 已提交
4517
    return pInfo->pRes;
4518
  }
H
Haojun Liao 已提交
4519

H
Haojun Liao 已提交
4520
  SQuery* pQuery = pRuntimeEnv->pQuery;
4521 4522 4523 4524 4525 4526 4527 4528 4529 4530
  int32_t order = pQuery->order.order;

  SOperatorInfo* upstream = pOperator->upstream;

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

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

H
Haojun Liao 已提交
4533
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4534
      STableScanInfo* pScanInfo = upstream->info;
4535 4536 4537 4538
      order = getTableScanOrder(pScanInfo);
    }

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

4541 4542
    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 已提交
4543
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
4544
  }
H
Haojun Liao 已提交
4545

H
Haojun Liao 已提交
4546 4547
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4548

H
Haojun Liao 已提交
4549
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4550
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4551

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

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

H
Haojun Liao 已提交
4559
  return pInfo->pRes;
4560 4561 4562 4563 4564
}

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

H
Haojun Liao 已提交
4565 4566
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4567
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4568

H
Haojun Liao 已提交
4569 4570 4571 4572
  SSDataBlock* pRes = pInfo->pRes;
  int32_t order = pRuntimeEnv->pQuery->order.order;

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

H
Haojun Liao 已提交
4574
  while(1) {
H
Haojun Liao 已提交
4575
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4576
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4577
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4578
      break;
H
Haojun Liao 已提交
4579 4580
    }

H
Haojun Liao 已提交
4581 4582 4583 4584
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current;

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

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

H
Haojun Liao 已提交
4590 4591
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
H
Haojun Liao 已提交
4592

H
Haojun Liao 已提交
4593 4594
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4595 4596 4597 4598
      break;
    }
  }

H
Haojun Liao 已提交
4599
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4600
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4601 4602 4603 4604
}

static SSDataBlock* doLimit(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4605
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4606
    return NULL;
H
Haojun Liao 已提交
4607 4608
  }

H
Haojun Liao 已提交
4609
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4610

H
Haojun Liao 已提交
4611
  SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4612
  if (pBlock == NULL) {
H
Haojun Liao 已提交
4613
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4614
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4615 4616 4617 4618
    return NULL;
  }

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

H
Haojun Liao 已提交
4621 4622
    pInfo->total = pInfo->limit;

H
Haojun Liao 已提交
4623
    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4624
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4625 4626
  } else {
    pInfo->total += pBlock->info.rows;
H
Haojun Liao 已提交
4627 4628 4629 4630 4631
  }

  return pBlock;
}

H
Haojun Liao 已提交
4632
// TODO add log
H
Haojun Liao 已提交
4633 4634
static SSDataBlock* doOffset(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
H
Haojun Liao 已提交
4635
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4636 4637
    return NULL;
  }
H
Haojun Liao 已提交
4638

H
Haojun Liao 已提交
4639
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4640 4641

  while (1) {
H
Haojun Liao 已提交
4642
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4643
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4644
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4645
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4646 4647 4648
      return NULL;
    }

H
Haojun Liao 已提交
4649
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4650
      return pBlock;
4651
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4652
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4653
    } else {
sangshuduo's avatar
sangshuduo 已提交
4654
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4655 4656 4657 4658 4659 4660
      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 已提交
4661
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4662 4663
      }

H
Haojun Liao 已提交
4664
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4665 4666 4667 4668 4669
      return pBlock;
    }
  }
}

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

H
Haojun Liao 已提交
4676
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4677

H
Haojun Liao 已提交
4678
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4679
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4680 4681
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4682
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4683
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4684 4685 4686 4687
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4690
  int32_t order = pQuery->order.order;
4691
  STimeWindow win = pQuery->window;
H
Haojun Liao 已提交
4692

H
Haojun Liao 已提交
4693
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4694 4695 4696 4697 4698 4699 4700 4701

  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 已提交
4702
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
H
Haojun Liao 已提交
4703
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4704 4705
  }

4706 4707 4708 4709
  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

H
Haojun Liao 已提交
4710
  pOperator->status = OP_RES_TO_RETURN;
4711
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4712
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4713
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4714

H
Haojun Liao 已提交
4715
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4716
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4717

H
Haojun Liao 已提交
4718
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4719
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4720 4721
  }

H
Haojun Liao 已提交
4722
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4723 4724
}

H
Haojun Liao 已提交
4725
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
4726
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4727
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4728 4729 4730
    return NULL;
  }

H
Haojun Liao 已提交
4731
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4732
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4733

H
Haojun Liao 已提交
4734
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4735
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4736
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4737
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4738 4739 4740 4741 4742
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
4743 4744 4745
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
4746
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4747 4748

  while(1) {
H
Haojun Liao 已提交
4749
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4750
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4751
      break;
H
Haojun Liao 已提交
4752 4753
    }

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

H
Haojun Liao 已提交
4757
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4758
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
4759
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
4760

H
Haojun Liao 已提交
4761
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
4762
  }
H
Haojun Liao 已提交
4763

H
Haojun Liao 已提交
4764
  pOperator->status = OP_RES_TO_RETURN;
4765 4766
  pQuery->order.order = order;   // TODO : restore the order
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
4767
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4768

H
Haojun Liao 已提交
4769
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4770
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4771
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4772 4773 4774 4775
  }

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

4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832
static SSDataBlock* doSessionWindowAgg(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

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

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

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

    return pBInfo->pRes;
  }

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

  SOperatorInfo* upstream = pOperator->upstream;

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

    // the pDataBlock are always the same one, no need to call this again
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQuery->order.order);
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

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

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

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

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

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

H
Haojun Liao 已提交
4833
static SSDataBlock* hashGroupbyAggregate(void* param) {
H
Haojun Liao 已提交
4834
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4835
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4836 4837 4838
    return NULL;
  }

H
Haojun Liao 已提交
4839
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
4840

H
Haojun Liao 已提交
4841
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4842
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4843
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4844 4845

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

H
Haojun Liao 已提交
4849
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860
  }

  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 已提交
4861
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
H
Haojun Liao 已提交
4862
    setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4863
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
4864
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
4865 4866
    }

H
Haojun Liao 已提交
4867
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
4868 4869
  }

H
Haojun Liao 已提交
4870
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
4871
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4872
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
4873

H
Haojun Liao 已提交
4874
  if (!pRuntimeEnv->pQuery->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
4875 4876 4877
    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);
4878 4879
  }

H
Haojun Liao 已提交
4880
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
4881
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
4882

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

H
Haojun Liao 已提交
4887
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
4888 4889
}

H
Haojun Liao 已提交
4890 4891
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4892
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4893 4894 4895
    return NULL;
  }

H
Haojun Liao 已提交
4896 4897
  SFillOperatorInfo *pInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4898

H
Haojun Liao 已提交
4899
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
sangshuduo's avatar
sangshuduo 已提交
4900
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4901 4902 4903 4904 4905 4906
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4907
      if (pInfo->totalInputRows == 0) {
H
Haojun Liao 已提交
4908
        pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4909 4910 4911
        return NULL;
      }

H
Haojun Liao 已提交
4912
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
H
Haojun Liao 已提交
4913
    } else {
H
Haojun Liao 已提交
4914 4915
      pInfo->totalInputRows += pBlock->info.rows;

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

H
Haojun Liao 已提交
4918 4919
      taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
H
Haojun Liao 已提交
4920 4921
    }

H
Haojun Liao 已提交
4922
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
4923
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4924 4925
  }
}
H
Haojun Liao 已提交
4926

H
Haojun Liao 已提交
4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938
// 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 已提交
4939 4940 4941 4942 4943
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
4944
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
4945
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
4946 4947
  }

H
Haojun Liao 已提交
4948
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
4949
  tfree(pOperator->info);
H
Haojun Liao 已提交
4950 4951 4952
  tfree(pOperator);
}

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

H
Haojun Liao 已提交
4956 4957 4958 4959
  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 已提交
4960
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
4961

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

H
Haojun Liao 已提交
4964
  pInfo->seed = rand();
H
Haojun Liao 已提交
4965
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed);
H
Haojun Liao 已提交
4966

H
Haojun Liao 已提交
4967
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4968
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
4969
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
4970
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4971
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
4972
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4973
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
4974 4975 4976
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
4977

H
Haojun Liao 已提交
4978 4979
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
4980 4981 4982
  return pOperator;
}

H
Haojun Liao 已提交
4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999
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 已提交
5000
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5001 5002 5003 5004
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5005
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5006
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5007
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5008 5009 5010 5011 5012 5013 5014
}

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

H
Haojun Liao 已提交
5015 5016 5017 5018 5019
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

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

H
Haojun Liao 已提交
5023
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5024

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

5029
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5030 5031
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5032
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5033
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5034
  pOperator->info         = pInfo;
5035
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5036 5037 5038
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5039

H
Haojun Liao 已提交
5040 5041 5042
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5043
  return pOperator;
H
Haojun Liao 已提交
5044 5045
}

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

H
Haojun Liao 已提交
5049
  pInfo->seed = rand();
H
Haojun Liao 已提交
5050
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5051

H
Haojun Liao 已提交
5052
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5053
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5054 5055 5056
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5057
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed);
H
Haojun Liao 已提交
5058 5059

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5060 5061
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5062
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5063
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5064
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5065
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5066 5067 5068
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5069

H
Haojun Liao 已提交
5070 5071 5072
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5073 5074 5075
  return pOperator;
}

H
Haojun Liao 已提交
5076
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5077 5078 5079 5080 5081
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;

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

H
Haojun Liao 已提交
5082 5083
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5084
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5085
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5086
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5087
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5088 5089
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5090 5091 5092 5093

  return pOperator;
}

H
Haojun Liao 已提交
5094
SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5095 5096 5097 5098 5099
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

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

H
Haojun Liao 已提交
5100 5101
  pOperator->name         = "OffsetOperator";
  pOperator->operatorType = OP_Offset;
H
Haojun Liao 已提交
5102
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5103
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5104
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5105
  pOperator->exec         = doOffset;
H
Haojun Liao 已提交
5106 5107
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5108 5109 5110 5111

  return pOperator;
}

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

H
Haojun Liao 已提交
5115
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5116
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5117
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5118 5119 5120

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

H
Haojun Liao 已提交
5121
  pOperator->name         = "TimeIntervalAggOperator";
5122
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5123
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5124
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5125
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5126 5127 5128 5129
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5130
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5131 5132
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5133 5134 5135
  return pOperator;
}

5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160
SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
  SSWindowOperatorInfo* pInfo = calloc(1, sizeof(SSWindowOperatorInfo));

  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);

  pInfo->prevTs = INT64_MIN;
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "SessionWindowAggOperator";
  pOperator->operatorType = OP_SessionWindow;
  pOperator->blockingOptr = true;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doSessionWindowAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

  return pOperator;
}

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

H
Haojun Liao 已提交
5164
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5165
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5166
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5167 5168

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

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

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

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

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

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

H
Haojun Liao 已提交
5206 5207
  return pOperator;
}
H
Haojun Liao 已提交
5208

H
Haojun Liao 已提交
5209
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5210
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5211
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226
  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 已提交
5227 5228 5229

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

H
Haojun Liao 已提交
5230
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5231
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5232 5233 5234
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5235
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5236 5237 5238 5239
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5240

H
Haojun Liao 已提交
5241 5242 5243
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5244 5245 5246
  return pOperator;
}

5247 5248
static SSDataBlock* doTagScan(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5249
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5250 5251
    return NULL;
  }
5252

H
Haojun Liao 已提交
5253
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5254

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

H
Haojun Liao 已提交
5257 5258
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
5259 5260

  int32_t count = 0;
H
Haojun Liao 已提交
5261 5262 5263 5264 5265
  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;
5266 5267 5268 5269
    assert(pQuery->numOfOutput == 1);

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

5271 5272 5273
    count = 0;

    int16_t bytes = pExprInfo->bytes;
H
Haojun Liao 已提交
5274
    int16_t type  = pExprInfo->type;
5275 5276 5277 5278 5279 5280 5281 5282 5283

    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 已提交
5284 5285 5286 5287
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5290
      char *output = pColInfo->pData + count * rsize;
5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307
      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 已提交
5308
      char* data = NULL;
5309
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5310
        data = tsdbGetTableName(item->pTable);
5311
      } else {
H
Haojun Liao 已提交
5312
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5313 5314
      }

H
Haojun Liao 已提交
5315
      doSetTagValueToResultBuf(output, data, type, bytes);
5316 5317 5318
      count += 1;
    }

H
Haojun Liao 已提交
5319
    qDebug("QInfo:%"PRIu64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5320 5321 5322
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5323
    count = 1;
H
Haojun Liao 已提交
5324 5325

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

H
Haojun Liao 已提交
5330 5331 5332
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343

      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 已提交
5344
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5345 5346
        type  = pExprInfo[j].type;
        bytes = pExprInfo[j].bytes;
5347 5348 5349 5350 5351 5352 5353

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

5358 5359 5360
      count += 1;
    }

H
Haojun Liao 已提交
5361 5362 5363 5364
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

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

H
Haojun Liao 已提交
5368
  pRes->info.rows = count;
H
Haojun Liao 已提交
5369
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5370 5371
}

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

H
Haojun Liao 已提交
5376 5377 5378 5379 5380 5381
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5382
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5383
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5384
  pOperator->operatorType = OP_TagScan;
5385
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5386
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5387 5388
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5389 5390
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5391
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5392
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5393

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

5397
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
5398
  int32_t j = 0;
5399

5400
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
5401
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5402
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
5403 5404
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5405
    }
Y
yihaoDeng 已提交
5406
    
H
Haojun Liao 已提交
5407

5408 5409 5410 5411
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
5412

5413 5414
      j += 1;
    }
5415

Y
TD-1230  
yihaoDeng 已提交
5416
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5417
    return TSDB_UD_COLUMN_INDEX;
5418 5419 5420 5421 5422
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
5423

5424
      j += 1;
5425 5426
    }
  }
5427 5428

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5429 5430
}

5431 5432
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
5433
  return j != INT32_MIN;
5434 5435
}

5436
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5437 5438
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5439
    return false;
5440 5441
  }

5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452
  if (pQueryMsg->sw.gap < 0 || pQueryMsg->sw.primaryColId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
    qError("qmsg:%p illegal value of session window time %" PRId64, pQueryMsg, pQueryMsg->sw.gap);
    return false;
  }

  if (pQueryMsg->sw.gap > 0 && pQueryMsg->interval.interval > 0) {
    qError("qmsg:%p illegal value of session window time %" PRId64" and interval value %"PRId64, pQueryMsg,
        pQueryMsg->sw.gap, pQueryMsg->interval.interval);
    return false;
  }

H
hjxilinx 已提交
5453
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5454
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5455
    return false;
5456 5457
  }

H
hjxilinx 已提交
5458
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5459
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5460
    return false;
5461 5462
  }

5463 5464
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5465
    return false;
5466 5467
  }

5468 5469 5470
  return true;
}

5471
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5472 5473 5474 5475
  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;
5476 5477 5478
  }

  if (numOfTotal == 0) {
5479
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
5480 5481 5482 5483
      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 已提交
5484 5485
          (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (pFuncMsg->functionId == TSDB_FUNC_BLKINFO)) {
5486
        continue;
5487
      }
5488

5489
      return false;
5490 5491
    }
  }
5492

5493 5494 5495 5496 5497 5498
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5499
  return true;
5500 5501
}

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

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

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

5510
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5511 5512
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5513

H
hjxilinx 已提交
5514 5515 5516
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5517

H
hjxilinx 已提交
5518 5519
  return pMsg;
}
5520

5521
/**
H
hjxilinx 已提交
5522
 * pQueryMsg->head has been converted before this function is called.
5523
 *
H
hjxilinx 已提交
5524
 * @param pQueryMsg
5525 5526 5527 5528
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5529
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5530 5531
  int32_t code = TSDB_CODE_SUCCESS;

5532 5533 5534 5535
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5536 5537 5538 5539
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5540 5541 5542
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5543 5544
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5545
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5546

5547 5548
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5549
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5550
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5551 5552

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5553
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5554
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5555 5556 5557
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
5558
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
5559
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
5560
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5561
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5562
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5563
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5564
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5565 5566
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
5567

5568
  // query msg safety check
5569
  if (!validateQueryMsg(pQueryMsg)) {
5570 5571
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5572 5573
  }

H
hjxilinx 已提交
5574 5575
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
5576 5577
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
5578
    pColInfo->colId = htons(pColInfo->colId);
5579
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
5580 5581
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
5582

5583 5584 5585 5586 5587
    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;
    }
5588

H
hjxilinx 已提交
5589
    int32_t numOfFilters = pColInfo->numOfFilters;
5590
    if (numOfFilters > 0) {
H
hjxilinx 已提交
5591
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
5592 5593 5594 5595
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
5596 5597 5598
    }

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

5601 5602
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
5603 5604 5605

      pMsg += sizeof(SColumnFilterInfo);

5606 5607
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
5608

5609
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
5610 5611 5612 5613 5614
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

5615
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
5616
        pMsg += (pColFilter->len + 1);
5617
      } else {
5618 5619
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
5620 5621
      }

5622 5623
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
5624 5625 5626
    }
  }

5627 5628
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
5629 5630 5631 5632
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

5633
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
5634

5635
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5636
    param->pExprMsg[i] = pExprMsg;
5637

5638
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
5639
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5640
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5641 5642 5643
    pExprMsg->colType       = htons(pExprMsg->colType);
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5644 5645 5646
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
5647

5648
    pMsg += sizeof(SSqlFuncMsg);
5649 5650

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
5651
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
5652 5653 5654 5655
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
5656
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
5657 5658 5659 5660 5661
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
5662 5663
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
5664
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
5665 5666
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
5667 5668 5669
      }
    }

5670
    pExprMsg = (SSqlFuncMsg *)pMsg;
5671
  }
5672

H
Haojun Liao 已提交
5673 5674
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
5675
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
5676

H
Haojun Liao 已提交
5677
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
5678
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
5679 5680 5681

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5682
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5683 5684 5685
      pExprMsg->colType       = htons(pExprMsg->colType);
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714
      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;
    }
  }

5715
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
5716

H
hjxilinx 已提交
5717
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
5718 5719
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
5720 5721 5722
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5723 5724

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

5728 5729
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
5730

5731 5732
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
5733

5734 5735
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
5736
    }
5737

H
hjxilinx 已提交
5738 5739
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
5740 5741
  }

5742 5743
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
5744
    pQueryMsg->fillVal = (uint64_t)(pMsg);
5745 5746

    int64_t *v = (int64_t *)pMsg;
5747
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5748 5749
      v[i] = htobe64(v[i]);
    }
5750

5751
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
5752
  }
5753

5754
  if (pQueryMsg->numOfTags > 0) {
5755 5756
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
5757 5758 5759 5760
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5761 5762
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
5763

5764 5765 5766 5767
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
5768

5769
      param->pTagColumnInfo[i] = *pTagCol;
5770
      pMsg += sizeof(SColumnInfo);
5771
    }
H
hjxilinx 已提交
5772
  }
5773

5774 5775
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
5776 5777
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
5778 5779 5780
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
5781 5782

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
5783 5784
    pMsg += pQueryMsg->tagCondLen;
  }
5785

5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796
  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 已提交
5797
  if (pQueryMsg->tbnameCondLen > 0) {
5798 5799
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
5800 5801 5802 5803
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

5804
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5805
    pMsg += pQueryMsg->tbnameCondLen;
5806 5807
  }

D
dapan1121 已提交
5808 5809 5810 5811 5812
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

5813
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
5814

5815
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
5816 5817
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
5818
  }
5819

5820
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
5821 5822
         "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,
5823
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
5824
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
5825

5826
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
5827
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
5828 5829

_cleanup:
5830
  freeParam(param);
5831
  return code;
5832 5833
}

H
Haojun Liao 已提交
5834 5835
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
5836 5837

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
5838
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
5839 5840 5841
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
5842
    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 已提交
5843 5844 5845
    return code;
  } END_TRY

H
hjxilinx 已提交
5846
  if (pExprNode == NULL) {
5847
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
5848
    return TSDB_CODE_QRY_APP_ERROR;
5849
  }
5850

5851
  pArithExprInfo->pExpr = pExprNode;
5852 5853 5854
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5855
static int32_t updateOutputBufForTopBotQuery(SQueryTableMsg* pQueryMsg, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874
  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 已提交
5875
// TODO tag length should be passed from client
H
Haojun Liao 已提交
5876 5877
int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                   SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5878
  *pExprInfo = NULL;
H
hjxilinx 已提交
5879
  int32_t code = TSDB_CODE_SUCCESS;
5880

H
Haojun Liao 已提交
5881
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
5882
  if (pExprs == NULL) {
5883
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
5884 5885 5886 5887 5888
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
5889
  for (int32_t i = 0; i < numOfOutput; ++i) {
5890
    pExprs[i].base = *pExprMsg[i];
5891
    pExprs[i].bytes = 0;
5892 5893 5894 5895

    int16_t type = 0;
    int16_t bytes = 0;

5896
    // parse the arithmetic expression
5897
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
5898
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
5899

5900
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5901
        tfree(pExprs);
5902
        return code;
5903 5904
      }

5905
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
5906
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
5907
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
5908 5909 5910
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
5911 5912 5913 5914
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
5915 5916
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
5917 5918
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

5919 5920
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
5921 5922 5923 5924 5925

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
5926
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
5927
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
5928
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
5929 5930 5931 5932 5933 5934 5935
          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 已提交
5936

dengyihao's avatar
dengyihao 已提交
5937
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
5938 5939 5940 5941
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
5942
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
5943

5944 5945
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
5946
      }
5947 5948
    }

S
TD-1057  
Shengliang Guan 已提交
5949
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
H
Haojun Liao 已提交
5950 5951
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
5952 5953 5954 5955
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

5956
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
5957
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
5958
      tfree(pExprs);
5959
      return TSDB_CODE_QRY_INVALID_MSG;
5960 5961
    }

5962
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
5963
      tagLen += pExprs[i].bytes;
5964
    }
5965

5966
    assert(isValidDataType(pExprs[i].type));
5967 5968
  }

H
Haojun Liao 已提交
5969 5970
  // the tag length is affected by other tag columns, so this should be update.
  updateOutputBufForTopBotQuery(pQueryMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
5971

5972
  *pExprInfo = pExprs;
5973 5974 5975
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5976 5977 5978 5979 5980 5981 5982 5983 5984 5985
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 已提交
5986
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009

  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 已提交
6010 6011
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027
    }

    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 已提交
6028
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6029 6030 6031 6032 6033
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6034
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6035
  if (pGroupbyExpr == NULL) {
6036
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6037 6038 6039 6040 6041 6042 6043
    return NULL;
  }

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

6044 6045 6046 6047
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6048

6049 6050 6051
  return pGroupbyExpr;
}

H
Haojun Liao 已提交
6052
static int32_t createFilterInfo(SQuery *pQuery, uint64_t qId) {
6053
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
6054
    if (pQuery->colList[i].numOfFilters > 0) {
6055 6056 6057 6058 6059 6060 6061 6062 6063
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
6064 6065 6066
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6067 6068

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
6069
    if (pQuery->colList[i].numOfFilters > 0) {
6070 6071
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
6072
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
6073
      pFilterInfo->info = pQuery->colList[i];
6074

6075
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
6076
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
6077 6078 6079
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6080 6081 6082

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
6083
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
6084 6085 6086 6087

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
H
Haojun Liao 已提交
6088
          qError("QInfo:%"PRIu64" invalid filter info", qId);
6089
          return TSDB_CODE_QRY_INVALID_MSG;
6090 6091
        }

6092 6093
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
H
Haojun Liao 已提交
6094
          qError("QInfo:%"PRIu64" invalid filter info", qId);
6095
          return TSDB_CODE_QRY_INVALID_MSG;
6096 6097
        }

6098
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
6099 6100 6101 6102 6103 6104 6105 6106 6107
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6108
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
6109
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
6110

6111
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
6112
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
6113
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6114 6115
      continue;
    }
6116

6117
    // todo opt performance
H
Haojun Liao 已提交
6118
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6119
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6120 6121
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
6122 6123
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
6124 6125 6126
          break;
        }
      }
H
Haojun Liao 已提交
6127 6128

      assert(f < pQuery->numOfCols);
6129 6130
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6131 6132 6133
    } 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);
6134
    } else {
6135 6136
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
6137 6138
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
6139 6140
          break;
        }
6141
      }
6142

Y
yihaoDeng 已提交
6143
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6144 6145 6146 6147
    }
  }
}

H
Haojun Liao 已提交
6148 6149 6150 6151 6152 6153 6154 6155
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 已提交
6156

6157
  if (isProjQuery(pQuery)) {
H
Haojun Liao 已提交
6158 6159 6160
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQuery->resultRowSize;
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6161
    }
H
Haojun Liao 已提交
6162

H
Haojun Liao 已提交
6163
    pResultInfo->capacity  = numOfRes;
6164
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6165
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6166
  }
H
Haojun Liao 已提交
6167 6168 6169

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

D
fix bug  
dapan1121 已提交
6172 6173 6174 6175
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6176 6177
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery,
D
dapan1121 已提交
6178
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6179 6180 6181
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6182 6183
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6184
    goto _cleanup_qinfo;
6185
  }
6186

B
Bomin Zhang 已提交
6187 6188
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6189
  SQuery* pQuery = &pQInfo->query;
6190 6191
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
6192
  pQuery->tableGroupInfo  = *pTableGroupInfo;
6193
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
6194
  pQuery->numOfOutput     = numOfOutput;
6195 6196 6197
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
6198
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
6199
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
6200 6201
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
6202
  pQuery->pGroupbyExpr    = pGroupbyExpr;
6203
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
6204
  pQuery->fillType        = pQueryMsg->fillType;
6205
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
6206
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
6207 6208
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
6209
  pQuery->sw              = pQueryMsg->sw;
6210
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
6211
  if (pQuery->colList == NULL) {
6212
    goto _cleanup;
6213
  }
6214

6215 6216
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
6217
  for (int16_t i = 0; i < numOfCols; ++i) {
6218
    pQuery->colList[i] = pQueryMsg->colList[i];
6219
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
6220 6221 6222 6223 6224

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
6225
  }
6226

6227
  // calculate the result row size
6228 6229
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
6230 6231 6232 6233 6234 6235
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
6236
  }
6237

6238
  doUpdateExprColumnIndex(pQuery);
H
Haojun Liao 已提交
6239
  int32_t ret = createFilterInfo(pQuery, pQInfo->qId);
6240
  if (ret != TSDB_CODE_SUCCESS) {
6241
    goto _cleanup;
6242 6243
  }

6244
  if (pQuery->fillType != TSDB_FILL_NONE) {
6245 6246
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
6247
      goto _cleanup;
6248 6249 6250
    }

    // the first column is the timestamp
6251
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
6252 6253
  }

dengyihao's avatar
dengyihao 已提交
6254 6255 6256
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6257
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6258

6259 6260 6261
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6262
  }
H
Haojun Liao 已提交
6263

H
Haojun Liao 已提交
6264
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6265 6266 6267 6268
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6269
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6270
  pQInfo->rspContext = NULL;
6271
  pQInfo->sql = sql;
6272
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6273
  tsem_init(&pQInfo->ready, 0, 0);
6274 6275 6276 6277

  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
6278
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6279 6280
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

6281
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
6282

H
Haojun Liao 已提交
6283
  int32_t index = 0;
H
hjxilinx 已提交
6284
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6285
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
6286

H
Haojun Liao 已提交
6287
    size_t s = taosArrayGetSize(pa);
6288
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6289 6290 6291
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6292

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

H
hjxilinx 已提交
6295
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6296
      STableKeyInfo* info = taosArrayGet(pa, j);
6297
      window.skey = info->lastKey;
6298 6299

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
6300
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
6301 6302 6303
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6304

6305
      item->groupIndex = i;
H
hjxilinx 已提交
6306
      taosArrayPush(p1, &item);
6307 6308

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6309
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6310
      index += 1;
H
hjxilinx 已提交
6311 6312
    }
  }
6313

H
Haojun Liao 已提交
6314
  colIdCheck(pQuery, pQInfo->qId);
6315

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

D
fix bug  
dapan1121 已提交
6319 6320 6321
  pQInfo->qId = atomic_add_fetch_64(&queryHandleId, 1);
  *qId = pQInfo->qId;
  qDebug("qmsg:%p QInfo:%" PRIu64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6322 6323
  return pQInfo;

B
Bomin Zhang 已提交
6324
_cleanup_qinfo:
H
Haojun Liao 已提交
6325
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6326

6327 6328 6329 6330
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6331

S
TD-1848  
Shengliang Guan 已提交
6332
  tfree(pTagCols);
B
Bomin Zhang 已提交
6333 6334 6335
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6336 6337
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6338 6339
    }
  }
H
Haojun Liao 已提交
6340

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

6343
_cleanup:
dengyihao's avatar
dengyihao 已提交
6344
  freeQInfo(pQInfo);
6345 6346 6347
  return NULL;
}

H
Haojun Liao 已提交
6348
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6349 6350 6351 6352
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6353

H
hjxilinx 已提交
6354 6355 6356 6357
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6358
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6359 6360 6361
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6362
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
6363
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6364 6365

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6366 6367 6368
  pRuntimeEnv->qinfo = pQInfo;

  SQuery *pQuery = pRuntimeEnv->pQuery;
6369

6370
  STSBuf *pTsBuf = NULL;
6371
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
6372
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
6373
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
6374

6375 6376
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
6377

dengyihao's avatar
dengyihao 已提交
6378
    UNUSED(ret);
H
hjxilinx 已提交
6379
  }
6380

6381 6382 6383
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
D
dapan1121 已提交
6384 6385
    
    pRuntimeEnv->prevResult = prevResult;    
6386 6387
  }

Y
TD-1665  
yihaoDeng 已提交
6388
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
6389

6390 6391
  if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
H
Haojun Liao 已提交
6392
    qDebug("QInfo:%"PRIu64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQuery->window.skey,
6393
           pQuery->window.ekey, pQuery->order.order);
H
Haojun Liao 已提交
6394
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6395
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6396
    // todo free memory
6397 6398
    return TSDB_CODE_SUCCESS;
  }
6399

H
Haojun Liao 已提交
6400
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
6401
    qDebug("QInfo:%"PRIu64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
6402
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6403 6404
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6405 6406

  // filter the qualified
D
dapan1121 已提交
6407
  if ((code = doInitQInfo(pQInfo, pTsBuf, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6408 6409
    goto _error;
  }
6410

H
hjxilinx 已提交
6411 6412 6413 6414
  return code;

_error:
  // table query ref will be decrease during error handling
6415
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6416 6417 6418
  return code;
}

H
Haojun Liao 已提交
6419
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6420
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6421 6422
      return;
    }
H
Haojun Liao 已提交
6423

B
Bomin Zhang 已提交
6424 6425 6426 6427 6428
    for (int32_t i = 0; i < numOfFilters; i++) {
      if (pFilter[i].filterstr) {
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6429

B
Bomin Zhang 已提交
6430 6431 6432
    free(pFilter);
}

H
Haojun Liao 已提交
6433 6434
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6435
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456
    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 已提交
6457 6458 6459 6460 6461 6462 6463 6464
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 已提交
6465
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6466 6467 6468 6469 6470 6471 6472
    }
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6473
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6474 6475 6476
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6477

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

H
Haojun Liao 已提交
6480
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6481
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
6482 6483 6484

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);

6485
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6486

H
Haojun Liao 已提交
6487 6488 6489
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
6490
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
6491
    }
6492

H
Haojun Liao 已提交
6493 6494 6495
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
6496
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
6497
      }
H
hjxilinx 已提交
6498
    }
6499

H
Haojun Liao 已提交
6500 6501
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
6502

S
TD-1848  
Shengliang Guan 已提交
6503 6504
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
6505 6506 6507 6508 6509 6510

    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 已提交
6511
      tfree(pQuery->colList);
H
Haojun Liao 已提交
6512 6513
    }

H
Haojun Liao 已提交
6514 6515 6516 6517
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
6518
  }
6519

H
Haojun Liao 已提交
6520

S
TD-1848  
Shengliang Guan 已提交
6521
  tfree(pQInfo->pBuf);
6522 6523
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
6524
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
6525

H
Haojun Liao 已提交
6526
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
6527
  pQInfo->signature = 0;
6528

H
Haojun Liao 已提交
6529
  qDebug("QInfo:%"PRIu64" QInfo is freed", pQInfo->qId);
6530

S
TD-1848  
Shengliang Guan 已提交
6531
  tfree(pQInfo);
H
hjxilinx 已提交
6532 6533
}

H
Haojun Liao 已提交
6534
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
6535
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
6536
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
hjxilinx 已提交
6537
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6538

H
hjxilinx 已提交
6539
  // load data from file to msg buffer
H
Haojun Liao 已提交
6540
  if (isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
6541 6542
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
6543

H
hjxilinx 已提交
6544
    // make sure file exist
D
fix bug  
dapan1121 已提交
6545 6546
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
6547
      assert(s == pRuntimeEnv->outputBuf->info.rows);
6548

H
Haojun Liao 已提交
6549
      qDebug("QInfo:%"PRIu64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
6550 6551
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
6552
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
6553
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
6554 6555
          assert(0);
        }
H
Haojun Liao 已提交
6556
      } else {
6557
        UNUSED(s);
D
dapan1121 已提交
6558 6559 6560 6561
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
6562
      // dump error info
D
dapan1121 已提交
6563 6564 6565
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
6566
      }
H
Haojun Liao 已提交
6567

D
fix bug  
dapan1121 已提交
6568
      fclose(f);
H
hjxilinx 已提交
6569
    }
6570

H
hjxilinx 已提交
6571
    // all data returned, set query over
H
Haojun Liao 已提交
6572 6573
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
6574
    }
H
hjxilinx 已提交
6575
  } else {
H
Haojun Liao 已提交
6576
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
6577
  }
6578

H
Haojun Liao 已提交
6579
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
6580
  qDebug("QInfo:%"PRIu64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
6581
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
6582

H
Haojun Liao 已提交
6583
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
6584
    qDebug("QInfo:%"PRIu64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQuery->limit.limit);
H
Haojun Liao 已提交
6585
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
6586
  }
6587

H
hjxilinx 已提交
6588
  return TSDB_CODE_SUCCESS;
6589 6590
}

H
Haojun Liao 已提交
6591
bool doBuildResCheck(SQInfo* pQInfo) {
6592 6593 6594 6595 6596
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
6597
  buildRes = needBuildResAfterQueryComplete(pQInfo);
6598

H
Haojun Liao 已提交
6599 6600
  // 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 已提交
6601
  assert(pQInfo->owner == taosGetSelfPthreadId());
6602
  pQInfo->owner = 0;
H
Haojun Liao 已提交
6603

H
Haojun Liao 已提交
6604
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
6605

6606
  // used in retrieve blocking model.
H
Haojun Liao 已提交
6607
  tsem_post(&pQInfo->ready);
6608 6609 6610
  return buildRes;
}

H
Haojun Liao 已提交
6611 6612 6613 6614
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
6615 6616
  }

6617 6618 6619
  if (IS_VAR_DATA_TYPE(type)) {
    // Binary data overflows for sort of unknown reasons. Let trim the overflow data
    if (varDataTLen(val) > bytes) {
H
Haojun Liao 已提交
6620
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
6621 6622 6623 6624 6625
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
6626
  } else {
H
Haojun Liao 已提交
6627
    memcpy(output, val, bytes);
6628 6629 6630
  }
}

H
Haojun Liao 已提交
6631
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
6632 6633 6634 6635
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
6636
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
6637 6638
}

H
Haojun Liao 已提交
6639
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
6640
  int64_t t = getQuerySupportBufSize(numOfTables);
6641
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6642
    return TSDB_CODE_SUCCESS;
6643
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
6644 6645

    while(1) {
6646
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
6647 6648
      int64_t remain = s - t;
      if (remain >= 0) {
6649
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661
          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 已提交
6662
void releaseQueryBuf(size_t numOfTables) {
6663
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6664 6665 6666 6667 6668 6669
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
6670
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
6671
}