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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

101

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

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

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

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

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

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

  uid |= sid;

D
fix bug  
dapan1121 已提交
127 128
  qDebug("gen qid:0x%"PRIx64, uid);

D
dapan1121 已提交
129 130 131 132 133
  return uid;
}



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

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

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

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

S
Shengliang Guan 已提交
159
  mon = (int)(mon + interval);
160 161 162 163 164 165 166 167 168 169 170
  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 已提交
171
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
172
static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
173
    int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
174

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

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

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

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

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

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

H
Haojun Liao 已提交
194 195
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 已提交
196
static SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv);
H
Haojun Liao 已提交
197

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

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

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

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

H
Haojun Liao 已提交
224 225
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 已提交
226
static bool isPointInterpoQuery(SQuery *pQuery);
H
Haojun Liao 已提交
227 228 229
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 已提交
230
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
231 232 233
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
234

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

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

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

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

  return res;
H
Haojun Liao 已提交
254 255
}

H
Haojun Liao 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
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 已提交
273
int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
274 275 276
  SQuery *pQuery = pRuntimeEnv->pQuery;
  bool    hasMainFunction = hasMainOutput(pQuery);

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

    /*
     * 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 已提交
285
    if (hasMainFunction && (id == TSDB_FUNC_TS || id == TSDB_FUNC_TAG || id == TSDB_FUNC_TAGPRJ)) {
H
Haojun Liao 已提交
286 287 288 289 290 291 292 293 294 295 296 297 298
      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 已提交
299
static void clearNumOfRes(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
300 301 302 303 304 305
  for (int32_t j = 0; j < numOfOutput; ++j) {
    SResultRowCellInfo *pResInfo = GET_RES_INFO(&pCtx[j]);
    pResInfo->numOfRes = 0;
  }
}

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

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

319 320 321
      return true;
    }
  }
322

323 324 325
  return false;
}

H
Haojun Liao 已提交
326
static bool isStabledev(SQuery* pQuery) {
327 328 329 330 331 332 333 334 335 336
  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 已提交
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
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);
}
355

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

  return true;
}

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

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

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

381 382 383
  return false;
}

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

  return false;
}

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

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

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
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 已提交
451
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
452
                                             int16_t bytes, bool masterscan, uint64_t uid) {
453
  bool existed = false;
H
Haojun Liao 已提交
454
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

  SResultRow **p1 =
      (SResultRow **)taosHashGet(pRuntimeEnv->pResultRowHashTable, pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));

  // in case of repeat scan/reverse scan, no new time window added.
  if (QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQuery)) {
    if (!masterscan) {  // the *p1 may be NULL in case of sliding+offset exists.
      return (p1 != NULL)? *p1:NULL;
    }

    if (p1 != NULL) {
      for(int32_t i = pResultRowInfo->size - 1; i >= 0; --i) {
        if (pResultRowInfo->pResult[i] == (*p1)) {
          pResultRowInfo->curIndex = i;
          existed = true;
          break;
        }
      }
    }
474
  } else {
475 476
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
477
    }
478
  }
479

480
  if (!existed) {
481
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
482

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

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

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

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

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
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;
    }
  }
}

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

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

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

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

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

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

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

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

586 587 588
  return w;
}

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

595
  tFilePage *pData = NULL;
596

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

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

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

618 619 620
  if (pData == NULL) {
    return -1;
  }
621

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

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

631 632 633
  return 0;
}

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

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

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

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

659 660 661
  return TSDB_CODE_SUCCESS;
}

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
759 760 761
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))) {
762 763 764
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
765
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
766
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQuery->timeWindowInterpo);
767
  }
768 769 770
}

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

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

H
hjxilinx 已提交
778
  STableQueryInfo* item = pQuery->current;
779

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

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

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

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

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

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

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

H
Haojun Liao 已提交
830
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
831

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

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

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


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

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

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

H
Haojun Liao 已提交
872
  int32_t startPos = 0;
H
Haojun Liao 已提交
873

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

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

H
Haojun Liao 已提交
920
  return startPos;
921 922
}

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

937 938 939
  return ekey;
}

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

952
// window start key interpolation
H
Haojun Liao 已提交
953

954

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

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

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

  return ts;
}

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

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

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
1140 1141
  bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);

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

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

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

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

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

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

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

H
Haojun Liao 已提交
1254
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1255

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1374
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1375 1376 1377 1378 1379 1380 1381
    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 已提交
1382 1383 1384 1385
      if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
        setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, val, bytes);
      }

H
Haojun Liao 已提交
1386 1387 1388 1389 1390
      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 已提交
1391 1392
    }

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

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
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 已提交
1463
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
  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 已提交
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
}

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

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

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

H
Haojun Liao 已提交
1510
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
  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 已提交
1528
  return -1;
H
Haojun Liao 已提交
1529 1530
}

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

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

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

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

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

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

1559 1560 1561
  return true;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

1658
    pCtx->ptsOutputBuf = NULL;
1659

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

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
1727 1728
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1729
  return pFuncCtx;
H
Haojun Liao 已提交
1730 1731
}

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

H
Haojun Liao 已提交
1764 1765 1766
  // 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 已提交
1767 1768
  pRuntimeEnv->sasArray = calloc(pQuery->numOfOutput, sizeof(SArithmeticSupport));

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

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

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

H
Haojun Liao 已提交
1784
  qDebug("QInfo:0x%"PRIx64" init runtime environment completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1785 1786

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

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

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

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

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

1816 1817 1818 1819 1820 1821 1822
    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 已提交
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
    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);
    }
1834

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

H
Haojun Liao 已提交
1837 1838
    if (pQuery->pExpr2 != NULL) {
      pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQuery->pExpr2, pQuery->numOfExpr2);
H
Haojun Liao 已提交
1839
    }
H
Haojun Liao 已提交
1840 1841 1842 1843 1844 1845
  } 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 已提交
1846
    }
H
Haojun Liao 已提交
1847
  }
H
Haojun Liao 已提交
1848

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

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

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

  return TSDB_CODE_SUCCESS;
1862

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

1870
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1871 1872
}

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

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

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

D
dapan1121 已提交
1883
static void destroyTsComp(SQueryRuntimeEnv *pRuntimeEnv, SQuery *pQuery) {
D
dapan1121 已提交
1884
  if (isTsCompQuery(pQuery) && pRuntimeEnv->outputBuf && pRuntimeEnv->outputBuf->pDataBlock && taosArrayGetSize(pRuntimeEnv->outputBuf->pDataBlock) > 0) {
D
dapan1121 已提交
1885
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
D
dapan1121 已提交
1886 1887 1888 1889 1890 1891
    if (pColInfoData) {
      FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
      if (f) {
        fclose(f);
        *(FILE **)pColInfoData->pData = NULL;
      }
D
dapan1121 已提交
1892 1893 1894 1895
    }
  }
}

H
Haojun Liao 已提交
1896
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
1897
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
1898
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1899

H
Haojun Liao 已提交
1900
  qDebug("QInfo:0x%"PRIx64" teardown runtime env", pQInfo->qId);
1901

1902 1903 1904
  if (pRuntimeEnv->sasArray != NULL) {
    for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
      tfree(pRuntimeEnv->sasArray[i].data);
H
Haojun Liao 已提交
1905
      tfree(pRuntimeEnv->sasArray[i].colList);
1906 1907 1908 1909 1910
    }

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1911
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1912
  doFreeQueryHandle(pRuntimeEnv);
1913

D
dapan1121 已提交
1914 1915
  destroyTsComp(pRuntimeEnv, pQuery);
  
H
Haojun Liao 已提交
1916
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1917

S
TD-1848  
Shengliang Guan 已提交
1918
  tfree(pRuntimeEnv->keyBuf);
1919
  tfree(pRuntimeEnv->prevRow);
1920 1921
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1922 1923
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1924

H
Haojun Liao 已提交
1925 1926 1927
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1928
  destroyOperatorInfo(pRuntimeEnv->proot);
D
dapan1121 已提交
1929 1930 1931 1932 1933

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

1934 1935
}

1936 1937 1938 1939
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1940
bool isQueryKilled(SQInfo *pQInfo) {
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
  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 已提交
1951 1952
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1953 1954 1955 1956 1957 1958
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
1961
static bool isFixedOutputQuery(SQuery* pQuery) {
H
Haojun Liao 已提交
1962
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
1963 1964
    return false;
  }
1965

1966
  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1967
  if (pQuery->topBotQuery || pQuery->groupbyColumn || isTsCompQuery(pQuery)) {
1968 1969
    return true;
  }
1970

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

1974 1975
    // ignore the ts_comp function
    if (i == 0 && pExprMsg->functionId == TSDB_FUNC_PRJ && pExprMsg->numOfParams == 1 &&
1976
        pExprMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
1977 1978
      continue;
    }
1979

1980 1981 1982
    if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
      continue;
    }
1983

H
Haojun Liao 已提交
1984
    if (!IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status)) {
1985 1986 1987
      return true;
    }
  }
1988

1989 1990 1991
  return false;
}

1992
// todo refactor with isLastRowQuery
1993
bool isPointInterpoQuery(SQuery *pQuery) {
1994
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
1995 1996
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
    if (functionId == TSDB_FUNC_INTERP) {
1997 1998 1999
      return true;
    }
  }
2000

2001 2002 2003 2004
  return false;
}

// TODO REFACTOR:MERGE WITH CLIENT-SIDE FUNCTION
2005
static UNUSED_FUNC bool isSumAvgRateQuery(SQuery *pQuery) {
2006
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2007
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2008 2009 2010
    if (functionId == TSDB_FUNC_TS) {
      continue;
    }
2011

2012 2013 2014 2015 2016
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
2017

2018 2019 2020
  return false;
}

H
hjxilinx 已提交
2021
static bool isFirstLastRowQuery(SQuery *pQuery) {
2022
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2023
    int32_t functionID = pQuery->pExpr1[i].base.functionId;
2024 2025 2026 2027
    if (functionID == TSDB_FUNC_LAST_ROW) {
      return true;
    }
  }
2028

2029 2030 2031
  return false;
}

H
hjxilinx 已提交
2032
static bool needReverseScan(SQuery *pQuery) {
2033
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2034
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2035 2036 2037
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG) {
      continue;
    }
2038

2039
    if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
2040 2041
      return true;
    }
2042 2043

    if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
H
Haojun Liao 已提交
2044
      // the scan order to acquire the last result of the specified column
H
Haojun Liao 已提交
2045
      int32_t order = (int32_t)pQuery->pExpr1[i].base.arg->argValue.i64;
H
Haojun Liao 已提交
2046 2047 2048
      if (order != pQuery->order.order) {
        return true;
      }
2049
    }
2050
  }
2051

2052 2053
  return false;
}
H
hjxilinx 已提交
2054

H
Haojun Liao 已提交
2055 2056 2057 2058
/**
 * 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 已提交
2059
bool onlyQueryTags(SQuery* pQuery) {
H
hjxilinx 已提交
2060
  for(int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2061
    SExprInfo* pExprInfo = &pQuery->pExpr1[i];
H
Haojun Liao 已提交
2062 2063

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
2064 2065 2066 2067

    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 已提交
2068
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
2069 2070 2071
      return false;
    }
  }
2072

H
hjxilinx 已提交
2073 2074 2075
  return true;
}

2076 2077
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2078
void getAlignQueryTimeWindow(SQuery *pQuery, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
2079 2080
  assert(key >= keyFirst && key <= keyLast && pQuery->interval.sliding <= pQuery->interval.interval);
  win->skey = taosTimeTruncate(key, &pQuery->interval, pQuery->precision);
H
Haojun Liao 已提交
2081 2082

  /*
2083
   * if the realSkey > INT64_MAX - pQuery->interval.interval, the query duration between
H
Haojun Liao 已提交
2084 2085
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
2086 2087
  if (keyFirst > (INT64_MAX - pQuery->interval.interval)) {
    assert(keyLast - keyFirst < pQuery->interval.interval);
2088
    win->ekey = INT64_MAX;
2089 2090
  } 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 已提交
2091
  } else {
2092
    win->ekey = win->skey + pQuery->interval.interval - 1;
2093 2094 2095 2096 2097
  }
}

static void setScanLimitationByResultBuffer(SQuery *pQuery) {
  if (isTopBottomQuery(pQuery)) {
H
Haojun Liao 已提交
2098
    pQuery->checkResultBuf = 0;
2099
  } else if (isGroupbyColumn(pQuery->pGroupbyExpr)) {
H
Haojun Liao 已提交
2100
    pQuery->checkResultBuf = 0;
2101 2102
  } else {
    bool hasMultioutput = false;
2103
    for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2104
      SSqlFuncMsg *pExprMsg = &pQuery->pExpr1[i].base;
2105 2106 2107
      if (pExprMsg->functionId == TSDB_FUNC_TS || pExprMsg->functionId == TSDB_FUNC_TS_DUMMY) {
        continue;
      }
2108

H
Haojun Liao 已提交
2109
      hasMultioutput = IS_MULTIOUTPUT(aAggs[pExprMsg->functionId].status);
2110 2111 2112 2113
      if (!hasMultioutput) {
        break;
      }
    }
2114

H
Haojun Liao 已提交
2115
    pQuery->checkResultBuf = hasMultioutput ? 1 : 0;
2116 2117 2118 2119 2120 2121
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2122
bool colIdCheck(SQuery *pQuery, uint64_t qId) {
2123 2124
  // load data column information is incorrect
  for (int32_t i = 0; i < pQuery->numOfCols - 1; ++i) {
2125
    if (pQuery->colList[i].colId == pQuery->colList[i + 1].colId) {
H
Haojun Liao 已提交
2126
      qError("QInfo:0x%"PRIx64" invalid data load column for query", qId);
2127 2128 2129
      return false;
    }
  }
2130

2131 2132 2133 2134 2135 2136
  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) {
2137
  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2138
    int32_t functionId = pQuery->pExpr1[i].base.functionId;
2139

2140 2141 2142 2143
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2144

2145 2146 2147 2148
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2149

2150 2151 2152 2153 2154 2155 2156
  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); }

H
Haojun Liao 已提交
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
static int32_t updateBlockLoadStatus(SQuery *pQuery, int32_t status) {
  bool hasFirstLastFunc = false;
  bool hasOtherFunc = false;

  if (status == BLK_DATA_ALL_NEEDED || status == BLK_DATA_DISCARD) {
    return status;
  }

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

    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }

    if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) {
      hasFirstLastFunc = true;
    } else {
      hasOtherFunc = true;
    }
  }

  if (hasFirstLastFunc && status == BLK_DATA_NO_NEEDED) {
    if(!hasOtherFunc) {
      return BLK_DATA_DISCARD;
    } else{
      return BLK_DATA_ALL_NEEDED;
    }
  }

  return status;
}

2191
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2192 2193
  SQuery* pQuery = &pQInfo->query;
  size_t t = taosArrayGetSize(pQuery->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2194
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2195
    SArray* p1 = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2196 2197 2198

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

2201 2202 2203 2204
      // 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 已提交
2205 2206 2207 2208
    }
  }
}

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

2212
  // in case of point-interpolation query, use asc order scan
H
Haojun Liao 已提交
2213
  char msg[] = "QInfo:0x%"PRIx64" scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64
2214
               "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64;
2215

2216 2217
  // 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 已提交
2218
  if (isFirstLastRowQuery(pQuery)) {
H
Haojun Liao 已提交
2219
    qDebug("QInfo:0x%"PRIx64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId, pQuery->order.order, TSDB_ORDER_ASC);
2220

H
Haojun Liao 已提交
2221
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2222 2223 2224
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2225

2226 2227
    return;
  }
2228

2229
  if (isGroupbyColumn(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) {
H
Haojun Liao 已提交
2230
    pQuery->order.order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
2231 2232 2233
    if (pQuery->window.skey > pQuery->window.ekey) {
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
H
Haojun Liao 已提交
2234

2235
    doExchangeTimeWindow(pQInfo, &pQuery->window);
H
Haojun Liao 已提交
2236 2237 2238
    return;
  }

2239
  if (isPointInterpoQuery(pQuery) && pQuery->interval.interval == 0) {
H
Haojun Liao 已提交
2240
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2241
      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 已提交
2242 2243
      SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
    }
2244

2245
    pQuery->order.order = TSDB_ORDER_ASC;
2246 2247
    return;
  }
2248

2249
  if (pQuery->interval.interval == 0) {
2250 2251
    if (onlyFirstQuery(pQuery)) {
      if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2252
        qDebug(msg, pQInfo->qId, "only-first", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey,
2253 2254
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2255
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2256
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2257
      }
2258

2259
      pQuery->order.order = TSDB_ORDER_ASC;
2260 2261
    } else if (onlyLastQuery(pQuery)) {
      if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2262
        qDebug(msg, pQInfo->qId, "only-last", pQuery->order.order, TSDB_ORDER_DESC, pQuery->window.skey,
2263 2264
               pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2265
        SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2266
        doExchangeTimeWindow(pQInfo, &pQuery->window);
2267
      }
2268

2269
      pQuery->order.order = TSDB_ORDER_DESC;
2270
    }
2271

2272
  } else {  // interval query
2273
    if (stableQuery) {
2274 2275
      if (onlyFirstQuery(pQuery)) {
        if (!QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2276
          qDebug(msg, pQInfo->qId, "only-first stable", pQuery->order.order, TSDB_ORDER_ASC,
2277 2278
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2279
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2280
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2281
        }
2282

2283
        pQuery->order.order = TSDB_ORDER_ASC;
2284 2285
      } else if (onlyLastQuery(pQuery)) {
        if (QUERY_IS_ASC_QUERY(pQuery)) {
H
Haojun Liao 已提交
2286
          qDebug(msg, pQInfo->qId, "only-last stable", pQuery->order.order, TSDB_ORDER_DESC,
2287 2288
                 pQuery->window.skey, pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey);

2289
          SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);
2290
          doExchangeTimeWindow(pQInfo, &pQuery->window);
2291
        }
2292

2293
        pQuery->order.order = TSDB_ORDER_DESC;
2294 2295 2296 2297 2298
      }
    }
  }
}

2299 2300
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2301
  int32_t MIN_ROWS_PER_PAGE = 4;
2302

H
Haojun Liao 已提交
2303
  *rowsize = (int32_t)(pQuery->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pQuery->topBotQuery, pQuery->stableQuery));
2304 2305 2306 2307
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2312 2313
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2314 2315
}

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

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

H
Haojun Liao 已提交
2321
  if (pDataStatis == NULL || pQuery->numOfFilterCols == 0) {
2322 2323 2324 2325 2326
    return true;
  }

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

H
Haojun Liao 已提交
2328 2329 2330 2331 2332 2333 2334 2335
    int32_t index = -1;
    for(int32_t i = 0; i < pQuery->numOfCols; ++i) {
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2336
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2337
    if (index == -1) {
H
Haojun Liao 已提交
2338
      return true;
2339
    }
2340

2341
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2342
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2343
      return true;
2344
    }
2345

2346
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2347
    if (pDataStatis[index].numOfNull == numOfRows) {
2348 2349 2350 2351

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2352
        if (pFilterElem->fp == isNullOperator) {
2353 2354 2355 2356
          return true;
        }
      }

2357 2358
      continue;
    }
2359

H
Haojun Liao 已提交
2360 2361 2362
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2366
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2367
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2368 2369 2370 2371 2372
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2373
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2374 2375 2376 2377 2378
          return true;
        }
      }
    }
  }
2379

H
Haojun Liao 已提交
2380
  return false;
2381 2382
}

H
Haojun Liao 已提交
2383 2384 2385 2386 2387 2388 2389 2390
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 已提交
2391
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2392

H
Haojun Liao 已提交
2393
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2394 2395 2396 2397
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2398
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2399
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2400 2401 2402
        break;
      }

H
Haojun Liao 已提交
2403 2404
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2405 2406 2407 2408 2409
        return true;
      }
    }
  } else {
    getAlignQueryTimeWindow(pQuery, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2410 2411 2412
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2413 2414 2415 2416
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2417
      getNextTimeWindow(pQuery, &w);
H
Haojun Liao 已提交
2418 2419 2420 2421
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2422 2423
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2424 2425 2426 2427 2428 2429 2430 2431
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456
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;
}
2457

H
Haojun Liao 已提交
2458
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
H
Haojun Liao 已提交
2459
                        SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2460 2461 2462 2463 2464
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2465
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485
    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 已提交
2486 2487 2488

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

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

H
Haojun Liao 已提交
2496 2497 2498
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2499

H
Haojun Liao 已提交
2500 2501 2502 2503 2504 2505 2506 2507
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2508
          } else {
H
Haojun Liao 已提交
2509 2510 2511 2512 2513 2514
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2515
          }
H
Haojun Liao 已提交
2516 2517

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2518 2519 2520 2521 2522
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2523
        if (!qualified) {
H
Haojun Liao 已提交
2524 2525 2526 2527
          break;
        }
      }

H
Haojun Liao 已提交
2528
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2529
      if (!qualified) {
H
Haojun Liao 已提交
2530
        all = false;
H
Haojun Liao 已提交
2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547
      }
    }
  }

  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 已提交
2548
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2549 2550 2551
          }

          start += len;
2552
          len = 0;
H
Haojun Liao 已提交
2553 2554 2555 2556
        }
      }
    }

2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
    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 已提交
2570 2571 2572 2573
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

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

H
Haojun Liao 已提交
2578 2579
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
H
Haojun Liao 已提交
2580 2581 2582 2583 2584 2585
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2586 2587 2588
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 已提交
2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
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 已提交
2626 2627
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2628
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2629
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2630
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2631

H
Haojun Liao 已提交
2632
  SQInfo* pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2633
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
2634

H
Haojun Liao 已提交
2635
  int64_t groupId = pQuery->current->groupIndex;
H
Haojun Liao 已提交
2636
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQuery);
H
Haojun Liao 已提交
2637 2638 2639

  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2640
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2641
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2642

H
Haojun Liao 已提交
2643
    if (pQuery->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2644 2645 2646 2647 2648 2649 2650
      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 已提交
2651
      setTimestampListJoinInfo(pRuntimeEnv, &t, pQuery->current);
H
Haojun Liao 已提交
2652 2653 2654 2655 2656 2657

      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 已提交
2658 2659 2660
    }
  }

H
Haojun Liao 已提交
2661 2662
  // 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.
2663
  if (pQuery->numOfFilterCols > 0 || pQuery->groupbyColumn || pQuery->sw.gap > 0 ||
H
Haojun Liao 已提交
2664 2665 2666
      (QUERY_IS_INTERVAL_QUERY(pQuery) && overlapWithTimeWindow(pQuery, &pBlock->info))) {
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2667

H
Haojun Liao 已提交
2668 2669 2670 2671 2672 2673
  // 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 已提交
2674

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

H
Haojun Liao 已提交
2678 2679 2680 2681 2682
      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 已提交
2683
      }
H
Haojun Liao 已提交
2684
    } else if (pQuery->stableQuery && (!isTsCompQuery(pQuery))) { // stable aggregate, not interval aggregate or normal column aggregate
2685 2686 2687
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
                               pQuery->current->groupIndex);
H
Haojun Liao 已提交
2688
    }
H
Haojun Liao 已提交
2689 2690

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

H
Haojun Liao 已提交
2693
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2694 2695
  *status = updateBlockLoadStatus(pRuntimeEnv->pQuery, *status);

2696
  if ((*status) == BLK_DATA_NO_NEEDED || (*status) == BLK_DATA_DISCARD) {
H
Haojun Liao 已提交
2697
    qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2698
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2699 2700 2701 2702
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2703
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2704

H
Haojun Liao 已提交
2705
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2706
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2707
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2708 2709 2710 2711 2712 2713
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2716
    if (pQuery->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
      { // 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 已提交
2732 2733
      bool load = false;
      for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
H
Haojun Liao 已提交
2734
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2735
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2736 2737
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2738
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2739
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2740
            qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2741
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2742 2743 2744 2745 2746 2747 2748 2749
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2750
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2751
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2752
      qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2753
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2754
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2755
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2756 2757 2758 2759
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2760
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2761
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2762 2763
      return terrno;
    }
H
Haojun Liao 已提交
2764

H
Haojun Liao 已提交
2765
    doSetFilterColumnInfo(pQuery, pBlock);
H
Haojun Liao 已提交
2766
    if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2767
      filterRowsInDataBlock(pRuntimeEnv, pQuery->pFilterInfo, pQuery->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2768
    }
H
Haojun Liao 已提交
2769 2770 2771 2772 2773
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2774
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2775
  int32_t midPos = -1;
H
Haojun Liao 已提交
2776
  int32_t numOfRows;
2777

2778 2779 2780
  if (num <= 0) {
    return -1;
  }
2781

2782
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2783 2784

  TSKEY * keyList = (TSKEY *)pValue;
2785
  int32_t firstPos = 0;
2786
  int32_t lastPos = num - 1;
2787

2788
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2789 2790 2791 2792 2793
    // 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;
2794

H
Haojun Liao 已提交
2795 2796
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2797

H
hjxilinx 已提交
2798 2799 2800 2801 2802 2803 2804 2805
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2806

H
hjxilinx 已提交
2807 2808 2809 2810 2811
  } 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;
2812

H
hjxilinx 已提交
2813 2814 2815 2816 2817 2818 2819
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2820

H
Haojun Liao 已提交
2821
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2822
      midPos = (numOfRows >> 1u) + firstPos;
2823

H
hjxilinx 已提交
2824 2825 2826 2827 2828 2829 2830 2831 2832
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2833

H
hjxilinx 已提交
2834 2835 2836
  return midPos;
}

H
Haojun Liao 已提交
2837 2838 2839 2840 2841 2842
/*
 * 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);
2843

H
Haojun Liao 已提交
2844
  char* val = NULL;
H
Haojun Liao 已提交
2845
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2846
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2847 2848
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2849 2850
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2851

H
Haojun Liao 已提交
2852 2853 2854 2855
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2856

H
Haojun Liao 已提交
2857
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2858 2859 2860 2861
    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 已提交
2862 2863
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2864
  }
2865 2866
}

2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878
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 已提交
2879
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2880
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2881

H
Haojun Liao 已提交
2882 2883 2884 2885
  SExprInfo *pExpr  = pOperatorInfo->pExpr;
  SQuery    *pQuery = pRuntimeEnv->pQuery;

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

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

2892
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2893
    return;
H
Haojun Liao 已提交
2894 2895 2896 2897
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQuery->tagLen);
H
Haojun Liao 已提交
2898

H
Haojun Liao 已提交
2899 2900 2901 2902 2903 2904 2905 2906 2907
    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 已提交
2908 2909
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->type,
                           pLocalExprInfo->bytes);
H
Haojun Liao 已提交
2910 2911 2912 2913

      if (IS_NUMERIC_TYPE(pLocalExprInfo->type) || pLocalExprInfo->type == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->bytes);
      } else {
2914
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2915 2916 2917 2918 2919
      }

      offset += pLocalExprInfo->bytes;
    }

H
Haojun Liao 已提交
2920
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2921
    if (pQuery->stableQuery && pQuery->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2922
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2923
    }
H
Haojun Liao 已提交
2924
  }
H
Haojun Liao 已提交
2925

H
Haojun Liao 已提交
2926 2927 2928
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2929 2930
  }
}
2931

2932
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000
  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);
  }
}

3001
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
3002
  SQuery* pQuery = pRuntimeEnv->pQuery;
3003
  int32_t numOfCols = pQuery->numOfOutput;
3004
  printf("super table query intermediate result, total:%d\n", numOfRows);
3005

3006 3007
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
3008

H
Haojun Liao 已提交
3009
      switch (pQuery->pExpr1[i].type) {
3010
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
3011 3012
          int32_t type = pQuery->pExpr1[i].type;
          printBinaryData(pQuery->pExpr1[i].base.functionId, pdata[i]->data + pQuery->pExpr1[i].bytes * j,
3013 3014 3015 3016 3017
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
3018
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3019 3020
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
3021
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3022 3023
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
3024
          printf("%f\t", *(float *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3025 3026
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
3027
          printf("%lf\t", *(double *)(pdata[i]->data + pQuery->pExpr1[i].bytes * j));
3028 3029 3030 3031 3032 3033 3034
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
3035
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
3036
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
3037
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3038 3039

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3040
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
3041 3042 3043
    // 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 已提交
3044
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3045 3046 3047 3048
        return;
      }
    }

H
Haojun Liao 已提交
3049
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
3050 3051

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
3052
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3053 3054
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3055
        break;
H
Haojun Liao 已提交
3056 3057 3058
      }
    }

H
Haojun Liao 已提交
3059 3060 3061 3062
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
3063
    }
H
Haojun Liao 已提交
3064

H
Haojun Liao 已提交
3065 3066
}

3067 3068 3069 3070
static void updateTableQueryInfoForReverseScan(SQuery *pQuery, STableQueryInfo *pTableQueryInfo) {
  if (pTableQueryInfo == NULL) {
    return;
  }
3071

3072 3073
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3074

3075 3076
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
3077

H
Haojun Liao 已提交
3078
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
3079
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
3080 3081
}

H
Haojun Liao 已提交
3082 3083
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3084

H
Haojun Liao 已提交
3085
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
3086 3087 3088
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
    SArray *tableKeyGroup = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
3089

H
Haojun Liao 已提交
3090 3091 3092 3093
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
      updateTableQueryInfoForReverseScan(pQuery, pCheckInfo);
H
Haojun Liao 已提交
3094

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

H
Haojun Liao 已提交
3100
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
3101
    }
H
Haojun Liao 已提交
3102 3103
  }
}
H
Haojun Liao 已提交
3104

H
Haojun Liao 已提交
3105 3106 3107
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3108 3109 3110
  }
}

H
Haojun Liao 已提交
3111 3112 3113 3114 3115 3116
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3117

H
Haojun Liao 已提交
3118 3119 3120 3121 3122 3123 3124 3125
/*
 * 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 已提交
3126 3127 3128 3129 3130 3131
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 已提交
3132 3133
  int32_t tid = 0;
  SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&tid, sizeof(tid), true, uid);
3134

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

H
Haojun Liao 已提交
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147
    /*
     * 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);
3148

H
Haojun Liao 已提交
3149 3150 3151 3152 3153
    // 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;
    }
3154
  }
3155

H
Haojun Liao 已提交
3156
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3157
}
3158

H
Haojun Liao 已提交
3159 3160 3161
void updateOutputBuf(SArithOperatorInfo* pInfo, int32_t numOfInputRows) {
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
  SSDataBlock* pDataBlock = pBInfo->pRes;
3162

H
Haojun Liao 已提交
3163 3164 3165 3166 3167 3168 3169
  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;
3170

H
Haojun Liao 已提交
3171 3172 3173 3174 3175
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        pInfo->bufCapacity = newSize;
      } else {
        // longjmp
3176 3177
      }
    }
H
Haojun Liao 已提交
3178
  }
3179

H
Haojun Liao 已提交
3180 3181 3182
  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;
3183

H
Haojun Liao 已提交
3184 3185 3186 3187
    // 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 已提交
3188
    }
H
Haojun Liao 已提交
3189 3190
  }
}
3191

H
Haojun Liao 已提交
3192
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3193 3194 3195 3196
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3197 3198
    }

H
Haojun Liao 已提交
3199
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3200
  }
H
Haojun Liao 已提交
3201
}
3202

H
Haojun Liao 已提交
3203
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3204
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3205
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3206 3207
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3208 3209
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3210 3211
  }
}
3212

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

H
Haojun Liao 已提交
3216 3217 3218 3219
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3220
  }
3221

H
Haojun Liao 已提交
3222 3223 3224 3225
  // reverse order time range
  SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY);

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3226
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3227

H
Haojun Liao 已提交
3228
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3229
  SWITCH_ORDER(pQuery->order.order);
H
Haojun Liao 已提交
3230 3231

  setupQueryRangeForReverseScan(pRuntimeEnv);
3232 3233
}

H
Haojun Liao 已提交
3234
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3235
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3236
  SQuery *pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
3237 3238

  int32_t numOfOutput = pOperator->numOfOutput;
3239
  if (pQuery->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQuery) || pQuery->sw.gap > 0) {
H
Haojun Liao 已提交
3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250
    // 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 已提交
3251
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3252 3253 3254 3255 3256 3257 3258 3259 3260

      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 已提交
3261
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3262 3263 3264 3265 3266 3267 3268 3269 3270
    }

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

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

3275 3276 3277 3278
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3279

3280 3281 3282
  return false;
}

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

H
hjxilinx 已提交
3286 3287
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3288

3289
  pTableQueryInfo->pTable = pTable;
3290
  pTableQueryInfo->cur.vgroupIndex = -1;
3291

H
Haojun Liao 已提交
3292
  // set more initial size of interval/groupby query
3293
  if (QUERY_IS_INTERVAL_QUERY(pQuery) || groupbyColumn) {
H
Haojun Liao 已提交
3294
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3295
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3296 3297 3298
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3299
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3300 3301
  }

3302 3303 3304
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3305
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3306 3307 3308
  if (pTableQueryInfo == NULL) {
    return;
  }
3309

H
Haojun Liao 已提交
3310
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3311
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3312 3313
}

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

H
Haojun Liao 已提交
3319
  int16_t offset = 0;
3320
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3321
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3322 3323 3324

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3325
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3326 3327
      continue;
    }
3328

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

3332
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3333
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3334
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3335
    }
3336

3337
    if (!pResInfo->initialized) {
3338
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3339 3340 3341 3342
    }
  }
}

3343 3344
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3345
  int64_t uid = 0;
H
Haojun Liao 已提交
3346
  SResultRow* pResultRow =
3347
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3348
  assert (pResultRow != NULL);
3349

3350 3351 3352 3353 3354
  /*
   * 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) {
3355 3356
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQuery->resultRowSize);
    if (ret != TSDB_CODE_SUCCESS) {
3357
      return;
3358 3359 3360
    }
  }

3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375
  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);

3376 3377
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3378 3379
}

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

H
Haojun Liao 已提交
3385
  int16_t offset = 0;
3386
  for (int32_t i = 0; i < numOfCols; ++i) {
3387
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv, page, pResult->offset, offset, pCtx[i].outputBytes);
H
Haojun Liao 已提交
3388
    offset += pCtx[i].outputBytes;
3389

3390 3391 3392
    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;
3393 3394
    }

3395 3396 3397 3398
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3399
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3400 3401 3402
  }
}

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

H
Haojun Liao 已提交
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418
  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 已提交
3419
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%s", GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3420 3421
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.pz);
    } else {
H
Haojun Liao 已提交
3422
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3423 3424 3425 3426 3427 3428
             pExprInfo->base.arg->argValue.i64, pCtx[0].tag.i64);
    }
  }
}

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

H
Haojun Liao 已提交
3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441
  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 已提交
3442
        qError("QInfo:0x%"PRIx64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3443
      } else {
H
Haojun Liao 已提交
3444
        qError("QInfo:0x%"PRIx64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3445 3446 3447 3448 3449 3450 3451 3452
      }

      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 已提交
3453
      qDebug("QInfo:0x%"PRIx64" 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 已提交
3454
    } else {
H
Haojun Liao 已提交
3455
      qDebug("QInfo:0x%"PRIx64" 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 已提交
3456 3457 3458 3459 3460
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3461
      qDebug("QInfo:0x%"PRIx64" 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 已提交
3462
    } else {
H
Haojun Liao 已提交
3463
      qDebug("QInfo:0x%"PRIx64" 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 已提交
3464
    }
H
Haojun Liao 已提交
3465 3466
  }

H
Haojun Liao 已提交
3467 3468 3469 3470 3471 3472
  return 0;
}

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

H
Haojun Liao 已提交
3473 3474 3475
  int32_t numOfExprs = pQuery->numOfOutput;
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SExprInfo* pExprInfo = &(pExpr[i]);
H
Haojun Liao 已提交
3476
    if (pExprInfo->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3477 3478 3479 3480 3481 3482
      continue;
    }

    SSqlFuncMsg* pFuncMsg = &pExprInfo->base;

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3486 3487 3488
    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 已提交
3489
      if (pQuery->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQuery->tagLen) == 0) {
H
Haojun Liao 已提交
3490 3491
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
          if (pres->colId == pFuncMsg->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3503

D
fix bug  
dapan1121 已提交
3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539
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;
          }
        }
      }
    }
  }

}



3540 3541 3542 3543 3544 3545 3546 3547 3548
/*
 * 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 已提交
3549
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3550 3551 3552
  SQuery           *pQuery = pRuntimeEnv->pQuery;
  STableQueryInfo  *pTableQueryInfo = pQuery->current;
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3553

H
Haojun Liao 已提交
3554 3555 3556
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3557

H
Haojun Liao 已提交
3558 3559
  pTableQueryInfo->win.skey = key;
  STimeWindow win = {.skey = key, .ekey = pQuery->window.ekey};
3560

H
Haojun Liao 已提交
3561 3562 3563 3564 3565 3566
  /**
   * 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 已提交
3567
  STimeWindow w = TSWINDOW_INITIALIZER;
3568

H
Haojun Liao 已提交
3569 3570 3571
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
  getAlignQueryTimeWindow(pQuery, win.skey, sk, ek, &w);
3572

H
Haojun Liao 已提交
3573 3574 3575
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
    if (!QUERY_IS_ASC_QUERY(pQuery)) {
      assert(win.ekey == pQuery->window.ekey);
3576
    }
H
Haojun Liao 已提交
3577

H
Haojun Liao 已提交
3578
    pWindowResInfo->prevSKey = w.skey;
3579
  }
H
Haojun Liao 已提交
3580 3581

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3582 3583 3584
}

/**
H
Haojun Liao 已提交
3585
 * copyToOutputBuf support copy data in ascending/descending order
3586 3587 3588 3589 3590 3591 3592
 * 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 已提交
3593

H
Haojun Liao 已提交
3594
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3595
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3596
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3597 3598 3599 3600

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3601
  qDebug("QInfo:0x%"PRIx64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621
  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 已提交
3622 3623

    int16_t offset = 0;
H
Haojun Liao 已提交
3624 3625 3626 3627 3628
    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;
3629
      char *in  = getPosInResultPage(pRuntimeEnv, page, pRow->offset, offset, bytes);
H
Haojun Liao 已提交
3630
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3631 3632

      offset += bytes;
H
Haojun Liao 已提交
3633 3634 3635
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3636
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3637 3638 3639 3640
      break;
    }
  }

H
Haojun Liao 已提交
3641
  qDebug("QInfo:0x%"PRIx64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3642 3643 3644 3645 3646 3647
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3649
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3650
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3651 3652 3653 3654 3655
    return;
  }

  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3656
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3657 3658 3659

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

H
Haojun Liao 已提交
3660 3661 3662
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3663
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3664
  }
3665 3666
}

H
Haojun Liao 已提交
3667
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv *pRuntimeEnv,
H
Haojun Liao 已提交
3668
    SQLFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
3669
  SQuery *pQuery = pRuntimeEnv->pQuery;
3670

3671
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3672 3673 3674
  if (QUERY_IS_INTERVAL_QUERY(pQuery)) {
    return;
  }
3675

3676 3677
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3678

3679 3680
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3681 3682
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3683
      }
H
Haojun Liao 已提交
3684

H
Haojun Liao 已提交
3685
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3686
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3687 3688 3689 3690 3691
    }
  }
}

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

H
Haojun Liao 已提交
3695
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3696

H
Haojun Liao 已提交
3697
  if (pQuery->pExpr2 == NULL) {
H
Haojun Liao 已提交
3698 3699 3700 3701
    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 已提交
3702 3703 3704
    }
  } else {
    for (int32_t col = 0; col < pQuery->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3705 3706 3707
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3708
    }
3709
  }
3710

H
Haojun Liao 已提交
3711
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3712 3713
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3714

3715
  int32_t total = 0;
H
Haojun Liao 已提交
3716
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3717

3718
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3719
    STableIdInfo* pDst = (STableIdInfo*)data;
3720 3721 3722 3723
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3724
    data += sizeof(STableIdInfo);
3725 3726
    total++;

H
Haojun Liao 已提交
3727
    qDebug("QInfo:0x%"PRIx64" set subscribe info, tid:%d, uid:%"PRIu64", skey:%"PRId64, pQInfo->qId, item->tid, item->uid, item->key);
H
Haojun Liao 已提交
3728
    item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, item);
weixin_48148422's avatar
weixin_48148422 已提交
3729 3730
  }

H
Haojun Liao 已提交
3731
  qDebug("QInfo:0x%"PRIx64" set %d subscribe info", pQInfo->qId, total);
H
Haojun Liao 已提交
3732
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3733 3734
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3735
  }
3736 3737
}

H
Haojun Liao 已提交
3738
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3739 3740 3741 3742 3743 3744
  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 已提交
3745
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3746
  tfree(p);
H
Haojun Liao 已提交
3747 3748
  return pOutput->info.rows;
}
3749

H
Haojun Liao 已提交
3750
void queryCostStatis(SQInfo *pQInfo) {
3751
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3752
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3753

H
Haojun Liao 已提交
3754
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3755
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3756 3757
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3758 3759 3760
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3761
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3762 3763 3764 3765 3766 3767 3768
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3769

H
Haojun Liao 已提交
3770
  qDebug("QInfo:0x%"PRIx64" :cost summary: elapsed time:%"PRId64" us, first merge:%"PRId64" us, total blocks:%d, "
H
Haojun Liao 已提交
3771
         "load block statis:%d, load data block:%d, total rows:%"PRId64 ", check rows:%"PRId64,
H
Haojun Liao 已提交
3772
         pQInfo->qId, pSummary->elapsedTime, pSummary->firstStageMergeTime, pSummary->totalBlocks, pSummary->loadBlockStatis,
H
Haojun Liao 已提交
3773
         pSummary->loadBlocks, pSummary->totalRows, pSummary->totalCheckedRows);
3774

H
Haojun Liao 已提交
3775
  qDebug("QInfo:0x%"PRIx64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb, hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0,
H
Haojun Liao 已提交
3776
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3777 3778
}

3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
//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 已提交
3811
//  qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
3812 3813
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3814

3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829
//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 已提交
3830
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3831 3832 3833 3834 3835 3836 3837 3838 3839 3840
//      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 已提交
3841
//      qDebug("QInfo:0x%"PRIx64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852
//             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 已提交
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
//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 已提交
3889
//    qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
H
Haojun Liao 已提交
3890
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013
//           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;
//}
4014

H
Haojun Liao 已提交
4015 4016
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

B
Bomin Zhang 已提交
4017
static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) {
B
Bomin Zhang 已提交
4018
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
4019 4020
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;

H
Haojun Liao 已提交
4021
  // TODO set the tags scan handle
B
Bomin Zhang 已提交
4022
  if (onlyQueryTags(pQuery)) {
B
Bomin Zhang 已提交
4023
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
4024 4025
  }

H
Haojun Liao 已提交
4026
  STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4027 4028 4029
  if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
4030

B
Bomin Zhang 已提交
4031
  if (!isSTableQuery
H
Haojun Liao 已提交
4032
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
4033
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
4034
    && (!QUERY_IS_INTERVAL_QUERY(pQuery))
4035
    && (!isGroupbyColumn(pQuery->pGroupbyExpr))
H
Haojun Liao 已提交
4036
    && (!isFixedOutputQuery(pQuery))
B
Bomin Zhang 已提交
4037
  ) {
H
Haojun Liao 已提交
4038
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
4039 4040
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
4041
  }
B
Bomin Zhang 已提交
4042

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

H
Haojun Liao 已提交
4047 4048
    // update the query time window
    pQuery->window = cond.twindow;
H
Haojun Liao 已提交
4049
    if (pQuery->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
4050
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
4051
    } else {
H
Haojun Liao 已提交
4052
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
4053
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
4054
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
4055

H
Haojun Liao 已提交
4056 4057 4058
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
4059

H
Haojun Liao 已提交
4060 4061 4062
          pCheckInfo->win = pQuery->window;
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
4063 4064
      }
    }
4065
  } else if (isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4066
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
4067
  } else {
H
Haojun Liao 已提交
4068
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQuery->tableGroupInfo, pQInfo->qId, &pQuery->memRef);
H
Haojun Liao 已提交
4069
  }
4070

B
Bomin Zhang 已提交
4071
  return terrno;
B
Bomin Zhang 已提交
4072 4073
}

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

H
Haojun Liao 已提交
4077
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
4078 4079 4080 4081
  if (pFillCol == NULL) {
    return NULL;
  }

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

4085
    pFillCol[i].col.bytes  = pExprInfo->bytes;
S
TD-1057  
Shengliang Guan 已提交
4086
    pFillCol[i].col.type   = (int8_t)pExprInfo->type;
4087
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
4088
    pFillCol[i].tagIndex   = -2;
4089 4090
    pFillCol[i].flag       = TSDB_COL_NORMAL;    // always be ta normal column for table query
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
4091
    pFillCol[i].fillVal.i  = fillVal[i];
4092

4093 4094
    offset += pExprInfo->bytes;
  }
4095

4096 4097 4098
  return pFillCol;
}

D
dapan1121 已提交
4099
int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bool isSTableQuery) {
4100 4101 4102
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

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

H
Haojun Liao 已提交
4105 4106
  pQuery->topBotQuery = isTopBottomQuery(pQuery);
  pQuery->hasTagResults = hasTagValOutput(pQuery);
H
Haojun Liao 已提交
4107
  pQuery->timeWindowInterpo = timeWindowInterpoRequired(pQuery);
H
Haojun Liao 已提交
4108
  pQuery->stabledev = isStabledev(pQuery);
H
Haojun Liao 已提交
4109

4110
  setScanLimitationByResultBuffer(pQuery);
H
Haojun Liao 已提交
4111

H
Haojun Liao 已提交
4112
  int32_t code = setupQueryHandle(tsdb, pQInfo, isSTableQuery);
B
Bomin Zhang 已提交
4113 4114 4115
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
4116

H
Haojun Liao 已提交
4117
  pQuery->tsdb = tsdb;
H
Haojun Liao 已提交
4118
  pQuery->vgId = vgId;
H
Haojun Liao 已提交
4119 4120
  pQuery->stableQuery = isSTableQuery;
  pQuery->groupbyColumn = isGroupbyColumn(pQuery->pGroupbyExpr);
H
Haojun Liao 已提交
4121
  pQuery->interBufSize = getOutputInterResultBufSize(pQuery);
H
Haojun Liao 已提交
4122

sangshuduo's avatar
sangshuduo 已提交
4123
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (isSTableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
4124 4125

  pRuntimeEnv->pQuery = pQuery;
H
Haojun Liao 已提交
4126
  pRuntimeEnv->pTsBuf = pTsBuf;
4127
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4128
  setResultBufSize(pQuery, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4129

4130
  if (onlyQueryTags(pQuery)) {
H
Haojun Liao 已提交
4131
    pRuntimeEnv->resultInfo.capacity = 4096;
H
Haojun Liao 已提交
4132
    pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQuery->pExpr1, pQuery->numOfOutput);
H
Haojun Liao 已提交
4133 4134
  } else if (pQuery->queryBlockDist) {
    pRuntimeEnv->pTableScanner = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4135
  } else if (isTsCompQuery(pQuery) || isPointInterpoQuery(pQuery)) {
H
Haojun Liao 已提交
4136
    pRuntimeEnv->pTableScanner = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
4137
  } else if (needReverseScan(pQuery)) {
H
Haojun Liao 已提交
4138
    pRuntimeEnv->pTableScanner = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery), 1);
H
Haojun Liao 已提交
4139
  } else {
H
Haojun Liao 已提交
4140
    pRuntimeEnv->pTableScanner = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQuery));
H
Haojun Liao 已提交
4141 4142
  }

H
Haojun Liao 已提交
4143
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4144 4145
    int16_t order = (pQuery->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4146 4147
  }

4148
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
4149
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQuery->intermediateResultRowSize);
4150

H
Haojun Liao 已提交
4151
  int32_t TENMB = 1024*1024*10;
H
Haojun Liao 已提交
4152
  code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo->qId);
H
Haojun Liao 已提交
4153 4154
  if (code != TSDB_CODE_SUCCESS) {
    return code;
4155 4156
  }

H
Haojun Liao 已提交
4157
  // create runtime environment
sangshuduo's avatar
sangshuduo 已提交
4158
  int32_t numOfTables = (int32_t)pQuery->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4159
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4160
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQuery->tableGroupInfo.numOfTables);
H
Haojun Liao 已提交
4161 4162 4163 4164
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4165
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4166
  return TSDB_CODE_SUCCESS;
4167 4168
}

H
Haojun Liao 已提交
4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182
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 已提交
4183
STsdbQueryCond createTsdbQueryCond(SQuery* pQuery, STimeWindow* win) {
4184 4185 4186 4187
  STsdbQueryCond cond = {
      .colList   = pQuery->colList,
      .order     = pQuery->order.order,
      .numOfCols = pQuery->numOfCols,
H
Haojun Liao 已提交
4188
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4189
      .loadExternalRows = false,
4190 4191
  };

H
Haojun Liao 已提交
4192
  TIME_WINDOW_COPY(cond.twindow, *win);
4193 4194 4195
  return cond;
}

H
Haojun Liao 已提交
4196
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
4197
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
4198
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
4199 4200 4201

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
4202
  tidInfo.key = pTableQueryInfo->lastKey;
4203 4204 4205 4206

  return tidInfo;
}

H
Haojun Liao 已提交
4207 4208 4209 4210
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 已提交
4211 4212
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4213 4214 4215 4216 4217 4218 4219 4220
  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 已提交
4221 4222 4223 4224
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);
4225

H
Haojun Liao 已提交
4226 4227 4228 4229
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4230 4231
    }
  }
4232 4233
}

H
Haojun Liao 已提交
4234 4235 4236 4237
static SSDataBlock* doTableScanImpl(void* param) {
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4238
  SSDataBlock*     pBlock = &pTableScanInfo->block;
H
Haojun Liao 已提交
4239 4240
  SQuery*          pQuery = pOperator->pRuntimeEnv->pQuery;
  STableGroupInfo* pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4241

H
Haojun Liao 已提交
4242
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4243 4244 4245
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4246

4247
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4248
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4249

4250
    // todo opt
H
Haojun Liao 已提交
4251
    if (pTableGroupInfo->numOfTables > 1 || (pQuery->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4252 4253
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4254 4255 4256 4257 4258 4259 4260 4261
      if (pTableQueryInfo == NULL) {
        break;
      }

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

H
Haojun Liao 已提交
4262
    // this function never returns error?
H
Haojun Liao 已提交
4263
    uint32_t status;
H
Haojun Liao 已提交
4264
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4265
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4266
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4267
    }
H
Haojun Liao 已提交
4268

H
Haojun Liao 已提交
4269
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4270
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4271
      continue;
H
Haojun Liao 已提交
4272 4273 4274 4275
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4276 4277

  return NULL;
H
Haojun Liao 已提交
4278 4279 4280
}

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

H
Haojun Liao 已提交
4283
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4284
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4285
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4286

H
Haojun Liao 已提交
4287 4288
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;

H
Haojun Liao 已提交
4289
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4290
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4291 4292
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4293 4294
    }

H
Haojun Liao 已提交
4295
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4296 4297 4298 4299 4300
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4301
    }
H
Haojun Liao 已提交
4302

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

H
Haojun Liao 已提交
4307
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4308
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4309

H
Haojun Liao 已提交
4310 4311 4312 4313 4314
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4315 4316 4317 4318
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4319

H
Haojun Liao 已提交
4320
    qDebug("QInfo:0x%"PRIx64" start to repeat scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
4321
           GET_QID(pRuntimeEnv), cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4322 4323
  }

H
Haojun Liao 已提交
4324
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4325
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4326

H
Haojun Liao 已提交
4327
    STsdbQueryCond cond = createTsdbQueryCond(pQuery, &pQuery->window);
H
Haojun Liao 已提交
4328
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4329

H
Haojun Liao 已提交
4330
    qDebug("QInfo:0x%"PRIx64" start to reverse scan data blocks due to query func required, qrange:%" PRId64 "-%" PRId64,
H
Haojun Liao 已提交
4331
           GET_QID(pRuntimeEnv), cond.twindow.skey, cond.twindow.ekey);
H
Haojun Liao 已提交
4332

H
Haojun Liao 已提交
4333 4334
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4335 4336
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4337 4338
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4339

H
Haojun Liao 已提交
4340 4341 4342 4343
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4344

H
Haojun Liao 已提交
4345
    SSDataBlock* p = doTableScanImpl(pOperator);
H
Haojun Liao 已提交
4346 4347
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4348 4349
    }
  }
H
Haojun Liao 已提交
4350

H
Haojun Liao 已提交
4351 4352 4353
  return NULL;
}

H
Haojun Liao 已提交
4354 4355
static SSDataBlock* doBlockInfoScan(void* param) {
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4356 4357 4358
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4359 4360 4361 4362

  STableScanInfo *pTableScanInfo = pOperator->info;

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

H
Haojun Liao 已提交
4366
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4367
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4368 4369 4370 4371 4372

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

H
Haojun Liao 已提交
4373 4374 4375 4376 4377 4378
  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 已提交
4379

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

H
Haojun Liao 已提交
4383
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4384

H
Haojun Liao 已提交
4385 4386 4387 4388 4389
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
  pOperator->pRuntimeEnv->pQuery->current = taosArrayGetP(g, 0);

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

H
Haojun Liao 已提交
4392
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4393 4394
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4395 4396
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4397
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4398
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4399 4400
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
  pInfo->current      = 0;
H
Haojun Liao 已提交
4401

H
Haojun Liao 已提交
4402
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4403
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4404
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4405 4406
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4407
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4408
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4409
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4410 4411 4412 4413

  return pOperator;
}

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

H
Haojun Liao 已提交
4417 4418 4419 4420 4421
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
  pInfo->order            = pRuntimeEnv->pQuery->order.order;
  pInfo->current          = 0;
H
Haojun Liao 已提交
4422 4423

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4424 4425
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4426 4427 4428 4429
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->numOfOutput  = pRuntimeEnv->pQuery->numOfCols;
H
Haojun Liao 已提交
4430 4431
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4432

H
Haojun Liao 已提交
4433 4434 4435
  return pOperator;
}

H
Haojun Liao 已提交
4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460
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 已提交
4461 4462 4463
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4464 4465 4466
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4467
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4468
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4469

H
Haojun Liao 已提交
4470 4471 4472
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
4473
  } else if (pDownstream->operatorType == OP_TimeWindow) {
H
Haojun Liao 已提交
4474
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4475 4476 4477

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

H
Haojun Liao 已提交
4480
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4481
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4482

H
Haojun Liao 已提交
4483 4484 4485
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4486

H
Haojun Liao 已提交
4487
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4488
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4489

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

H
Haojun Liao 已提交
4494
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4495
    SArithOperatorInfo *pInfo = pDownstream->info;
4496

4497 4498 4499 4500 4501 4502
    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 已提交
4503 4504 4505
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4506 4507 4508
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4509 4510
}

H
Haojun Liao 已提交
4511
static SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4512 4513 4514 4515
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4516
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4517
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4518 4519
  pInfo->current      = 0;
  pInfo->order        = pRuntimeEnv->pQuery->order.order;
H
Haojun Liao 已提交
4520 4521

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4522 4523
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4524
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4525 4526 4527
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4528 4529

  return pOptr;
H
Haojun Liao 已提交
4530 4531
}

H
Haojun Liao 已提交
4532
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4533 4534 4535
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4536
// this is a blocking operator
H
Haojun Liao 已提交
4537
static SSDataBlock* doAggregate(void* param) {
H
Haojun Liao 已提交
4538
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4539
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4540 4541
    return NULL;
  }
H
Haojun Liao 已提交
4542

H
Haojun Liao 已提交
4543
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4544 4545
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4546
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4547

H
Haojun Liao 已提交
4548
  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4549
  int32_t order = pQuery->order.order;
H
Haojun Liao 已提交
4550

H
Haojun Liao 已提交
4551
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4552

H
Haojun Liao 已提交
4553
  while(1) {
H
Haojun Liao 已提交
4554
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4555 4556 4557 4558
    if (pBlock == NULL) {
      break;
    }

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

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

H
Haojun Liao 已提交
4566
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4567 4568
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4569 4570
  }

H
Haojun Liao 已提交
4571
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4572
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4573

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

H
Haojun Liao 已提交
4577
  return pInfo->pRes;
H
Haojun Liao 已提交
4578 4579
}

H
Haojun Liao 已提交
4580
static SSDataBlock* doSTableAggregate(void* param) {
H
Haojun Liao 已提交
4581
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4582
  if (pOperator->status == OP_EXEC_DONE) {
4583 4584
    return NULL;
  }
H
Haojun Liao 已提交
4585

H
Haojun Liao 已提交
4586
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4587 4588
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4589
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4590

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

H
Haojun Liao 已提交
4594 4595
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4596 4597
    }

H
Haojun Liao 已提交
4598
    return pInfo->pRes;
4599
  }
H
Haojun Liao 已提交
4600

H
Haojun Liao 已提交
4601
  SQuery* pQuery = pRuntimeEnv->pQuery;
4602 4603 4604 4605 4606 4607 4608 4609 4610 4611
  int32_t order = pQuery->order.order;

  SOperatorInfo* upstream = pOperator->upstream;

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

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

H
Haojun Liao 已提交
4614
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4615
      STableScanInfo* pScanInfo = upstream->info;
4616 4617 4618 4619
      order = getTableScanOrder(pScanInfo);
    }

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

4622 4623
    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 已提交
4624
    doAggregateImpl(pOperator, pQuery->window.skey, pInfo->pCtx, pBlock);
4625
  }
H
Haojun Liao 已提交
4626

H
Haojun Liao 已提交
4627 4628
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4629

H
Haojun Liao 已提交
4630
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4631
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4632

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

H
Haojun Liao 已提交
4635 4636 4637
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4638 4639
  }

H
Haojun Liao 已提交
4640
  return pInfo->pRes;
4641 4642 4643 4644 4645
}

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

H
Haojun Liao 已提交
4646 4647
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4648
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4649

H
Haojun Liao 已提交
4650 4651 4652 4653
  SSDataBlock* pRes = pInfo->pRes;
  int32_t order = pRuntimeEnv->pQuery->order.order;

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

H
Haojun Liao 已提交
4655
  while(1) {
H
Haojun Liao 已提交
4656
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream);
H
Haojun Liao 已提交
4657
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4658
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4659
      break;
H
Haojun Liao 已提交
4660 4661
    }

H
Haojun Liao 已提交
4662 4663 4664 4665
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->pQuery->current;

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

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

H
Haojun Liao 已提交
4671 4672
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
H
Haojun Liao 已提交
4673

H
Haojun Liao 已提交
4674 4675
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4676 4677 4678 4679
      break;
    }
  }

H
Haojun Liao 已提交
4680
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4681
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4682 4683 4684 4685
}

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

H
Haojun Liao 已提交
4690
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4691

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

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

H
Haojun Liao 已提交
4702 4703
    pInfo->total = pInfo->limit;

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

  return pBlock;
}

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

H
Haojun Liao 已提交
4720
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4721 4722

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

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

H
Haojun Liao 已提交
4745
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4746 4747 4748 4749 4750
      return pBlock;
    }
  }
}

D
dapan1121 已提交
4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801

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

  return false;
}


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

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

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

D
dapan1121 已提交
4802
        SColumnFilterElem filterElem = {.filterInfo = pExprInfo->pFilter[m]};
D
dapan1121 已提交
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 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855
        
        if (doFilterData(p, r, &filterElem, fp)) {
          exprQualified = 1;
          break;
        }
      }

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

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

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

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

  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

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

    return pBlock;
  }
}


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

H
Haojun Liao 已提交
4862
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4863

H
Haojun Liao 已提交
4864
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4865
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4866 4867
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4868
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4869
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4870 4871 4872 4873
    }

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

  SQuery* pQuery = pRuntimeEnv->pQuery;
H
Haojun Liao 已提交
4876
  int32_t order = pQuery->order.order;
4877
  STimeWindow win = pQuery->window;
H
Haojun Liao 已提交
4878

H
Haojun Liao 已提交
4879
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4880 4881 4882 4883 4884 4885 4886 4887

  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 已提交
4888
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
H
Haojun Liao 已提交
4889
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
4890 4891
  }

4892 4893 4894 4895
  // restore the value
  pQuery->order.order = order;
  pQuery->window = win;

H
Haojun Liao 已提交
4896
  pOperator->status = OP_RES_TO_RETURN;
4897
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4898
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4899
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4900

H
Haojun Liao 已提交
4901
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4902
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4903

H
Haojun Liao 已提交
4904
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4905
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4906 4907
  }

H
Haojun Liao 已提交
4908
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4909 4910
}

H
Haojun Liao 已提交
4911
static SSDataBlock* doSTableIntervalAgg(void* param) {
H
Haojun Liao 已提交
4912
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4913
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4914 4915 4916
    return NULL;
  }

H
Haojun Liao 已提交
4917
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4918
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4919

H
Haojun Liao 已提交
4920
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4921
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4922
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4923
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4924 4925 4926 4927 4928
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
4929 4930 4931
  SQuery* pQuery = pRuntimeEnv->pQuery;
  int32_t order = pQuery->order.order;

H
Haojun Liao 已提交
4932
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4933 4934

  while(1) {
H
Haojun Liao 已提交
4935
    SSDataBlock* pBlock = upstream->exec(upstream);
H
Haojun Liao 已提交
4936
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4937
      break;
H
Haojun Liao 已提交
4938 4939
    }

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

H
Haojun Liao 已提交
4943
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4944
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQuery->order.order);
4945
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
4946

H
Haojun Liao 已提交
4947
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
4948
  }
H
Haojun Liao 已提交
4949

H
Haojun Liao 已提交
4950
  pOperator->status = OP_RES_TO_RETURN;
4951 4952
  pQuery->order.order = order;   // TODO : restore the order
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
4953
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4954

H
Haojun Liao 已提交
4955
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4956
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4957
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4958 4959 4960 4961
  }

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

4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018
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 已提交
5019
static SSDataBlock* hashGroupbyAggregate(void* param) {
H
Haojun Liao 已提交
5020
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5021
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5022 5023 5024
    return NULL;
  }

H
Haojun Liao 已提交
5025
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5026

H
Haojun Liao 已提交
5027
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5028
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5029
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5030 5031

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

H
Haojun Liao 已提交
5035
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046
  }

  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 已提交
5047
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQuery->order.order);
H
Haojun Liao 已提交
5048
    setTagValue(pOperator, pRuntimeEnv->pQuery->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5049
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
5050
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQuery->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
5051 5052
    }

H
Haojun Liao 已提交
5053
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5054 5055
  }

H
Haojun Liao 已提交
5056
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5057
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5058
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5059

H
Haojun Liao 已提交
5060
  if (!pRuntimeEnv->pQuery->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5061 5062 5063
    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);
5064 5065
  }

H
Haojun Liao 已提交
5066
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5067
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5068

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

H
Haojun Liao 已提交
5073
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5074 5075
}

H
Haojun Liao 已提交
5076 5077
static SSDataBlock* doFill(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5078
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5079 5080 5081
    return NULL;
  }

H
Haojun Liao 已提交
5082 5083
  SFillOperatorInfo *pInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5084

H
Haojun Liao 已提交
5085
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
sangshuduo's avatar
sangshuduo 已提交
5086
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5087 5088 5089 5090 5091 5092
    return pInfo->pRes;
  }

  while(1) {
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream);
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5093
      if (pInfo->totalInputRows == 0) {
H
Haojun Liao 已提交
5094
        pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5095 5096 5097
        return NULL;
      }

H
Haojun Liao 已提交
5098
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQuery->window.ekey);
H
Haojun Liao 已提交
5099
    } else {
H
Haojun Liao 已提交
5100 5101
      pInfo->totalInputRows += pBlock->info.rows;

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

H
Haojun Liao 已提交
5104 5105
      taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
H
Haojun Liao 已提交
5106 5107
    }

H
Haojun Liao 已提交
5108
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5109
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
5110 5111
  }
}
H
Haojun Liao 已提交
5112

H
Haojun Liao 已提交
5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124
// 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 已提交
5125 5126 5127 5128 5129
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5130
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5131
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5132 5133
  }

H
Haojun Liao 已提交
5134
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5135
  tfree(pOperator->info);
H
Haojun Liao 已提交
5136 5137 5138
  tfree(pOperator);
}

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

H
Haojun Liao 已提交
5142 5143 5144 5145
  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 已提交
5146
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5147

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

H
Haojun Liao 已提交
5150
  pInfo->seed = rand();
H
Haojun Liao 已提交
5151
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed);
H
Haojun Liao 已提交
5152

H
Haojun Liao 已提交
5153
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5154
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5155
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5156
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5157
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5158
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5159
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5160 5161 5162
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5163

H
Haojun Liao 已提交
5164 5165
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5166 5167 5168
  return pOperator;
}

H
Haojun Liao 已提交
5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185
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 已提交
5186
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5187 5188 5189 5190
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5191
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5192
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5193
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5194 5195 5196 5197 5198 5199 5200
}

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

H
Haojun Liao 已提交
5201 5202 5203 5204 5205
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

D
dapan1121 已提交
5206 5207 5208 5209 5210 5211 5212
static void destroyHavingOperatorInfo(void* param, int32_t numOfOutput) {
  SHavingOperatorInfo* pInfo = (SHavingOperatorInfo*) param;
  if (pInfo->fp) {
    taosArrayDestroy(pInfo->fp);
  }
}

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

H
Haojun Liao 已提交
5216
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5217

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

5222
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5223 5224
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5225
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5226
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5227
  pOperator->info         = pInfo;
5228
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5229 5230 5231
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5232

H
Haojun Liao 已提交
5233 5234 5235
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5236
  return pOperator;
H
Haojun Liao 已提交
5237 5238
}

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

H
Haojun Liao 已提交
5242
  pInfo->seed = rand();
H
Haojun Liao 已提交
5243
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5244

H
Haojun Liao 已提交
5245
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5246
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5247 5248 5249
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5250
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed);
H
Haojun Liao 已提交
5251 5252

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5253 5254
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5255
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5256
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5257
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5258
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5259 5260 5261
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5262

H
Haojun Liao 已提交
5263 5264 5265
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5266 5267 5268
  return pOperator;
}

D
dapan1121 已提交
5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297

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

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

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

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

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

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

    for (int32_t j = 0; j < filterNum; ++j) {      
      int32_t lower = filterInfo->lowerRelOptr;
      int32_t upper = filterInfo->upperRelOptr;
      if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
        qError("invalid rel optr");
D
dapan1121 已提交
5298
        taosArrayDestroy(es);
D
dapan1121 已提交
5299 5300 5301 5302 5303 5304
        return TSDB_CODE_QRY_APP_ERROR;
      }

      __filter_func_t ffp = getFilterOperator(lower, upper);
      if (ffp == NULL) {
        qError("invalid filter info");
D
dapan1121 已提交
5305
        taosArrayDestroy(es);
D
dapan1121 已提交
5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345
        return TSDB_CODE_QRY_APP_ERROR;
      }
      
      taosArrayPush(es, &ffp);
      
      filterInfo += 1;
    }

    taosArrayPush(*fps, &es);
  }

  return TSDB_CODE_SUCCESS;
}

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

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

  assert(pInfo->fp);
  
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));

  pOperator->name         = "HavingOperator";
  pOperator->operatorType = OP_Having;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
  pOperator->exec         = doHaving;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->cleanup      = destroyHavingOperatorInfo;

  return pOperator;
}



H
Haojun Liao 已提交
5346
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5347 5348 5349 5350 5351
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
  pInfo->limit = pRuntimeEnv->pQuery->limit.limit;

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

H
Haojun Liao 已提交
5352 5353
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5354
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5355
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5356
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5357
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5358 5359
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5360 5361 5362 5363

  return pOperator;
}

H
Haojun Liao 已提交
5364
SOperatorInfo* createOffsetOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5365 5366 5367 5368 5369
  SOffsetOperatorInfo* pInfo = calloc(1, sizeof(SOffsetOperatorInfo));

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

H
Haojun Liao 已提交
5370 5371
  pOperator->name         = "OffsetOperator";
  pOperator->operatorType = OP_Offset;
H
Haojun Liao 已提交
5372
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5373
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5374
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5375
  pOperator->exec         = doOffset;
H
Haojun Liao 已提交
5376 5377
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5378 5379 5380 5381

  return pOperator;
}

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

H
Haojun Liao 已提交
5385
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5386
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5387
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5388 5389 5390

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

H
Haojun Liao 已提交
5391
  pOperator->name         = "TimeIntervalAggOperator";
5392
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5393
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5394
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5395
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5396 5397 5398 5399
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5400
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5401 5402
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5403 5404 5405
  return pOperator;
}

5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430
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 已提交
5431
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5432
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5433

H
Haojun Liao 已提交
5434
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5435
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5436
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5437 5438

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5439 5440
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5441
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5442
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5443
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5444 5445
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5446 5447
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5448

H
Haojun Liao 已提交
5449 5450 5451
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5452 5453 5454
  return pOperator;
}

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

H
Haojun Liao 已提交
5459
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5460
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5461
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5462 5463

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5464
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5465
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5466 5467
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5468
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5469 5470 5471 5472
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5473
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5474 5475
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5476 5477
  return pOperator;
}
H
Haojun Liao 已提交
5478

H
Haojun Liao 已提交
5479
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5480
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5481
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496
  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 已提交
5497 5498 5499

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

H
Haojun Liao 已提交
5500
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5501
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5502 5503 5504
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5505
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5506 5507 5508 5509
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5510

H
Haojun Liao 已提交
5511 5512 5513
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5514 5515 5516
  return pOperator;
}

5517 5518
static SSDataBlock* doTagScan(void* param) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5519
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5520 5521
    return NULL;
  }
5522

H
Haojun Liao 已提交
5523
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5524

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

H
Haojun Liao 已提交
5527 5528
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
5529 5530

  int32_t count = 0;
H
Haojun Liao 已提交
5531 5532 5533 5534 5535
  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;
5536 5537 5538 5539
    assert(pQuery->numOfOutput == 1);

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

5541 5542 5543
    count = 0;

    int16_t bytes = pExprInfo->bytes;
H
Haojun Liao 已提交
5544
    int16_t type  = pExprInfo->type;
5545 5546 5547 5548 5549 5550 5551 5552 5553

    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 已提交
5554 5555 5556 5557
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5560
      char *output = pColInfo->pData + count * rsize;
5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577
      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 已提交
5578
      char* data = NULL;
5579
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5580
        data = tsdbGetTableName(item->pTable);
5581
      } else {
H
Haojun Liao 已提交
5582
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5583 5584
      }

H
Haojun Liao 已提交
5585
      doSetTagValueToResultBuf(output, data, type, bytes);
5586 5587 5588
      count += 1;
    }

H
Haojun Liao 已提交
5589
    qDebug("QInfo:0x%"PRIx64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5590 5591 5592
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5593
    count = 1;
H
Haojun Liao 已提交
5594 5595

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

H
Haojun Liao 已提交
5600 5601 5602
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613

      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 已提交
5614
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5615 5616
        type  = pExprInfo[j].type;
        bytes = pExprInfo[j].bytes;
5617 5618 5619 5620 5621 5622 5623

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

5628 5629 5630
      count += 1;
    }

H
Haojun Liao 已提交
5631 5632 5633 5634
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

H
Haojun Liao 已提交
5635
    qDebug("QInfo:0x%"PRIx64" create tag values results completed, rows:%d", GET_QID(pRuntimeEnv), count);
5636 5637
  }

H
Haojun Liao 已提交
5638
  pRes->info.rows = count;
H
Haojun Liao 已提交
5639
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5640 5641
}

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

H
Haojun Liao 已提交
5646 5647 5648 5649 5650 5651
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5652
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5653
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5654
  pOperator->operatorType = OP_TagScan;
5655
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5656
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5657 5658
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5659 5660
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5661
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5662
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5663

5664 5665
  return pOperator;
}
H
Haojun Liao 已提交
5666

5667
static int32_t getColumnIndexInSource(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
5668
  int32_t j = 0;
5669

5670
  if (TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {
H
Haojun Liao 已提交
5671
    if (pExprMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5672
      return TSDB_TBNAME_COLUMN_INDEX;
Y
yihaoDeng 已提交
5673 5674
    } else if (pExprMsg->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5675
    }
Y
yihaoDeng 已提交
5676
    
H
Haojun Liao 已提交
5677

5678 5679 5680 5681
    while(j < pQueryMsg->numOfTags) {
      if (pExprMsg->colInfo.colId == pTagCols[j].colId) {
        return j;
      }
5682

5683 5684
      j += 1;
    }
5685

Y
TD-1230  
yihaoDeng 已提交
5686
  } else if (TSDB_COL_IS_UD_COL(pExprMsg->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5687
    return TSDB_UD_COLUMN_INDEX;
5688 5689 5690 5691 5692
  } else {
    while (j < pQueryMsg->numOfCols) {
      if (pExprMsg->colInfo.colId == pQueryMsg->colList[j].colId) {
        return j;
      }
5693

5694
      j += 1;
5695 5696
    }
  }
5697 5698

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5699 5700
}

5701 5702
bool validateExprColumnInfo(SQueryTableMsg *pQueryMsg, SSqlFuncMsg *pExprMsg, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pQueryMsg, pExprMsg, pTagCols);
5703
  return j != INT32_MIN;
5704 5705
}

5706
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5707 5708
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5709
    return false;
5710 5711
  }

5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722
  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 已提交
5723
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5724
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5725
    return false;
5726 5727
  }

H
hjxilinx 已提交
5728
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5729
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5730
    return false;
5731 5732
  }

5733 5734
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5735
    return false;
5736 5737
  }

5738 5739 5740
  return true;
}

5741
static bool validateQuerySourceCols(SQueryTableMsg *pQueryMsg, SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
5742 5743 5744 5745
  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;
5746 5747 5748
  }

  if (numOfTotal == 0) {
5749
    for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
5750 5751 5752 5753
      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 已提交
5754 5755
          (pFuncMsg->functionId == TSDB_FUNC_COUNT && pFuncMsg->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (pFuncMsg->functionId == TSDB_FUNC_BLKINFO)) {
5756
        continue;
5757
      }
5758

5759
      return false;
5760 5761
    }
  }
5762

5763 5764 5765 5766 5767 5768
  for(int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
    if (!validateExprColumnInfo(pQueryMsg, pExprMsg[i], pTagCols)) {
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5769
  return true;
5770 5771
}

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

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

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

5780
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
5781 5782
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
5783

H
hjxilinx 已提交
5784 5785 5786
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
5787

H
hjxilinx 已提交
5788 5789
  return pMsg;
}
5790

5791
/**
H
hjxilinx 已提交
5792
 * pQueryMsg->head has been converted before this function is called.
5793
 *
H
hjxilinx 已提交
5794
 * @param pQueryMsg
5795 5796 5797 5798
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
5799
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
5800 5801
  int32_t code = TSDB_CODE_SUCCESS;

5802 5803 5804 5805
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

5806 5807 5808 5809
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);

  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
5810 5811 5812
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
5813 5814
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
5815
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
5816

5817 5818
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
5819
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
5820
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
5821 5822

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
5823
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
5824
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
5825 5826 5827
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
  pQueryMsg->tsOffset = htonl(pQueryMsg->tsOffset);
  pQueryMsg->tsLen = htonl(pQueryMsg->tsLen);
H
hjxilinx 已提交
5828
  pQueryMsg->tsNumOfBlocks = htonl(pQueryMsg->tsNumOfBlocks);
5829
  pQueryMsg->tsOrder = htonl(pQueryMsg->tsOrder);
5830
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
5831
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
5832
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
5833
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
5834
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
5835 5836
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
5837

5838
  // query msg safety check
5839
  if (!validateQueryMsg(pQueryMsg)) {
5840 5841
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
5842 5843
  }

H
hjxilinx 已提交
5844 5845
  char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
5846 5847
    SColumnInfo *pColInfo = &pQueryMsg->colList[col];

H
hjxilinx 已提交
5848
    pColInfo->colId = htons(pColInfo->colId);
5849
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
5850 5851
    pColInfo->bytes = htons(pColInfo->bytes);
    pColInfo->numOfFilters = htons(pColInfo->numOfFilters);
5852

5853 5854 5855 5856 5857
    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;
    }
5858

H
hjxilinx 已提交
5859
    int32_t numOfFilters = pColInfo->numOfFilters;
5860
    if (numOfFilters > 0) {
H
hjxilinx 已提交
5861
      pColInfo->filters = calloc(numOfFilters, sizeof(SColumnFilterInfo));
H
Haojun Liao 已提交
5862 5863 5864 5865
      if (pColInfo->filters == NULL) {
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
5866 5867 5868
    }

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

5871 5872
      SColumnFilterInfo *pColFilter = &pColInfo->filters[f];
      pColFilter->filterstr = htons(pFilterMsg->filterstr);
5873 5874 5875

      pMsg += sizeof(SColumnFilterInfo);

5876 5877
      if (pColFilter->filterstr) {
        pColFilter->len = htobe64(pFilterMsg->len);
5878

5879
        pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
H
Haojun Liao 已提交
5880 5881 5882 5883 5884
        if (pColFilter->pz == 0) {
          code = TSDB_CODE_QRY_OUT_OF_MEMORY;
          goto _cleanup;
        }

5885
        memcpy((void *)pColFilter->pz, pMsg, (size_t)pColFilter->len);
5886
        pMsg += (pColFilter->len + 1);
5887
      } else {
5888 5889
        pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
5890 5891
      }

5892 5893
      pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
5894 5895 5896
    }
  }

5897 5898
  param->pExprMsg = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExprMsg == NULL) {
H
Haojun Liao 已提交
5899 5900 5901 5902
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

5903
  SSqlFuncMsg *pExprMsg = (SSqlFuncMsg *)pMsg;
5904

5905
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
5906
    param->pExprMsg[i] = pExprMsg;
5907

5908
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
5909
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5910
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5911 5912 5913
    pExprMsg->colType       = htons(pExprMsg->colType);
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5914 5915 5916
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
D
dapan1121 已提交
5917
    pExprMsg->filterNum     = htonl(pExprMsg->filterNum);
5918

5919
    pMsg += sizeof(SSqlFuncMsg);
5920

D
dapan1121 已提交
5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945
    SColumnFilterInfo* pExprFilterInfo = pExprMsg->filterInfo;

    pMsg += sizeof(SColumnFilterInfo) * pExprMsg->filterNum;

    for (int32_t f = 0; f < pExprMsg->filterNum; ++f) {
      SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)pExprFilterInfo;

      pFilterMsg->filterstr = htons(pFilterMsg->filterstr);

      if (pFilterMsg->filterstr) {
        pFilterMsg->len = htobe64(pFilterMsg->len);

        pFilterMsg->pz = (int64_t)pMsg;
        pMsg += (pFilterMsg->len + 1);
      } else {
        pFilterMsg->lowerBndi = htobe64(pFilterMsg->lowerBndi);
        pFilterMsg->upperBndi = htobe64(pFilterMsg->upperBndi);
      }

      pFilterMsg->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
      pFilterMsg->upperRelOptr = htons(pFilterMsg->upperRelOptr);

      pExprFilterInfo++;
    }

5946
    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
5947
      pExprMsg->arg[j].argType = htons(pExprMsg->arg[j].argType);
5948 5949 5950 5951
      pExprMsg->arg[j].argBytes = htons(pExprMsg->arg[j].argBytes);

      if (pExprMsg->arg[j].argType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->arg[j].argValue.pz = pMsg;
5952
        pMsg += pExprMsg->arg[j].argBytes;  // one more for the string terminated char.
5953 5954 5955 5956 5957
      } else {
        pExprMsg->arg[j].argValue.i64 = htobe64(pExprMsg->arg[j].argValue.i64);
      }
    }

H
Haojun Liao 已提交
5958 5959
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
5960
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
5961 5962
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
5963 5964 5965
      }
    }

5966
    pExprMsg = (SSqlFuncMsg *)pMsg;
5967
  }
5968

H
Haojun Liao 已提交
5969 5970
  if (pQueryMsg->secondStageOutput) {
    pExprMsg = (SSqlFuncMsg *)pMsg;
5971
    param->pSecExprMsg = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
5972

H
Haojun Liao 已提交
5973
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
5974
      param->pSecExprMsg[i] = pExprMsg;
H
Haojun Liao 已提交
5975 5976 5977

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
5978
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
5979 5980 5981
      pExprMsg->colType       = htons(pExprMsg->colType);
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);

H
Haojun Liao 已提交
5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010
      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;
    }
  }

6011
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
6012

H
hjxilinx 已提交
6013
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
6014 6015
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
6016 6017 6018
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6019 6020

    for (int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
6021 6022
      param->pGroupColIndex[i].colId = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colId);
6023

6024 6025
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
6026

6027 6028
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
6029

6030 6031
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
6032
    }
6033

H
hjxilinx 已提交
6034 6035
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
6036 6037
  }

6038 6039
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
6040
    pQueryMsg->fillVal = (uint64_t)(pMsg);
6041 6042

    int64_t *v = (int64_t *)pMsg;
6043
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
6044 6045
      v[i] = htobe64(v[i]);
    }
6046

6047
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
6048
  }
6049

6050
  if (pQueryMsg->numOfTags > 0) {
6051 6052
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
6053 6054 6055 6056
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6057 6058
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6059

6060 6061 6062 6063
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
      pTagCol->numOfFilters = 0;
6064

6065
      param->pTagColumnInfo[i] = *pTagCol;
6066
      pMsg += sizeof(SColumnInfo);
6067
    }
H
hjxilinx 已提交
6068
  }
6069

6070 6071
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6072 6073
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6074 6075 6076
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6077 6078

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6079 6080
    pMsg += pQueryMsg->tagCondLen;
  }
6081

6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092
  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 已提交
6093
  if (pQueryMsg->tbnameCondLen > 0) {
6094 6095
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6096 6097 6098 6099
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6100
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6101
    pMsg += pQueryMsg->tbnameCondLen;
6102 6103
  }

D
dapan1121 已提交
6104 6105 6106 6107 6108
  //skip ts buf
  if ((pQueryMsg->tsOffset + pQueryMsg->tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsOffset + pQueryMsg->tsLen;
  }

6109
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6110

6111
  if (!validateQuerySourceCols(pQueryMsg, param->pExprMsg, param->pTagColumnInfo)) {
6112 6113
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6114
  }
6115

6116
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6117 6118
         "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,
6119
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6120
         pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6121

6122
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6123
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6124 6125

_cleanup:
6126
  freeParam(param);
6127
  return code;
6128 6129
}

D
dapan1121 已提交
6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142
int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
  if (filterNum <= 0) {
    return TSDB_CODE_SUCCESS;
  }

  *dst = calloc(filterNum, sizeof(*src));
  if (*dst == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  memcpy(*dst, src, sizeof(*src) * filterNum);
  
  for (int32_t i = 0; i < filterNum; i++) {
D
dapan1121 已提交
6143
    if ((*dst)[i].filterstr && dst[i]->len > 0) {
D
dapan1121 已提交
6144
      void *pz = calloc(1, (size_t)(*dst)[i].len + 1); 
D
dapan1121 已提交
6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155
    
      if (pz == NULL) {
        if (i == 0) {
          free(*dst);
        } else {
          freeColumnFilterInfo(*dst, i);
        }

        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }

D
dapan1121 已提交
6156
      memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6157

D
dapan1121 已提交
6158
      (*dst)[i].pz = (int64_t)pz;
D
dapan1121 已提交
6159 6160 6161 6162 6163 6164 6165
    }
  }

  return TSDB_CODE_SUCCESS;
}


H
Haojun Liao 已提交
6166 6167
static int32_t buildArithmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTableMsg *pQueryMsg) {
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6168 6169

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6170
  TRY(TSDB_MAX_TAG_CONDITIONS) {
weixin_48148422's avatar
weixin_48148422 已提交
6171 6172 6173
    pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
  } CATCH( code ) {
    CLEANUP_EXECUTE();
dengyihao's avatar
TD-816  
dengyihao 已提交
6174
    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 已提交
6175 6176 6177
    return code;
  } END_TRY

H
hjxilinx 已提交
6178
  if (pExprNode == NULL) {
6179
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
6180
    return TSDB_CODE_QRY_APP_ERROR;
6181
  }
6182

6183
  pArithExprInfo->pExpr = pExprNode;
6184 6185 6186
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6187
static int32_t updateOutputBufForTopBotQuery(SQueryTableMsg* pQueryMsg, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206
  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 已提交
6207
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6208 6209
int32_t createQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                   SSqlFuncMsg** pExprMsg, SColumnInfo* pTagCols) {
6210
  *pExprInfo = NULL;
H
hjxilinx 已提交
6211
  int32_t code = TSDB_CODE_SUCCESS;
6212

H
Haojun Liao 已提交
6213
  SExprInfo *pExprs = (SExprInfo *)calloc(pQueryMsg->numOfOutput, sizeof(SExprInfo));
6214
  if (pExprs == NULL) {
6215
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6216 6217 6218 6219 6220
  }

  bool    isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6221
  for (int32_t i = 0; i < numOfOutput; ++i) {
6222
    pExprs[i].base = *pExprMsg[i];
6223
    pExprs[i].bytes = 0;
6224 6225 6226 6227

    int16_t type = 0;
    int16_t bytes = 0;

6228
    // parse the arithmetic expression
6229
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6230
      code = buildArithmeticExprFromMsg(&pExprs[i], pQueryMsg);
6231

6232
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6233
        tfree(pExprs);
6234
        return code;
6235 6236
      }

6237
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6238
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6239
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6240 6241 6242
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6243 6244 6245 6246
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
6247 6248
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX) {
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6249 6250
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

6251 6252
      type = pExprs[i].base.arg[1].argType;
      bytes = pExprs[i].base.arg[1].argBytes;
H
Haojun Liao 已提交
6253 6254 6255 6256 6257

      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
6258
      int32_t j = getColumnIndexInSource(pQueryMsg, &pExprs[i].base, pTagCols);
6259
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
Y
yihaoDeng 已提交
6260
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pQueryMsg->numOfTags) {
6261 6262 6263 6264 6265 6266 6267
          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 已提交
6268

dengyihao's avatar
dengyihao 已提交
6269
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6270 6271 6272 6273
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pQueryMsg->colList[j];
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6274
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6275

6276 6277
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6278
      }
D
dapan1121 已提交
6279 6280 6281 6282 6283 6284 6285

      if (pExprs[i].base.filterNum > 0) {
        int32_t ret = cloneExprFilterInfo(&pExprs[i].pFilter, pExprMsg[i]->filterInfo, pExprMsg[i]->filterNum);
        if (ret) {
          return ret;
        }
      }
6286 6287
    }

S
TD-1057  
Shengliang Guan 已提交
6288
    int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64;
H
Haojun Liao 已提交
6289 6290
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6291 6292 6293 6294
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

6295
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes,
6296
                          &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6297
      tfree(pExprs);
6298
      return TSDB_CODE_QRY_INVALID_MSG;
6299 6300
    }

6301
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
6302
      tagLen += pExprs[i].bytes;
6303
    }
6304

6305
    assert(isValidDataType(pExprs[i].type));
6306 6307
  }

H
Haojun Liao 已提交
6308 6309
  // the tag length is affected by other tag columns, so this should be update.
  updateOutputBufForTopBotQuery(pQueryMsg, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6310

6311
  *pExprInfo = pExprs;
6312 6313 6314
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6315 6316 6317 6318 6319 6320 6321 6322 6323 6324
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 已提交
6325
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348

  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 已提交
6349 6350
      type  = prevExpr[index].type;
      bytes = prevExpr[index].bytes;
H
Haojun Liao 已提交
6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366
    }

    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 已提交
6367
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6368 6369 6370 6371 6372
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6373
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6374
  if (pGroupbyExpr == NULL) {
6375
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6376 6377 6378 6379 6380 6381 6382
    return NULL;
  }

  pGroupbyExpr->numOfGroupCols = pQueryMsg->numOfGroupCols;
  pGroupbyExpr->orderType = pQueryMsg->orderType;
  pGroupbyExpr->orderIndex = pQueryMsg->orderByIdx;

6383 6384 6385 6386
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6387

6388 6389 6390
  return pGroupbyExpr;
}

H
Haojun Liao 已提交
6391
static int32_t createFilterInfo(SQuery *pQuery, uint64_t qId) {
6392
  for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
6393
    if (pQuery->colList[i].numOfFilters > 0) {
6394 6395 6396 6397 6398 6399 6400 6401 6402
      pQuery->numOfFilterCols++;
    }
  }

  if (pQuery->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  pQuery->pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * pQuery->numOfFilterCols);
H
Haojun Liao 已提交
6403 6404 6405
  if (pQuery->pFilterInfo == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6406 6407

  for (int32_t i = 0, j = 0; i < pQuery->numOfCols; ++i) {
6408
    if (pQuery->colList[i].numOfFilters > 0) {
6409 6410
      SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[j];

B
Bomin Zhang 已提交
6411
      memcpy(&pFilterInfo->info, &pQuery->colList[i], sizeof(SColumnInfo));
6412
      pFilterInfo->info = pQuery->colList[i];
6413

6414
      pFilterInfo->numOfFilters = pQuery->colList[i].numOfFilters;
6415
      pFilterInfo->pFilters = calloc(pFilterInfo->numOfFilters, sizeof(SColumnFilterElem));
H
Haojun Liao 已提交
6416 6417 6418
      if (pFilterInfo->pFilters == NULL) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6419 6420 6421

      for (int32_t f = 0; f < pFilterInfo->numOfFilters; ++f) {
        SColumnFilterElem *pSingleColFilter = &pFilterInfo->pFilters[f];
6422
        pSingleColFilter->filterInfo = pQuery->colList[i].filters[f];
6423 6424 6425 6426

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
H
Haojun Liao 已提交
6427
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6428
          return TSDB_CODE_QRY_INVALID_MSG;
6429 6430
        }

6431 6432
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
H
Haojun Liao 已提交
6433
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6434
          return TSDB_CODE_QRY_INVALID_MSG;
6435 6436
        }

6437
        pSingleColFilter->bytes = pQuery->colList[i].bytes;
6438 6439 6440 6441 6442 6443 6444 6445 6446
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6447
static void doUpdateExprColumnIndex(SQuery *pQuery) {
H
Haojun Liao 已提交
6448
  assert(pQuery->pExpr1 != NULL && pQuery != NULL);
6449

6450
  for (int32_t k = 0; k < pQuery->numOfOutput; ++k) {
H
Haojun Liao 已提交
6451
    SSqlFuncMsg *pSqlExprMsg = &pQuery->pExpr1[k].base;
6452
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6453 6454
      continue;
    }
6455

6456
    // todo opt performance
H
Haojun Liao 已提交
6457
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6458
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6459 6460
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfCols; ++f) {
H
Haojun Liao 已提交
6461 6462
        if (pColIndex->colId == pQuery->colList[f].colId) {
          pColIndex->colIndex = f;
6463 6464 6465
          break;
        }
      }
H
Haojun Liao 已提交
6466 6467

      assert(f < pQuery->numOfCols);
6468 6469
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6470 6471 6472
    } 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);
6473
    } else {
6474 6475
      int32_t f = 0;
      for (f = 0; f < pQuery->numOfTags; ++f) {
H
Haojun Liao 已提交
6476 6477
        if (pColIndex->colId == pQuery->tagColList[f].colId) {
          pColIndex->colIndex = f;
6478 6479
          break;
        }
6480
      }
6481

Y
yihaoDeng 已提交
6482
      assert(f < pQuery->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6483 6484 6485 6486
    }
  }
}

H
Haojun Liao 已提交
6487 6488 6489 6490 6491 6492 6493 6494
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 已提交
6495

6496
  if (isProjQuery(pQuery)) {
H
Haojun Liao 已提交
6497 6498 6499
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQuery->resultRowSize;
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6500
    }
H
Haojun Liao 已提交
6501

H
Haojun Liao 已提交
6502
    pResultInfo->capacity  = numOfRes;
6503
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6504
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6505
  }
H
Haojun Liao 已提交
6506 6507 6508

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
  pResultInfo->total = 0;
H
Haojun Liao 已提交
6509 6510
}

D
fix bug  
dapan1121 已提交
6511 6512 6513 6514
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6515 6516
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, bool stableQuery,
D
dapan1121 已提交
6517
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6518 6519 6520
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6521 6522
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6523
    goto _cleanup_qinfo;
6524
  }
6525

D
dapan1121 已提交
6526 6527
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6528 6529
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6530
  SQuery* pQuery = &pQInfo->query;
6531 6532
  pQInfo->runtimeEnv.pQuery = pQuery;

H
Haojun Liao 已提交
6533
  pQuery->tableGroupInfo  = *pTableGroupInfo;
6534
  pQuery->numOfCols       = numOfCols;
H
hjxilinx 已提交
6535
  pQuery->numOfOutput     = numOfOutput;
6536 6537 6538
  pQuery->limit.limit     = pQueryMsg->limit;
  pQuery->limit.offset    = pQueryMsg->offset;
  pQuery->order.order     = pQueryMsg->order;
6539
  pQuery->order.orderColId = pQueryMsg->orderColId;
H
Haojun Liao 已提交
6540
  pQuery->pExpr1          = pExprs;
H
Haojun Liao 已提交
6541 6542
  pQuery->pExpr2          = pSecExprs;
  pQuery->numOfExpr2      = pQueryMsg->secondStageOutput;
6543
  pQuery->pGroupbyExpr    = pGroupbyExpr;
6544
  memcpy(&pQuery->interval, &pQueryMsg->interval, sizeof(pQuery->interval));
6545
  pQuery->fillType        = pQueryMsg->fillType;
6546
  pQuery->numOfTags       = pQueryMsg->numOfTags;
B
Bomin Zhang 已提交
6547
  pQuery->tagColList      = pTagCols;
H
Haojun Liao 已提交
6548 6549
  pQuery->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQuery->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
6550
  pQuery->sw              = pQueryMsg->sw;
6551
  pQuery->colList = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
6552
  if (pQuery->colList == NULL) {
6553
    goto _cleanup;
6554
  }
6555

6556 6557
  pQuery->srcRowSize = 0;
  pQuery->maxSrcColumnSize = 0;
H
hjxilinx 已提交
6558
  for (int16_t i = 0; i < numOfCols; ++i) {
6559
    pQuery->colList[i] = pQueryMsg->colList[i];
6560
    pQuery->colList[i].filters = tFilterInfoDup(pQueryMsg->colList[i].filters, pQuery->colList[i].numOfFilters);
6561 6562 6563 6564 6565

    pQuery->srcRowSize += pQuery->colList[i].bytes;
    if (pQuery->maxSrcColumnSize < pQuery->colList[i].bytes) {
      pQuery->maxSrcColumnSize = pQuery->colList[i].bytes;
    }
H
hjxilinx 已提交
6566
  }
6567

6568
  // calculate the result row size
6569 6570
  for (int16_t col = 0; col < numOfOutput; ++col) {
    assert(pExprs[col].bytes > 0);
6571 6572 6573 6574 6575 6576
    pQuery->resultRowSize += pExprs[col].bytes;

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
      pQuery->tagLen += pExprs[col].bytes;
    }
D
dapan1121 已提交
6577 6578 6579 6580

    if (pExprs[col].pFilter) {
      ++pQuery->havingNum;
    }
6581
  }
6582

6583
  doUpdateExprColumnIndex(pQuery);
H
Haojun Liao 已提交
6584
  int32_t ret = createFilterInfo(pQuery, pQInfo->qId);
6585
  if (ret != TSDB_CODE_SUCCESS) {
6586
    goto _cleanup;
6587 6588
  }

6589
  if (pQuery->fillType != TSDB_FILL_NONE) {
6590 6591
    pQuery->fillVal = malloc(sizeof(int64_t) * pQuery->numOfOutput);
    if (pQuery->fillVal == NULL) {
6592
      goto _cleanup;
6593 6594 6595
    }

    // the first column is the timestamp
6596
    memcpy(pQuery->fillVal, (char *)pQueryMsg->fillVal, pQuery->numOfOutput * sizeof(int64_t));
6597 6598
  }

dengyihao's avatar
dengyihao 已提交
6599 6600 6601
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6602
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6603

6604 6605 6606
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6607
  }
H
Haojun Liao 已提交
6608

H
Haojun Liao 已提交
6609
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6610 6611 6612 6613
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6614
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6615
  pQInfo->rspContext = NULL;
6616
  pQInfo->sql = sql;
6617
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6618
  tsem_init(&pQInfo->ready, 0, 0);
6619 6620 6621 6622

  pQuery->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, stableQuery);

H
Haojun Liao 已提交
6623
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6624 6625
  bool groupByCol = isGroupbyColumn(pQuery->pGroupbyExpr);

6626
  STimeWindow window = pQuery->window;
H
Haojun Liao 已提交
6627

H
Haojun Liao 已提交
6628
  int32_t index = 0;
H
hjxilinx 已提交
6629
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6630
    SArray* pa = taosArrayGetP(pQuery->tableGroupInfo.pGroupList, i);
6631

H
Haojun Liao 已提交
6632
    size_t s = taosArrayGetSize(pa);
6633
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6634 6635 6636
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6637

H
Haojun Liao 已提交
6638
    taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1);
6639

H
hjxilinx 已提交
6640
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6641
      STableKeyInfo* info = taosArrayGet(pa, j);
6642
      window.skey = info->lastKey;
6643 6644

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
6645
      STableQueryInfo* item = createTableQueryInfo(pQuery, info->pTable, groupByCol, window, buf);
B
Bomin Zhang 已提交
6646 6647 6648
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6649

6650
      item->groupIndex = i;
H
hjxilinx 已提交
6651
      taosArrayPush(p1, &item);
6652 6653

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6654
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6655
      index += 1;
H
hjxilinx 已提交
6656 6657
    }
  }
6658

H
Haojun Liao 已提交
6659
  colIdCheck(pQuery, pQInfo->qId);
6660

6661
  // todo refactor
H
Haojun Liao 已提交
6662
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
H
Haojun Liao 已提交
6663

H
Haojun Liao 已提交
6664
  qDebug("qmsg:%p QInfo:0x%" PRIx64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6665 6666
  return pQInfo;

B
Bomin Zhang 已提交
6667
_cleanup_qinfo:
H
Haojun Liao 已提交
6668
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6669

6670 6671 6672 6673
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6674

S
TD-1848  
Shengliang Guan 已提交
6675
  tfree(pTagCols);
B
Bomin Zhang 已提交
6676 6677 6678
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6679 6680
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6681
    }
D
dapan1121 已提交
6682 6683 6684 6685

    if (pExprInfo->pFilter) {
      freeColumnFilterInfo(pExprInfo->pFilter, pExprInfo->base.filterNum);
    }
B
Bomin Zhang 已提交
6686
  }
H
Haojun Liao 已提交
6687

S
TD-1848  
Shengliang Guan 已提交
6688
  tfree(pExprs);
B
Bomin Zhang 已提交
6689

6690
_cleanup:
dengyihao's avatar
dengyihao 已提交
6691
  freeQInfo(pQInfo);
6692 6693 6694
  return NULL;
}

H
Haojun Liao 已提交
6695
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6696 6697 6698 6699
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6700

H
hjxilinx 已提交
6701 6702 6703 6704
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6705
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6706 6707 6708
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6709
int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, SQueryParam* param, bool isSTable) {
H
hjxilinx 已提交
6710
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6711 6712

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6713 6714 6715
  pRuntimeEnv->qinfo = pQInfo;

  SQuery *pQuery = pRuntimeEnv->pQuery;
6716

6717
  STSBuf *pTsBuf = NULL;
6718
  if (pQueryMsg->tsLen > 0) { // open new file to save the result
H
Haojun Liao 已提交
6719
    char *tsBlock = (char *) pQueryMsg + pQueryMsg->tsOffset;
6720
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder, vgId);
6721

6722 6723
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
6724

dengyihao's avatar
dengyihao 已提交
6725
    UNUSED(ret);
H
hjxilinx 已提交
6726
  }
6727

6728 6729 6730
  SArray* prevResult = NULL;
  if (pQueryMsg->prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, pQueryMsg->prevResultLen);
D
dapan1121 已提交
6731 6732
    
    pRuntimeEnv->prevResult = prevResult;    
6733 6734
  }

Y
TD-1665  
yihaoDeng 已提交
6735
  pQuery->precision = tsdbGetCfg(tsdb)->precision;
6736

6737 6738
  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 已提交
6739
    qDebug("QInfo:0x%"PRIx64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQuery->window.skey,
6740
           pQuery->window.ekey, pQuery->order.order);
H
Haojun Liao 已提交
6741
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
6742
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
6743
    // todo free memory
6744 6745
    return TSDB_CODE_SUCCESS;
  }
6746

H
Haojun Liao 已提交
6747
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
6748
    qDebug("QInfo:0x%"PRIx64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
6749
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
6750 6751
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
6752 6753

  // filter the qualified
D
dapan1121 已提交
6754
  if ((code = doInitQInfo(pQInfo, pTsBuf, tsdb, vgId, isSTable)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
6755 6756
    goto _error;
  }
6757

H
hjxilinx 已提交
6758 6759 6760 6761
  return code;

_error:
  // table query ref will be decrease during error handling
6762
  freeQInfo(pQInfo);
H
hjxilinx 已提交
6763 6764 6765
  return code;
}

H
Haojun Liao 已提交
6766
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
6767
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
6768 6769
      return;
    }
H
Haojun Liao 已提交
6770

B
Bomin Zhang 已提交
6771
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
6772
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
6773 6774 6775
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
6776

B
Bomin Zhang 已提交
6777 6778 6779
    free(pFilter);
}

H
Haojun Liao 已提交
6780 6781
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
6782
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803
    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 已提交
6804 6805 6806 6807 6808 6809 6810 6811
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 已提交
6812
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
6813
    }
D
dapan1121 已提交
6814 6815 6816 6817

    if (pExprInfo[i].pFilter) {
      freeColumnFilterInfo(pExprInfo[i].pFilter, pExprInfo[i].base.filterNum);
    }
H
Haojun Liao 已提交
6818 6819 6820 6821 6822 6823
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
6824
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
6825 6826 6827
  if (!isValidQInfo(pQInfo)) {
    return;
  }
6828

H
Haojun Liao 已提交
6829
  qDebug("QInfo:0x%"PRIx64" start to free QInfo", pQInfo->qId);
6830

H
Haojun Liao 已提交
6831
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6832
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
6833 6834 6835

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);

6836
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
6837

H
Haojun Liao 已提交
6838 6839 6840
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
  if (pQuery != NULL) {
    if (pQuery->fillVal != NULL) {
S
TD-1848  
Shengliang Guan 已提交
6841
      tfree(pQuery->fillVal);
H
Haojun Liao 已提交
6842
    }
6843

H
Haojun Liao 已提交
6844 6845 6846
    for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) {
      SSingleColumnFilterInfo *pColFilter = &pQuery->pFilterInfo[i];
      if (pColFilter->numOfFilters > 0) {
S
TD-1848  
Shengliang Guan 已提交
6847
        tfree(pColFilter->pFilters);
H
hjxilinx 已提交
6848
      }
H
hjxilinx 已提交
6849
    }
6850

H
Haojun Liao 已提交
6851 6852
    pQuery->pExpr1 = destroyQueryFuncExpr(pQuery->pExpr1, pQuery->numOfOutput);
    pQuery->pExpr2 = destroyQueryFuncExpr(pQuery->pExpr2, pQuery->numOfExpr2);
6853

S
TD-1848  
Shengliang Guan 已提交
6854 6855
    tfree(pQuery->tagColList);
    tfree(pQuery->pFilterInfo);
H
Haojun Liao 已提交
6856 6857 6858 6859 6860 6861

    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 已提交
6862
      tfree(pQuery->colList);
H
Haojun Liao 已提交
6863 6864
    }

H
Haojun Liao 已提交
6865 6866 6867 6868
    if (pQuery->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQuery->pGroupbyExpr->columnInfo);
      tfree(pQuery->pGroupbyExpr);
    }
H
hjxilinx 已提交
6869
  }
6870

H
Haojun Liao 已提交
6871

S
TD-1848  
Shengliang Guan 已提交
6872
  tfree(pQInfo->pBuf);
6873 6874
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
6875
  tsdbDestroyTableGroup(&pQuery->tableGroupInfo);
6876

H
Haojun Liao 已提交
6877
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
6878
  pQInfo->signature = 0;
6879

H
Haojun Liao 已提交
6880
  qDebug("QInfo:0x%"PRIx64" QInfo is freed", pQInfo->qId);
6881

S
TD-1848  
Shengliang Guan 已提交
6882
  tfree(pQInfo);
H
hjxilinx 已提交
6883 6884
}

H
Haojun Liao 已提交
6885
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
6886
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
6887
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
hjxilinx 已提交
6888
  SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
6889

H
hjxilinx 已提交
6890
  // load data from file to msg buffer
H
Haojun Liao 已提交
6891
  if (isTsCompQuery(pQuery)) {
H
Haojun Liao 已提交
6892 6893
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
6894

H
hjxilinx 已提交
6895
    // make sure file exist
D
fix bug  
dapan1121 已提交
6896 6897
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
6898
      assert(s == pRuntimeEnv->outputBuf->info.rows);
6899

H
Haojun Liao 已提交
6900
      qDebug("QInfo:0x%"PRIx64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
6901 6902
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
6903
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
6904
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
6905 6906
          assert(0);
        }
H
Haojun Liao 已提交
6907
      } else {
6908
        UNUSED(s);
D
dapan1121 已提交
6909 6910 6911 6912
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
6913
      // dump error info
D
dapan1121 已提交
6914 6915 6916
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
6917
      }
H
Haojun Liao 已提交
6918

D
fix bug  
dapan1121 已提交
6919
      fclose(f);
D
dapan1121 已提交
6920
      *(FILE **)pColInfoData->pData = NULL;
H
hjxilinx 已提交
6921
    }
6922

H
hjxilinx 已提交
6923
    // all data returned, set query over
H
Haojun Liao 已提交
6924 6925
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
6926
    }
H
hjxilinx 已提交
6927
  } else {
H
Haojun Liao 已提交
6928
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
6929
  }
6930

H
Haojun Liao 已提交
6931
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
6932
  qDebug("QInfo:0x%"PRIx64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
6933
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
6934

H
Haojun Liao 已提交
6935
  if (pQuery->limit.limit > 0 && pQuery->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
6936
    qDebug("QInfo:0x%"PRIx64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQuery->limit.limit);
H
Haojun Liao 已提交
6937
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
6938
  }
6939

H
hjxilinx 已提交
6940
  return TSDB_CODE_SUCCESS;
6941 6942
}

H
Haojun Liao 已提交
6943
bool doBuildResCheck(SQInfo* pQInfo) {
6944 6945 6946 6947 6948
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
6949
  buildRes = needBuildResAfterQueryComplete(pQInfo);
6950

H
Haojun Liao 已提交
6951 6952
  // 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 已提交
6953
  assert(pQInfo->owner == taosGetSelfPthreadId());
6954
  pQInfo->owner = 0;
H
Haojun Liao 已提交
6955

H
Haojun Liao 已提交
6956
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
6957

6958
  // used in retrieve blocking model.
H
Haojun Liao 已提交
6959
  tsem_post(&pQInfo->ready);
6960 6961 6962
  return buildRes;
}

H
Haojun Liao 已提交
6963 6964 6965 6966
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
6967 6968
  }

6969 6970 6971
  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 已提交
6972
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
6973 6974 6975 6976 6977
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
6978
  } else {
H
Haojun Liao 已提交
6979
    memcpy(output, val, bytes);
6980 6981 6982
  }
}

H
Haojun Liao 已提交
6983
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
6984 6985 6986 6987
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
6988
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
6989 6990
}

H
Haojun Liao 已提交
6991
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
6992
  int64_t t = getQuerySupportBufSize(numOfTables);
6993
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
6994
    return TSDB_CODE_SUCCESS;
6995
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
6996 6997

    while(1) {
6998
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
6999 7000
      int64_t remain = s - t;
      if (remain >= 0) {
7001
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013
          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 已提交
7014
void releaseQueryBuf(size_t numOfTables) {
7015
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7016 7017 7018 7019 7020 7021
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
7022
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
7023
}