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

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

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

D
fix bug  
dapan1121 已提交
36 37
#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey))

38
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
39

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

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

47
enum {
48 49
  TS_JOIN_TS_EQUAL       = 0,
  TS_JOIN_TS_NOT_EQUALS  = 1,
50 51 52
  TS_JOIN_TAG_NOT_EQUALS = 2,
};

H
Haojun Liao 已提交
53 54 55 56 57
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP   = 2,
} SResultTsInterpType;

H
Haojun Liao 已提交
58
#if 0
H
Haojun Liao 已提交
59
static UNUSED_FUNC void *u_malloc (size_t __size) {
H
Haojun Liao 已提交
60
  uint32_t v = rand();
H
Haojun Liao 已提交
61 62

  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
63 64
    return NULL;
  } else {
H
Haojun Liao 已提交
65
    return malloc(__size);
H
Haojun Liao 已提交
66
  }
H
Haojun Liao 已提交
67 68
}

H
Haojun Liao 已提交
69 70
static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) {
  uint32_t v = rand();
H
Haojun Liao 已提交
71
  if (v % 1000 <= 0) {
H
Haojun Liao 已提交
72 73 74 75 76 77
    return NULL;
  } else {
    return calloc(num, __size);
  }
}

H
Haojun Liao 已提交
78 79 80 81 82 83 84 85 86
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 已提交
87
#define calloc  u_calloc
H
Haojun Liao 已提交
88
#define malloc  u_malloc
H
Haojun Liao 已提交
89
#define realloc u_realloc
H
Haojun Liao 已提交
90
#endif
H
Haojun Liao 已提交
91

92
#define CLEAR_QUERY_STATUS(q, st)   ((q)->status &= (~(st)))
H
Haojun Liao 已提交
93
#define GET_NUM_OF_TABLEGROUP(q)    taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
94
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)
H
Haojun Liao 已提交
95

D
fix bug  
dapan1121 已提交
96 97
uint64_t queryHandleId = 0;

H
Haojun Liao 已提交
98
int32_t getMaximumIdleDurationSec() {
99 100
  return tsShellActivityTimer * 2;
}
101

D
dapan1121 已提交
102 103 104
int64_t genQueryId(void) {
  int64_t uid = 0;
  int64_t did = tsDnodeId;
H
Haojun Liao 已提交
105

D
dapan1121 已提交
106
  uid = did << 54;
H
Haojun Liao 已提交
107

D
dapan1121 已提交
108 109 110
  int64_t pid = ((int64_t)taosGetPId()) & 0x3FF;

  uid |= pid << 44;
H
Haojun Liao 已提交
111

D
dapan1121 已提交
112 113 114
  int64_t ts = taosGetTimestampMs() & 0x1FFFFFFFF;

  uid |= ts << 11;
H
Haojun Liao 已提交
115

D
dapan1121 已提交
116 117 118 119
  int64_t sid = atomic_add_fetch_64(&queryHandleId, 1) & 0x7FF;

  uid |= sid;

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

D
dapan1121 已提交
122 123 124
  return uid;
}

H
Haojun Liao 已提交
125 126 127 128 129
static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
  int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
  if (pQueryAttr->interval.intervalUnit != 'n' && pQueryAttr->interval.intervalUnit != 'y') {
    tw->skey += pQueryAttr->interval.sliding * factor;
    tw->ekey = tw->skey + pQueryAttr->interval.interval - 1;
130 131 132
    return;
  }

H
Haojun Liao 已提交
133 134
  int64_t key = tw->skey / 1000, interval = pQueryAttr->interval.interval;
  if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
135 136
    key /= 1000;
  }
H
Haojun Liao 已提交
137
  if (pQueryAttr->interval.intervalUnit == 'y') {
138 139
    interval *= 12;
  }
140 141 142 143 144

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

S
Shengliang Guan 已提交
145
  int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
146 147 148 149
  tm.tm_year = mon / 12;
  tm.tm_mon = mon % 12;
  tw->skey = mktime(&tm) * 1000L;

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

H
Haojun Liao 已提交
155
  if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
156 157 158 159 160 161
    tw->skey *= 1000L;
    tw->ekey *= 1000L;
  }
  tw->ekey -= 1;
}

H
Haojun Liao 已提交
162
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
163 164
static void setResultOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRow* pResult, SQLFunctionCtx* pCtx,
                               int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
165

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

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

H
Haojun Liao 已提交
171
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
172
static bool hasMainOutput(SQueryAttr *pQueryAttr);
173

H
Haojun Liao 已提交
174
static int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
175
static void releaseQueryBuf(size_t numOfTables);
176
static int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order);
H
Haojun Liao 已提交
177
static STsdbQueryCond createTsdbQueryCond(SQueryAttr* pQueryAttr, STimeWindow* win);
H
Haojun Liao 已提交
178
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo);
179

H
Haojun Liao 已提交
180
static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream);
181 182 183
static int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols,
                                  SSingleColumnFilterInfo** pFilterInfo, uint64_t qId);
static void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols);
H
Haojun Liao 已提交
184

H
Haojun Liao 已提交
185
static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr);
H
Haojun Liao 已提交
186

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

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

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

H
Haojun Liao 已提交
199
static void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size);
H
Haojun Liao 已提交
200 201
static void getAlignQueryTimeWindow(SQueryAttr *pQueryAttr, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win);
static void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo);
H
Haojun Liao 已提交
202 203
static void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable);
static void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr);
H
Haojun Liao 已提交
204
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
205 206 207
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
208

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

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

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

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

  return res;
H
Haojun Liao 已提交
229 230
}

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

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

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

H
Haojun Liao 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
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);
}
299

H
Haojun Liao 已提交
300 301 302
static bool isProjQuery(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functId = pQueryAttr->pExpr1[i].base.functionId;
303 304 305 306 307 308 309 310
    if (functId != TSDB_FUNC_PRJ && functId != TSDB_FUNC_TAGPRJ) {
      return false;
    }
  }

  return true;
}

H
Haojun Liao 已提交
311 312 313 314 315 316 317 318 319 320 321 322
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;
}

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
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 已提交
349
static SResultRow *doPrepareResultRowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, char *pData,
H
Haojun Liao 已提交
350
                                             int16_t bytes, bool masterscan, uint64_t uid) {
351
  bool existed = false;
H
Haojun Liao 已提交
352
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);
353 354 355 356 357

  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.
H
Haojun Liao 已提交
358
  if (QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQueryAttr)) {
359 360 361 362 363 364 365 366 367 368 369 370 371
    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;
        }
      }
    }
372
  } else {
373 374
    if (p1 != NULL) {  // group by column query
      return *p1;
H
Haojun Liao 已提交
375
    }
376
  }
377

378
  if (!existed) {
379
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
380

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

395
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
396
    pResultRowInfo->curIndex = pResultRowInfo->size++;
397
  }
398

399
  // too many time window in query
H
Haojun Liao 已提交
400
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
401 402 403
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
404
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
405 406
}

H
Haojun Liao 已提交
407 408 409
static void getInitialStartTimeWindow(SQueryAttr* pQueryAttr, TSKEY ts, STimeWindow* w) {
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
    getAlignQueryTimeWindow(pQueryAttr, ts, ts, pQueryAttr->window.ekey, w);
410 411
  } else {
    // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
H
Haojun Liao 已提交
412
    getAlignQueryTimeWindow(pQueryAttr, ts, pQueryAttr->window.ekey, ts, w);
413 414 415

    int64_t key = w->skey;
    while(key < ts) { // moving towards end
H
Haojun Liao 已提交
416 417
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        key = taosTimeAdd(key, pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit, pQueryAttr->precision);
418
      } else {
H
Haojun Liao 已提交
419
        key += pQueryAttr->interval.sliding;
420 421 422 423 424 425 426 427 428 429 430
      }

      if (key >= ts) {
        break;
      }

      w->skey = key;
    }
  }
}

431
// get the correct time window according to the handled timestamp
H
Haojun Liao 已提交
432
static STimeWindow getActiveTimeWindow(SResultRowInfo * pResultRowInfo, int64_t ts, SQueryAttr *pQueryAttr) {
433
  STimeWindow w = {0};
434

H
Haojun Liao 已提交
435
 if (pResultRowInfo->curIndex == -1) {  // the first window, from the previous stored value
436
    if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
437
      getInitialStartTimeWindow(pQueryAttr, ts, &w);
438 439 440 441
      pResultRowInfo->prevSKey = w.skey;
    } else {
      w.skey = pResultRowInfo->prevSKey;
    }
H
Haojun Liao 已提交
442

H
Haojun Liao 已提交
443 444
    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
      w.ekey = taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
445
    } else {
H
Haojun Liao 已提交
446
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
447
    }
448
  } else {
H
Haojun Liao 已提交
449 450
    int32_t slot = curTimeWindowIndex(pResultRowInfo);
    SResultRow* pWindowRes = getResultRow(pResultRowInfo, slot);
451
    w = pWindowRes->win;
452
  }
453

454
  if (w.skey > ts || w.ekey < ts) {
H
Haojun Liao 已提交
455 456 457
    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
      w.skey = taosTimeTruncate(ts, &pQueryAttr->interval, pQueryAttr->precision);
      w.ekey = taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
458 459
    } else {
      int64_t st = w.skey;
460

461
      if (st > ts) {
H
Haojun Liao 已提交
462
        st -= ((st - ts + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
463
      }
464

H
Haojun Liao 已提交
465
      int64_t et = st + pQueryAttr->interval.interval - 1;
466
      if (et < ts) {
H
Haojun Liao 已提交
467
        st += ((ts - et + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
468
      }
469

470
      w.skey = st;
H
Haojun Liao 已提交
471
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
472
    }
473
  }
474

475 476 477 478
  /*
   * 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.
   */
H
Haojun Liao 已提交
479 480
  if (w.ekey > pQueryAttr->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
    w.ekey = pQueryAttr->window.ekey;
481
  }
482

483 484 485
  return w;
}

H
Haojun Liao 已提交
486 487
// 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) {
488
  if (pWindowRes->pageId != -1) {
489 490
    return 0;
  }
491

492
  tFilePage *pData = NULL;
493

494 495
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
496
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
497

H
Haojun Liao 已提交
498
  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
499
    pData = getNewDataBuf(pResultBuf, tid, &pageId);
500
  } else {
H
Haojun Liao 已提交
501 502 503
    SPageInfo* pi = getLastPageInfo(list);
    pData = getResBufPage(pResultBuf, pi->pageId);
    pageId = pi->pageId;
504

H
Haojun Liao 已提交
505
    if (pData->num + size > pResultBuf->pageSize) {
H
Haojun Liao 已提交
506 507
      // release current page first, and prepare the next one
      releaseResBufPageInfo(pResultBuf, pi);
H
Haojun Liao 已提交
508
      pData = getNewDataBuf(pResultBuf, tid, &pageId);
509
      if (pData != NULL) {
510
        assert(pData->num == 0);  // number of elements must be 0 for new allocated buffer
511 512 513
      }
    }
  }
514

515 516 517
  if (pData == NULL) {
    return -1;
  }
518

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

H
Haojun Liao 已提交
524
    pData->num += size;
525
    assert(pWindowRes->pageId >= 0);
526
  }
527

528 529 530
  return 0;
}

531
static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, STimeWindow *win,
532
                                       bool masterscan, SResultRow **pResult, int64_t groupId, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
533
                                       int32_t numOfOutput, int32_t* rowCellInfoOffset) {
534 535
  assert(win->skey <= win->ekey);
  SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
536

537
  SResultRow *pResultRow = doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char *)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
H
Haojun Liao 已提交
538
  if (pResultRow == NULL) {
539 540
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
541
  }
542

543
  // not assign result buffer yet, add new result buffer
H
Haojun Liao 已提交
544
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
545
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, (int32_t) groupId, pRuntimeEnv->pQueryAttr->intermediateResultRowSize);
H
Haojun Liao 已提交
546
    if (ret != TSDB_CODE_SUCCESS) {
547 548 549
      return -1;
    }
  }
550

551
  // set time window for current result
H
Haojun Liao 已提交
552
  pResultRow->win = (*win);
553
  *pResult = pResultRow;
H
Haojun Liao 已提交
554
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
555

556 557 558
  return TSDB_CODE_SUCCESS;
}

559 560 561 562 563 564 565 566 567
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 已提交
568
static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
569 570 571 572 573 574 575 576
  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 已提交
577
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
578 579
                                      int16_t order, int64_t *pData) {
  int32_t forwardStep = 0;
580

H
Haojun Liao 已提交
581 582 583 584
  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*) &pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
      forwardStep = end;
585

H
Haojun Liao 已提交
586 587 588 589 590 591 592 593 594 595 596 597
      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;
      }
598 599
    }
  }
600

H
Haojun Liao 已提交
601
  assert(forwardStep > 0);
602 603 604
  return forwardStep;
}

605
static void doUpdateResultRowIndex(SResultRowInfo*pResultRowInfo, TSKEY lastKey, bool ascQuery, bool timeWindowInterpo) {
H
Haojun Liao 已提交
606
  int64_t skey = TSKEY_INITIAL_VAL;
607 608 609
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
H
Haojun Liao 已提交
610
    if (pResult->closed) {
611
      break;
H
Haojun Liao 已提交
612 613
    }

614
    // new closed result rows
615 616 617 618 619 620 621 622 623 624
    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 已提交
625
    } else {
626 627 628 629 630
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
H
Haojun Liao 已提交
631 632 633
    }
  }

634
  // all result rows are closed, set the last one to be the skey
H
Haojun Liao 已提交
635
  if (skey == TSKEY_INITIAL_VAL) {
636
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
H
Haojun Liao 已提交
637 638
  } else {

639 640 641 642 643
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
644
    }
645

D
fix bug  
dapan1121 已提交
646
    if (i == pResultRowInfo->size - 1) {
647
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
648 649 650 651
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

652
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
653
  }
654
}
655

H
Haojun Liao 已提交
656 657 658
static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, SQueryAttr* pQueryAttr, TSKEY lastKey) {
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
  if ((lastKey > pQueryAttr->window.ekey && ascQuery) || (lastKey < pQueryAttr->window.ekey && (!ascQuery))) {
659 660 661
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
662
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
663
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQueryAttr->timeWindowInterpo);
664
  }
665 666
}

H
Haojun Liao 已提交
667
static int32_t getNumOfRowsInTimeWindow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo *pDataBlockInfo, TSKEY *pPrimaryColumn,
H
hjxilinx 已提交
668
                                        int32_t startPos, TSKEY ekey, __block_search_fn_t searchFn, bool updateLastKey) {
669
  assert(startPos >= 0 && startPos < pDataBlockInfo->rows);
H
Haojun Liao 已提交
670
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
671
  STableQueryInfo* item = pRuntimeEnv->current;
672

H
Haojun Liao 已提交
673
  int32_t num   = -1;
H
Haojun Liao 已提交
674
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
675
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
676

H
Haojun Liao 已提交
677
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
678
    if (ekey < pDataBlockInfo->window.ekey) {
679
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
680 681
      if (updateLastKey) { // update the last key
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
682 683
      }
    } else {
684
      num = pDataBlockInfo->rows - startPos;
685
      if (updateLastKey) {
H
hjxilinx 已提交
686
        item->lastKey = pDataBlockInfo->window.ekey + step;
687 688 689 690
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey) {
691
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
H
Haojun Liao 已提交
692 693
      if (updateLastKey) {  // update the last key
        item->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
694 695 696 697
      }
    } else {
      num = startPos + 1;
      if (updateLastKey) {
H
hjxilinx 已提交
698
        item->lastKey = pDataBlockInfo->window.skey + step;
699 700 701
      }
    }
  }
702

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

H
Haojun Liao 已提交
707 708
static void doApplyFunctions(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, STimeWindow* pWin, int32_t offset,
                             int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput) {
H
Haojun Liao 已提交
709
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
710 711
  bool hasPrev = pCtx[0].preAggVals.isSet;

712
  for (int32_t k = 0; k < numOfOutput; ++k) {
713
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
714
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
715

716
    char* start = pCtx[k].pInput;
H
Haojun Liao 已提交
717

H
Haojun Liao 已提交
718
    int32_t pos = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? offset : offset - (forwardStep - 1);
719 720
    if (pCtx[k].pInput != NULL) {
      pCtx[k].pInput = (char *)pCtx[k].pInput + pos * pCtx[k].inputBytes;
H
Haojun Liao 已提交
721 722 723 724 725
    }

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

H
Haojun Liao 已提交
727
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
728

729 730 731 732 733
    // 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 已提交
734

735 736
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
737
    }
738 739 740

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
741
    pCtx[k].pInput = start;
742 743 744 745
  }
}


H
Haojun Liao 已提交
746
static int32_t getNextQualifiedWindow(SQueryAttr* pQueryAttr, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
747
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
748
  getNextTimeWindow(pQueryAttr, pNext);
749

H
Haojun Liao 已提交
750
  // next time window is not in current block
H
Haojun Liao 已提交
751 752
  if ((pNext->skey > pDataBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
      (pNext->ekey < pDataBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
H
Haojun Liao 已提交
753 754
    return -1;
  }
755

H
Haojun Liao 已提交
756
  TSKEY startKey = -1;
H
Haojun Liao 已提交
757
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
758
    startKey = pNext->skey;
H
Haojun Liao 已提交
759 760
    if (startKey < pQueryAttr->window.skey) {
      startKey = pQueryAttr->window.skey;
761
    }
H
Haojun Liao 已提交
762
  } else {
H
Haojun Liao 已提交
763
    startKey = pNext->ekey;
H
Haojun Liao 已提交
764 765
    if (startKey > pQueryAttr->window.skey) {
      startKey = pQueryAttr->window.skey;
766
    }
H
Haojun Liao 已提交
767
  }
768

H
Haojun Liao 已提交
769
  int32_t startPos = 0;
H
Haojun Liao 已提交
770

H
Haojun Liao 已提交
771
  // tumbling time window query, a special case of sliding time window query
H
Haojun Liao 已提交
772 773
  if (pQueryAttr->interval.sliding == pQueryAttr->interval.interval && prevPosition != -1) {
    int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
774 775
    startPos = prevPosition + factor;
  } else {
H
Haojun Liao 已提交
776
    if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
777
      startPos = 0;
H
Haojun Liao 已提交
778
    } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
779 780
      startPos = pDataBlockInfo->rows - 1;
    } else {
H
Haojun Liao 已提交
781
      startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQueryAttr->order.order);
H
Haojun Liao 已提交
782
    }
H
Haojun Liao 已提交
783
  }
784

H
Haojun Liao 已提交
785 786 787 788
  /*
   * 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 已提交
789
  if (primaryKeys == NULL) {
H
Haojun Liao 已提交
790
    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
791
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
792
    } else {
H
Haojun Liao 已提交
793
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
794
    }
H
Haojun Liao 已提交
795
  } else {
H
Haojun Liao 已提交
796
    if (QUERY_IS_ASC_QUERY(pQueryAttr) && primaryKeys[startPos] > pNext->ekey) {
H
Haojun Liao 已提交
797
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
798 799 800
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQueryAttr->interval, pQueryAttr->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
801
      } else {
H
Haojun Liao 已提交
802 803
        pNext->ekey += ((next - pNext->ekey + pQueryAttr->interval.sliding - 1)/pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
        pNext->skey = pNext->ekey - pQueryAttr->interval.interval + 1;
H
Haojun Liao 已提交
804
      }
H
Haojun Liao 已提交
805
    } else if ((!QUERY_IS_ASC_QUERY(pQueryAttr)) && primaryKeys[startPos] < pNext->skey) {
H
Haojun Liao 已提交
806
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
807 808 809
      if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
        pNext->skey = taosTimeTruncate(next, &pQueryAttr->interval, pQueryAttr->precision);
        pNext->ekey = taosTimeAdd(pNext->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
810
      } else {
H
Haojun Liao 已提交
811 812
        pNext->skey -= ((pNext->skey - next + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
        pNext->ekey = pNext->skey + pQueryAttr->interval.interval - 1;
H
Haojun Liao 已提交
813
      }
814
    }
815
  }
816

H
Haojun Liao 已提交
817
  return startPos;
818 819
}

H
Haojun Liao 已提交
820
static FORCE_INLINE TSKEY reviseWindowEkey(SQueryAttr *pQueryAttr, STimeWindow *pWindow) {
821
  TSKEY ekey = -1;
H
Haojun Liao 已提交
822
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
823
    ekey = pWindow->ekey;
H
Haojun Liao 已提交
824 825
    if (ekey > pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
826 827 828
    }
  } else {
    ekey = pWindow->skey;
H
Haojun Liao 已提交
829 830
    if (ekey < pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
831 832
    }
  }
833

834 835 836
  return ekey;
}

H
Haojun Liao 已提交
837 838 839 840 841 842 843 844 845 846 847 848
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;
    }
  }
}

849
// window start key interpolation
H
Haojun Liao 已提交
850

851

H
Haojun Liao 已提交
852
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
853
    int32_t rowIndex) {
854 855 856 857
  if (pDataBlock == NULL) {
    return;
  }

H
Haojun Liao 已提交
858 859
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  for (int32_t k = 0; k < pQueryAttr->numOfCols; ++k) {
860
    SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, k);
H
Haojun Liao 已提交
861
    memcpy(pRuntimeEnv->prevRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
862 863 864
  }
}

H
Haojun Liao 已提交
865
static TSKEY getStartTsKey(SQueryAttr* pQueryAttr, STimeWindow* win, const TSKEY* tsCols, int32_t rows) {
866 867
  TSKEY ts = TSKEY_INITIAL_VAL;

H
Haojun Liao 已提交
868
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
869
  if (tsCols == NULL) {
H
Haojun Liao 已提交
870
    ts = ascQuery? win->skey : win->ekey;
871
  } else {
H
Haojun Liao 已提交
872
    int32_t offset = ascQuery? 0:rows-1;
873 874 875 876 877 878
    ts = tsCols[offset];
  }

  return ts;
}

H
Haojun Liao 已提交
879 880
static void setArithParams(SArithmeticSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) {
  sas->numOfCols = (int32_t) pSDataBlock->info.numOfCols;
H
Haojun Liao 已提交
881
  sas->pExprInfo = pExprInfo;
H
Haojun Liao 已提交
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901

  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 已提交
902
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
903
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
904

H
Haojun Liao 已提交
905 906 907 908
    setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);
  }
}

H
Haojun Liao 已提交
909
void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
H
Haojun Liao 已提交
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
  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 已提交
929
    pCtx[i].size  = pBlock->info.rows;
sangshuduo's avatar
sangshuduo 已提交
930
    pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag;
H
Haojun Liao 已提交
931 932 933 934 935 936 937

    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 已提交
938 939
      if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || (pCol->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) ||
          (TSDB_COL_IS_TAG(pCol->flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
H
Haojun Liao 已提交
940 941
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
H
Haojun Liao 已提交
942

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

H
Haojun Liao 已提交
947
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
948
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
949
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
950
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
951
        }
H
Haojun Liao 已提交
952 953 954 955 956 957 958 959 960 961
      } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);

        pCtx[i].pInput = p->pData;
        assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type);
        for(int32_t j = 0; j < pBlock->info.rows; ++j) {
          char* dst = p->pData + j * p->info.bytes;
          tVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
        }
H
Haojun Liao 已提交
962 963 964 965 966
      }
    }
  }
}

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

H
Haojun Liao 已提交
970
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
971
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
972
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
H
Haojun Liao 已提交
973
      pCtx[k].startTs = startTs;// this can be set during create the struct
H
Haojun Liao 已提交
974 975 976 977 978
      aAggs[functionId].xFunction(&pCtx[k]);
    }
  }
}

H
Haojun Liao 已提交
979
static void arithmeticApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
980
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
981

H
Haojun Liao 已提交
982
  for (int32_t k = 0; k < numOfOutput; ++k) {
H
Haojun Liao 已提交
983
    pCtx[k].startTs = pQueryAttr->window.skey;
H
Haojun Liao 已提交
984 985 986 987 988 989

    // Always set the asc order for merge stage process
    if (pCtx[k].currentStage == MERGE_STAGE) {
      pCtx[k].order = TSDB_ORDER_ASC;
    }

990
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
991 992 993
  }
}

H
Haojun Liao 已提交
994 995
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 已提交
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
  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 已提交
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
    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 已提交
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048

      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 已提交
1049 1050
static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx, int32_t pos,
                                              int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols, STimeWindow* win) {
H
Haojun Liao 已提交
1051
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
1052
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1053

H
Haojun Liao 已提交
1054
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1055

H
Haojun Liao 已提交
1056 1057 1058 1059 1060
  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 已提交
1061
  TSKEY key = ascQuery? win->skey:win->ekey;
H
Haojun Liao 已提交
1062 1063 1064 1065 1066
  if (key == curTs) {
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

H
Haojun Liao 已提交
1067
  if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
H
Haojun Liao 已提交
1068 1069 1070 1071
    setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfOutput, RESULT_ROW_START_INTERP);
    return true;
  }

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

H
Haojun Liao 已提交
1075 1076
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1077 1078 1079 1080
  return true;
}

static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SQLFunctionCtx* pCtx,
H
Haojun Liao 已提交
1081
    int32_t endRowIndex, SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
H
Haojun Liao 已提交
1082
  SQueryRuntimeEnv *pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
1083
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1084 1085 1086 1087
  int32_t numOfOutput = pOperatorInfo->numOfOutput;

  TSKEY   actualEndKey = tsCols[endRowIndex];

H
Haojun Liao 已提交
1088
  TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? win->ekey:win->skey;
H
Haojun Liao 已提交
1089 1090

  // not ended in current data block, do not invoke interpolation
H
Haojun Liao 已提交
1091
  if ((key > blockEkey && QUERY_IS_ASC_QUERY(pQueryAttr)) || (key < blockEkey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
H
Haojun Liao 已提交
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
    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;
  }

H
Haojun Liao 已提交
1102
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1103 1104 1105 1106
  int32_t nextRowIndex = endRowIndex + step;
  assert(nextRowIndex >= 0);

  TSKEY nextKey = tsCols[nextRowIndex];
H
Haojun Liao 已提交
1107 1108
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
      nextRowIndex, key, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1109 1110 1111 1112 1113 1114
  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;
H
Haojun Liao 已提交
1115 1116
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  if (!pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1117 1118 1119 1120
    return;
  }

  assert(pBlock != NULL);
H
Haojun Liao 已提交
1121
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1122 1123 1124 1125 1126 1127 1128 1129

  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 已提交
1130
        tsCols, win);
H
Haojun Liao 已提交
1131 1132 1133 1134
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    }
  } else {
H
Haojun Liao 已提交
1135
    setNotInterpoWindowKey(pCtx, pQueryAttr->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1136 1137 1138
  }

  // point interpolation does not require the end key time window interpolation.
H
Haojun Liao 已提交
1139
  if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
1140 1141 1142 1143 1144 1145 1146 1147
    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;

H
Haojun Liao 已提交
1148
    TSKEY endKey = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey:pBlock->info.window.skey;
H
Haojun Liao 已提交
1149 1150 1151 1152 1153
    bool  interp = setTimeWindowInterpolationEndTs(pOperatorInfo, pCtx, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
    }
  } else {
H
Haojun Liao 已提交
1154
    setNotInterpoWindowKey(pCtx, pQueryAttr->numOfOutput, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1155 1156 1157
  }
}

H
Haojun Liao 已提交
1158 1159 1160
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pSDataBlock, int32_t groupId) {
  STableIntervalOperatorInfo* pInfo = (STableIntervalOperatorInfo*) pOperatorInfo->info;

H
Haojun Liao 已提交
1161 1162
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
H
Haojun Liao 已提交
1163
  SQueryAttr*           pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1164

H
Haojun Liao 已提交
1165 1166
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1167

H
Haojun Liao 已提交
1168
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1169

H
Haojun Liao 已提交
1170 1171 1172
  TSKEY* tsCols = NULL;
  if (pSDataBlock->pDataBlock != NULL) {
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, 0);
H
Haojun Liao 已提交
1173
    tsCols = (int64_t*) pColDataInfo->pData;
H
Haojun Liao 已提交
1174 1175
    assert(tsCols[0] == pSDataBlock->info.window.skey &&
           tsCols[pSDataBlock->info.rows - 1] == pSDataBlock->info.window.ekey);
H
Haojun Liao 已提交
1176 1177
  }

H
Haojun Liao 已提交
1178
  int32_t startPos = ascQuery? 0 : (pSDataBlock->info.rows - 1);
H
Haojun Liao 已提交
1179
  TSKEY ts = getStartTsKey(pQueryAttr, &pSDataBlock->info.window, tsCols, pSDataBlock->info.rows);
H
Haojun Liao 已提交
1180

H
Haojun Liao 已提交
1181
  STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQueryAttr);
H
Haojun Liao 已提交
1182
  bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);
H
Haojun Liao 已提交
1183

H
Haojun Liao 已提交
1184 1185 1186
  SResultRow* pResult = NULL;
  int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                        numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1187
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1188
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1189 1190 1191
  }

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1192
  TSKEY   ekey = reviseWindowEkey(pQueryAttr, &win);
H
Haojun Liao 已提交
1193
  forwardStep =
H
Haojun Liao 已提交
1194
      getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1195 1196

  // prev time window not interpolation yet.
H
Haojun Liao 已提交
1197
  int32_t curIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1198
  if (prevIndex != -1 && prevIndex < curIndex && pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1199
    for (int32_t j = prevIndex; j < curIndex; ++j) {  // previous time window may be all closed already.
H
Haojun Liao 已提交
1200
      SResultRow* pRes = pResultRowInfo->pResult[j];
H
Haojun Liao 已提交
1201
      if (pRes->closed) {
H
Haojun Liao 已提交
1202 1203
        assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) &&
               resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
H
Haojun Liao 已提交
1204
        continue;
H
Haojun Liao 已提交
1205
      }
H
Haojun Liao 已提交
1206 1207

      STimeWindow w = pRes->win;
H
Haojun Liao 已提交
1208 1209
      ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &w, masterScan, &pResult, groupId, pInfo->pCtx,
                                    numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1210 1211 1212 1213 1214
      if (ret != TSDB_CODE_SUCCESS) {
        longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
      }

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

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

H
Haojun Liao 已提交
1219
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1220
      setNotInterpoWindowKey(pInfo->pCtx, pQueryAttr->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1221

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

H
Haojun Liao 已提交
1225
    // restore current time window
H
Haojun Liao 已提交
1226 1227
    ret = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &win, masterScan, &pResult, groupId, pInfo->pCtx,
                                  numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1228 1229 1230
    if (ret != TSDB_CODE_SUCCESS) {
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
H
Haojun Liao 已提交
1231 1232 1233
  }

  // window start key interpolation
H
Haojun Liao 已提交
1234
  doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
1235
  doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
H
Haojun Liao 已提交
1236 1237 1238 1239

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = (forwardStep - 1) * step + startPos;
H
Haojun Liao 已提交
1240
    startPos = getNextQualifiedWindow(pQueryAttr, &nextWin, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
H
Haojun Liao 已提交
1241 1242
    if (startPos < 0) {
      break;
H
Haojun Liao 已提交
1243 1244
    }

H
Haojun Liao 已提交
1245
    // null data, failed to allocate more memory buffer
H
Haojun Liao 已提交
1246 1247
    int32_t code = setWindowOutputBufByKey(pRuntimeEnv, pResultRowInfo, &nextWin, masterScan, &pResult, groupId,
                                           pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
1248
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
H
Haojun Liao 已提交
1249
      longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
H
Haojun Liao 已提交
1250 1251
    }

H
Haojun Liao 已提交
1252
    ekey = reviseWindowEkey(pQueryAttr, &nextWin);
H
Haojun Liao 已提交
1253
    forwardStep = getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1254 1255

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

H
Haojun Liao 已提交
1260
  if (pQueryAttr->timeWindowInterpo) {
H
Haojun Liao 已提交
1261
    int32_t rowIndex = ascQuery? (pSDataBlock->info.rows-1):0;
H
Haojun Liao 已提交
1262 1263
    saveDataBlockLastRow(pRuntimeEnv, &pSDataBlock->info, pSDataBlock->pDataBlock, rowIndex);
  }
H
Haojun Liao 已提交
1264

H
Haojun Liao 已提交
1265
  updateResultRowInfoActiveIndex(pResultRowInfo, pQueryAttr, pRuntimeEnv->current->lastKey);
H
Haojun Liao 已提交
1266 1267
}

H
Haojun Liao 已提交
1268 1269
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
1270
  STableQueryInfo*  item = pRuntimeEnv->current;
H
Haojun Liao 已提交
1271

H
Haojun Liao 已提交
1272
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1273 1274 1275 1276

  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int16_t     bytes = pColInfoData->info.bytes;
  int16_t     type = pColInfoData->info.type;
H
Haojun Liao 已提交
1277 1278

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

H
Haojun Liao 已提交
1283
  for (int32_t j = 0; j < pSDataBlock->info.rows; ++j) {
sangshuduo's avatar
sangshuduo 已提交
1284
    char* val = ((char*)pColInfoData->pData) + bytes * j;
H
Haojun Liao 已提交
1285
    if (isNull(val, type)) {
H
Haojun Liao 已提交
1286 1287 1288
      continue;
    }

1289
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1290 1291 1292 1293 1294 1295 1296
    if (pInfo->prevData == NULL || (memcmp(pInfo->prevData, val, bytes) != 0)) {
      if (pInfo->prevData == NULL) {
        pInfo->prevData = malloc(bytes);
      }

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

H
Haojun Liao 已提交
1297 1298 1299 1300
      if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
        setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, val, bytes);
      }

H
Haojun Liao 已提交
1301 1302 1303 1304 1305
      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 已提交
1306 1307
    }

H
Haojun Liao 已提交
1308
    for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
1309
      pInfo->binfo.pCtx[k].size = 1;
H
Haojun Liao 已提交
1310 1311
      int32_t functionId = pInfo->binfo.pCtx[k].functionId;
      if (functionNeedToExecute(pRuntimeEnv, &pInfo->binfo.pCtx[k], functionId)) {
H
Haojun Liao 已提交
1312
        aAggs[functionId].xFunctionF(&pInfo->binfo.pCtx[k], j);
H
Haojun Liao 已提交
1313 1314 1315 1316 1317
      }
    }
  }
}

1318 1319
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSWindowOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
1320
  STableQueryInfo*  item = pRuntimeEnv->current;
1321 1322 1323 1324 1325 1326 1327

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

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

H
Haojun Liao 已提交
1328
  int64_t gap = pOperator->pRuntimeEnv->pQueryAttr->sw.gap;
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
  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 已提交
1378
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
  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 已提交
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
}

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

H
Haojun Liao 已提交
1412
  setResultRowKey(pResultRow, pData, type);
H
Haojun Liao 已提交
1413
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
1414
    int32_t ret = addNewWindowResultBuf(pResultRow, pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
H
Haojun Liao 已提交
1415 1416 1417 1418 1419
    if (ret != 0) {
      return -1;
    }
  }

H
Haojun Liao 已提交
1420 1421
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1422 1423
  return TSDB_CODE_SUCCESS;
}
1424

H
Haojun Liao 已提交
1425
static int32_t getGroupbyColumnIndex(SSqlGroupbyExpr *pGroupbyExpr, SSDataBlock* pDataBlock) {
H
Haojun Liao 已提交
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
  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 已提交
1443
  return -1;
H
Haojun Liao 已提交
1444 1445
}

1446
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId) {
H
Haojun Liao 已提交
1447
  SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
H
Haojun Liao 已提交
1448
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1449 1450 1451 1452 1453

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

1455 1456 1457
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1458

1459
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
Haojun Liao 已提交
1460
    return QUERY_IS_ASC_QUERY(pQueryAttr);
H
hjxilinx 已提交
1461
  }
1462

H
Haojun Liao 已提交
1463
  // denote the order type
1464
  if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
H
Haojun Liao 已提交
1465
    return pCtx->param[0].i64 == pQueryAttr->order.order;
1466 1467
  }

1468 1469 1470
  // 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)) {
1471 1472
    return false;
  }
1473

1474 1475 1476
  return true;
}

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

H
Haojun Liao 已提交
1480 1481 1482 1483
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

    pCtx->preAggVals.statis = *pStatis;
H
Haojun Liao 已提交
1484 1485 1486 1487 1488 1489
    pCtx->preAggVals.isSet  = true;
    assert(pCtx->preAggVals.statis.numOfNull <= pSDataBlock->info.rows);
  } else {
    pCtx->preAggVals.isSet = false;
  }

H
Haojun Liao 已提交
1490
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1491 1492

  // set the statistics data for primary time stamp column
H
Haojun Liao 已提交
1493
  if (pCtx->functionId == TSDB_FUNC_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
H
Haojun Liao 已提交
1494
    pCtx->preAggVals.isSet  = true;
H
Haojun Liao 已提交
1495 1496
    pCtx->preAggVals.statis.min = pSDataBlock->info.window.skey;
    pCtx->preAggVals.statis.max = pSDataBlock->info.window.ekey;
H
Haojun Liao 已提交
1497
  }
H
Haojun Liao 已提交
1498 1499
}

H
Haojun Liao 已提交
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
// 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;
}
1541

H
Haojun Liao 已提交
1542
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1543
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1544
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1545

1546 1547
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1548
    return NULL;
1549 1550
  }

H
Haojun Liao 已提交
1551
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1552 1553 1554 1555
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1556

H
Haojun Liao 已提交
1557
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
1558
    SSqlExpr *pSqlExpr = &pExpr[i].base;
1559
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1560

H
Haojun Liao 已提交
1561
    SColIndex *pIndex = &pSqlExpr->colInfo;
1562

Y
TD-1230  
yihaoDeng 已提交
1563
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1564 1565
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1566
    } else {
1567 1568
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1569

H
Haojun Liao 已提交
1570 1571
    pCtx->inputBytes = pSqlExpr->colBytes;
    pCtx->inputType  = pSqlExpr->colType;
H
Haojun Liao 已提交
1572

1573
    pCtx->ptsOutputBuf = NULL;
1574

H
Haojun Liao 已提交
1575 1576
    pCtx->outputBytes  = pSqlExpr->resBytes;
    pCtx->outputType   = pSqlExpr->resType;
1577

H
Haojun Liao 已提交
1578
    pCtx->order        = pQueryAttr->order.order;
H
Haojun Liao 已提交
1579
    pCtx->functionId   = pSqlExpr->functionId;
H
Haojun Liao 已提交
1580
    pCtx->stableQuery  = pQueryAttr->stableQuery;
H
Haojun Liao 已提交
1581
    pCtx->interBufBytes = pSqlExpr->interBytes;
1582 1583
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1584

H
Haojun Liao 已提交
1585
    pCtx->numOfParams  = pSqlExpr->numOfParams;
1586
    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
H
Haojun Liao 已提交
1587 1588 1589
      int16_t type = pSqlExpr->param[j].nType;
      int16_t bytes = pSqlExpr->param[j].nLen;
      if (pSqlExpr->functionId == TSDB_FUNC_STDDEV_DST) {
1590 1591 1592
        continue;
      }

1593
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
1594
        tVariantCreateFromBinary(&pCtx->param[j], pSqlExpr->param[j].pz, bytes, type);
1595
      } else {
H
Haojun Liao 已提交
1596
        tVariantCreateFromBinary(&pCtx->param[j], (char *)&pSqlExpr->param[j].i64, bytes, type);
1597 1598
      }
    }
1599

1600 1601
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1602

1603
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1604
      int32_t f = pExpr[0].base.functionId;
1605
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1606

H
Haojun Liao 已提交
1607
      pCtx->param[2].i64 = pQueryAttr->order.order;
1608
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1609
      pCtx->param[3].i64 = functionId;
1610
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1611

H
Haojun Liao 已提交
1612
      pCtx->param[1].i64 = pQueryAttr->order.orderColId;
H
Haojun Liao 已提交
1613
    } else if (functionId == TSDB_FUNC_INTERP) {
H
Haojun Liao 已提交
1614 1615 1616
      pCtx->param[2].i64 = (int8_t)pQueryAttr->fillType;
      if (pQueryAttr->fillVal != NULL) {
        if (isNull((const char *)&pQueryAttr->fillVal[i], pCtx->inputType)) {
H
Haojun Liao 已提交
1617 1618 1619
          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) {
H
Haojun Liao 已提交
1620
            tVariantCreateFromBinary(&pCtx->param[1], (char *)&pQueryAttr->fillVal[i], pCtx->inputBytes, pCtx->inputType);
H
Haojun Liao 已提交
1621 1622 1623 1624
          }
        }
      }
    } else if (functionId == TSDB_FUNC_TS_COMP) {
H
Haojun Liao 已提交
1625
      pCtx->param[0].i64 = pQueryAttr->vgId;  //TODO this should be the parameter from client
H
Haojun Liao 已提交
1626 1627
      pCtx->param[0].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_TWA) {
H
Haojun Liao 已提交
1628
      pCtx->param[1].i64 = pQueryAttr->window.skey;
H
Haojun Liao 已提交
1629
      pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT;
H
Haojun Liao 已提交
1630
      pCtx->param[2].i64 = pQueryAttr->window.ekey;
H
Haojun Liao 已提交
1631 1632 1633
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
    } else if (functionId == TSDB_FUNC_ARITHM) {
      pCtx->param[1].pz = (char*) &pRuntimeEnv->sasArray[i];
1634
    }
H
Haojun Liao 已提交
1635
  }
1636

H
Haojun Liao 已提交
1637
  for(int32_t i = 1; i < numOfOutput; ++i) {
sangshuduo's avatar
sangshuduo 已提交
1638
    (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowCellInfo) +
H
Haojun Liao 已提交
1639
        pExpr[i - 1].base.interBytes * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
1640
  }
1641

H
Haojun Liao 已提交
1642 1643
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1644
  return pFuncCtx;
H
Haojun Liao 已提交
1645 1646
}

H
Haojun Liao 已提交
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
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 已提交
1665
static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfTables, SArray* pOperator, void* merger) {
H
Haojun Liao 已提交
1666
  qDebug("QInfo:0x%"PRIx64" setup runtime env", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
1667
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1668 1669

  pRuntimeEnv->prevGroupId = INT32_MIN;
H
Haojun Liao 已提交
1670
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
1671 1672

  pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
H
Haojun Liao 已提交
1673
  pRuntimeEnv->keyBuf  = malloc(pQueryAttr->maxTableColumnWidth + sizeof(int64_t));
H
Haojun Liao 已提交
1674
  pRuntimeEnv->pool    = initResultRowPool(getResultRowSize(pRuntimeEnv));
H
Haojun Liao 已提交
1675 1676 1677
  pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQueryAttr->numOfCols + pQueryAttr->srcRowSize);
  pRuntimeEnv->tagVal  = malloc(pQueryAttr->tagLen);
  pRuntimeEnv->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
1678

H
Haojun Liao 已提交
1679 1680 1681
  // 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 已提交
1682
  pRuntimeEnv->sasArray = calloc(pQueryAttr->numOfOutput, sizeof(SArithmeticSupport));
H
Haojun Liao 已提交
1683

H
Haojun Liao 已提交
1684 1685
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1686 1687 1688
    goto _clean;
  }

H
Haojun Liao 已提交
1689 1690
  if (pQueryAttr->numOfCols) {
    char* start = POINTER_BYTES * pQueryAttr->numOfCols + (char*) pRuntimeEnv->prevRow;
H
Haojun Liao 已提交
1691
    pRuntimeEnv->prevRow[0] = start;
H
Haojun Liao 已提交
1692
    for(int32_t i = 1; i < pQueryAttr->numOfCols; ++i) {
H
Haojun Liao 已提交
1693
      pRuntimeEnv->prevRow[i] = pRuntimeEnv->prevRow[i - 1] + pQueryAttr->tableCols[i-1].bytes;
H
Haojun Liao 已提交
1694
    }
H
Haojun Liao 已提交
1695

H
Haojun Liao 已提交
1696 1697
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1698

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

  // group by normal column, sliding window query, interval query are handled by interval query processor
H
Haojun Liao 已提交
1702
  // interval (down sampling operation)
H
Haojun Liao 已提交
1703
  int32_t numOfOperator = (int32_t) taosArrayGetSize(pOperator);
H
Haojun Liao 已提交
1704 1705 1706 1707 1708
  for(int32_t i = 0; i < numOfOperator; ++i) {
    int32_t* op = taosArrayGet(pOperator, i);

    switch (*op) {
      case OP_TagScan: {
H
Haojun Liao 已提交
1709
        pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1710 1711 1712 1713
        break;
      }
      case OP_MultiTableTimeInterval: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1714 1715
            createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1716 1717 1718 1719
        break;
      }
      case OP_TimeWindow: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1720 1721
            createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1722 1723 1724 1725
        break;
      }
      case OP_Groupby: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1726 1727
            createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1728 1729 1730 1731
        break;
      }
      case OP_SessionWindow: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1732 1733
            createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1734 1735 1736 1737
        break;
      }
      case OP_MultiTableAggregate: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1738 1739
            createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1740 1741 1742 1743
        break;
      }
      case OP_Aggregate: {
        pRuntimeEnv->proot =
H
Haojun Liao 已提交
1744 1745 1746
            createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
        if (pRuntimeEnv->proot->upstream->operatorType != OP_DummyInput) {
          setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1747
        }
H
Haojun Liao 已提交
1748 1749 1750
        break;
      }

H
Haojun Liao 已提交
1751
      case OP_Arithmetic: {  // TODO refactor to remove arith operator.
H
Haojun Liao 已提交
1752
        SOperatorInfo* prev = pRuntimeEnv->proot;
H
Haojun Liao 已提交
1753
        if (i == 0) {
H
Haojun Liao 已提交
1754
          pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1755 1756
          if (pRuntimeEnv->proot != NULL && pRuntimeEnv->proot->operatorType != OP_DummyInput) {  // TODO refactor
            setTableScanFilterOperatorInfo(prev->info, pRuntimeEnv->proot);
H
Haojun Liao 已提交
1757
          }
H
Haojun Liao 已提交
1758
        } else {
H
Haojun Liao 已提交
1759
          prev = pRuntimeEnv->proot;
H
Haojun Liao 已提交
1760
          assert(pQueryAttr->pExpr2 != NULL);
H
Haojun Liao 已提交
1761
          pRuntimeEnv->proot = createArithOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
H
Haojun Liao 已提交
1762 1763 1764 1765 1766 1767 1768 1769 1770
        }
        break;
      }

      case OP_Limit: {
        pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot);
        break;
      }

H
Haojun Liao 已提交
1771
      case OP_Filter: {  // todo refactor
1772 1773
        assert(pQueryAttr->havingNum > 0);
        if (pQueryAttr->stableQuery) {
H
Haojun Liao 已提交
1774
          pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
1775
        } else {
H
Haojun Liao 已提交
1776
          pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1777 1778 1779
        }
        break;
      }
H
Haojun Liao 已提交
1780

H
Haojun Liao 已提交
1781 1782 1783 1784 1785 1786
      case OP_Fill: {
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
        break;
      }

1787
      case OP_MultiwayMergeSort: {
H
Haojun Liao 已提交
1788 1789 1790 1791
        bool groupMix = true;
        if(pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) {
          groupMix = false;
        }
H
Haojun Liao 已提交
1792
        pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput,
H
Haojun Liao 已提交
1793
            4096, merger, groupMix); // TODO hack it
H
Haojun Liao 已提交
1794
        break;
H
Haojun Liao 已提交
1795
      }
H
Haojun Liao 已提交
1796

H
Haojun Liao 已提交
1797
      case OP_GlobalAggregate: {
1798 1799
        pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
                                                               pQueryAttr->numOfExpr3, merger);
H
Haojun Liao 已提交
1800 1801 1802 1803
        break;
      }

      case OP_SLimit: {
H
Haojun Liao 已提交
1804
        pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
1805 1806 1807 1808 1809 1810
                                                      pQueryAttr->numOfExpr3, merger);
        break;
      }

      case OP_Distinct: {
        pRuntimeEnv->proot = createDistinctOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
H
Haojun Liao 已提交
1811
        break;
H
Haojun Liao 已提交
1812
      }
H
Haojun Liao 已提交
1813

H
Haojun Liao 已提交
1814 1815
      default: {
        assert(0);
H
Haojun Liao 已提交
1816
      }
H
Haojun Liao 已提交
1817
    }
H
Haojun Liao 已提交
1818
  }
H
Haojun Liao 已提交
1819

H
Haojun Liao 已提交
1820
  return TSDB_CODE_SUCCESS;
1821

1822
_clean:
1823
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1824 1825 1826 1827
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1828

1829
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1830 1831
}

H
Haojun Liao 已提交
1832
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1833
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1834 1835 1836 1837

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

H
Haojun Liao 已提交
1838
  SMemRef* pMemRef = &pQueryAttr->memRef;
1839
  assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
H
Haojun Liao 已提交
1840 1841
}

H
Haojun Liao 已提交
1842
static void destroyTsComp(SQueryRuntimeEnv *pRuntimeEnv, SQueryAttr *pQueryAttr) {
H
Haojun Liao 已提交
1843
  if (pQueryAttr->tsCompQuery && pRuntimeEnv->outputBuf && pRuntimeEnv->outputBuf->pDataBlock && taosArrayGetSize(pRuntimeEnv->outputBuf->pDataBlock) > 0) {
D
dapan1121 已提交
1844
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
D
dapan1121 已提交
1845 1846 1847 1848 1849 1850
    if (pColInfoData) {
      FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
      if (f) {
        fclose(f);
        *(FILE **)pColInfoData->pData = NULL;
      }
D
dapan1121 已提交
1851 1852 1853 1854
    }
  }
}

H
Haojun Liao 已提交
1855
static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
H
Haojun Liao 已提交
1856
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1857
  SQInfo* pQInfo = (SQInfo*) pRuntimeEnv->qinfo;
1858

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

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

    tfree(pRuntimeEnv->sasArray);
  }

H
Haojun Liao 已提交
1870
  destroyResultBuf(pRuntimeEnv->pResultBuf);
H
Haojun Liao 已提交
1871
  doFreeQueryHandle(pRuntimeEnv);
1872

H
Haojun Liao 已提交
1873 1874
  destroyTsComp(pRuntimeEnv, pQueryAttr);

H
Haojun Liao 已提交
1875
  pRuntimeEnv->pTsBuf = tsBufDestroy(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
1876

S
TD-1848  
Shengliang Guan 已提交
1877
  tfree(pRuntimeEnv->keyBuf);
1878
  tfree(pRuntimeEnv->prevRow);
1879 1880
  tfree(pRuntimeEnv->tagVal);

H
Haojun Liao 已提交
1881 1882
  taosHashCleanup(pRuntimeEnv->pResultRowHashTable);
  pRuntimeEnv->pResultRowHashTable = NULL;
1883

H
Haojun Liao 已提交
1884 1885 1886
  taosHashCleanup(pRuntimeEnv->pTableRetrieveTsMap);
  pRuntimeEnv->pTableRetrieveTsMap = NULL;

H
Haojun Liao 已提交
1887
  destroyOperatorInfo(pRuntimeEnv->proot);
D
dapan1121 已提交
1888 1889 1890 1891

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

1894 1895 1896 1897
static bool needBuildResAfterQueryComplete(SQInfo* pQInfo) {
  return pQInfo->rspContext != NULL;
}

H
Haojun Liao 已提交
1898
bool isQueryKilled(SQInfo *pQInfo) {
1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
  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 已提交
1909 1910
    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d sec, abort current query execution, start:%" PRId64
           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
1911 1912 1913 1914 1915 1916
    return true;
  }

  return false;
}

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

H
Haojun Liao 已提交
1919 1920
//static bool isFixedOutputQuery(SQueryAttr* pQueryAttr) {
//  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
1921 1922 1923 1924
//    return false;
//  }
//
//  // Note:top/bottom query is fixed output query
H
Haojun Liao 已提交
1925
//  if (pQueryAttr->topBotQuery || pQueryAttr->groupbyColumn || pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
1926 1927 1928
//    return true;
//  }
//
H
Haojun Liao 已提交
1929 1930
//  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
//    SSqlExpr *pExpr = &pQueryAttr->pExpr1[i].base;
H
Haojun Liao 已提交
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942
//
//    if (pExpr->functionId == TSDB_FUNC_TS || pExpr->functionId == TSDB_FUNC_TS_DUMMY) {
//      continue;
//    }
//
//    if (!IS_MULTIOUTPUT(aAggs[pExpr->functionId].status)) {
//      return true;
//    }
//  }
//
//  return false;
//}
1943

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

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

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

1970 1971 1972
  return false;
}

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

1981 1982 1983
  return false;
}

D
init  
dapan1121 已提交
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
static bool isCachedLastQuery(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionID = pQueryAttr->pExpr1[i].base.functionId;
    if (functionID == TSDB_FUNC_LAST || functionID == TSDB_FUNC_LAST_DST) {
      continue;
    }

    return false;
  }

D
fix bug  
dapan1121 已提交
1994
  if (pQueryAttr->order.order != TSDB_ORDER_DESC || !TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_DESC_INITIALIZER)) {
D
init  
dapan1121 已提交
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
    return false;
  }

  if (pQueryAttr->groupbyColumn) {
    return false;
  }

  if (pQueryAttr->interval.interval > 0) {
    return false;
  }

  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->havingNum > 0) {
    return false;
  }

  return true;
}



H
Haojun Liao 已提交
2015 2016 2017 2018
/**
 * 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 已提交
2019 2020 2021
bool onlyQueryTags(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pQueryAttr->pExpr1[i];
H
Haojun Liao 已提交
2022 2023

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
2024 2025 2026 2027

    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 已提交
2028
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
2029 2030 2031
      return false;
    }
  }
2032

H
hjxilinx 已提交
2033 2034 2035
  return true;
}

2036 2037
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2038 2039 2040
void getAlignQueryTimeWindow(SQueryAttr *pQueryAttr, int64_t key, int64_t keyFirst, int64_t keyLast, STimeWindow *win) {
  assert(key >= keyFirst && key <= keyLast && pQueryAttr->interval.sliding <= pQueryAttr->interval.interval);
  win->skey = taosTimeTruncate(key, &pQueryAttr->interval, pQueryAttr->precision);
H
Haojun Liao 已提交
2041 2042

  /*
H
Haojun Liao 已提交
2043
   * if the realSkey > INT64_MAX - pQueryAttr->interval.interval, the query duration between
H
Haojun Liao 已提交
2044 2045
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
H
Haojun Liao 已提交
2046 2047
  if (keyFirst > (INT64_MAX - pQueryAttr->interval.interval)) {
    assert(keyLast - keyFirst < pQueryAttr->interval.interval);
2048
    win->ekey = INT64_MAX;
H
Haojun Liao 已提交
2049 2050
  } else if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
    win->ekey = taosTimeAdd(win->skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) - 1;
H
Haojun Liao 已提交
2051
  } else {
H
Haojun Liao 已提交
2052
    win->ekey = win->skey + pQueryAttr->interval.interval - 1;
2053 2054 2055 2056 2057 2058
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2059
bool colIdCheck(SQueryAttr *pQueryAttr, uint64_t qId) {
2060
  // load data column information is incorrect
H
Haojun Liao 已提交
2061
  for (int32_t i = 0; i < pQueryAttr->numOfCols - 1; ++i) {
H
Haojun Liao 已提交
2062
    if (pQueryAttr->tableCols[i].colId == pQueryAttr->tableCols[i + 1].colId) {
H
Haojun Liao 已提交
2063
      qError("QInfo:0x%"PRIx64" invalid data load column for query", qId);
2064 2065 2066
      return false;
    }
  }
2067

2068 2069 2070 2071 2072
  return true;
}

// todo ignore the avg/sum/min/max/count/stddev/top/bottom functions, of which
// the scan order is not matter
H
Haojun Liao 已提交
2073 2074 2075
static bool onlyOneQueryType(SQueryAttr *pQueryAttr, int32_t functId, int32_t functIdDst) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
2076

2077 2078 2079 2080
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2081

2082 2083 2084 2085
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2086

2087 2088 2089
  return true;
}

H
Haojun Liao 已提交
2090
static bool onlyFirstQuery(SQueryAttr *pQueryAttr) { return onlyOneQueryType(pQueryAttr, TSDB_FUNC_FIRST, TSDB_FUNC_FIRST_DST); }
2091

H
Haojun Liao 已提交
2092
static bool onlyLastQuery(SQueryAttr *pQueryAttr) { return onlyOneQueryType(pQueryAttr, TSDB_FUNC_LAST, TSDB_FUNC_LAST_DST); }
2093

H
Haojun Liao 已提交
2094
static int32_t updateBlockLoadStatus(SQueryAttr *pQuery, int32_t status) {
H
Haojun Liao 已提交
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
  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;
}

2128
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2129 2130
  SQueryAttr* pQueryAttr = &pQInfo->query;
  size_t t = taosArrayGetSize(pQueryAttr->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2131
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2132
    SArray* p1 = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2133 2134 2135

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

2138 2139 2140 2141
      // 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 已提交
2142 2143 2144 2145
    }
  }
}

2146
static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bool stableQuery) {
H
Haojun Liao 已提交
2147
  SQueryAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
2148

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

2153 2154
  // 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 已提交
2155
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
2156
    qDebug("QInfo:0x%"PRIx64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId, pQueryAttr->order.order, TSDB_ORDER_ASC);
2157

H
Haojun Liao 已提交
2158 2159 2160
    pQueryAttr->order.order = TSDB_ORDER_ASC;
    if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2161
    }
2162

2163 2164
    return;
  }
2165

H
Haojun Liao 已提交
2166 2167 2168 2169
  if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) {
    pQueryAttr->order.order = TSDB_ORDER_ASC;
    if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2170
    }
H
Haojun Liao 已提交
2171

H
Haojun Liao 已提交
2172
    doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
H
Haojun Liao 已提交
2173 2174 2175
    return;
  }

H
Haojun Liao 已提交
2176 2177 2178 2179
  if (pQueryAttr->pointInterpQuery && pQueryAttr->interval.interval == 0) {
    if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
      qDebug(msg, pQInfo, "interp", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2180
    }
2181

H
Haojun Liao 已提交
2182
    pQueryAttr->order.order = TSDB_ORDER_ASC;
2183 2184
    return;
  }
2185

H
Haojun Liao 已提交
2186 2187 2188 2189 2190
  if (pQueryAttr->interval.interval == 0) {
    if (onlyFirstQuery(pQueryAttr)) {
      if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
        qDebug(msg, pQInfo, "only-first", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey,
               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2191

H
Haojun Liao 已提交
2192 2193
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2194
      }
2195

H
Haojun Liao 已提交
2196 2197 2198 2199 2200
      pQueryAttr->order.order = TSDB_ORDER_ASC;
    } else if (onlyLastQuery(pQueryAttr)) {
      if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
        qDebug(msg, pQInfo, "only-last", pQueryAttr->order.order, TSDB_ORDER_DESC, pQueryAttr->window.skey,
               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2201

H
Haojun Liao 已提交
2202 2203
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2204
      }
2205

H
Haojun Liao 已提交
2206
      pQueryAttr->order.order = TSDB_ORDER_DESC;
2207
    }
2208

2209
  } else {  // interval query
2210
    if (stableQuery) {
H
Haojun Liao 已提交
2211 2212 2213 2214
      if (onlyFirstQuery(pQueryAttr)) {
        if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
          qDebug(msg, pQInfo, "only-first stable", pQueryAttr->order.order, TSDB_ORDER_ASC,
                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2215

H
Haojun Liao 已提交
2216 2217
          SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
          doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2218
        }
2219

H
Haojun Liao 已提交
2220 2221 2222 2223 2224
        pQueryAttr->order.order = TSDB_ORDER_ASC;
      } else if (onlyLastQuery(pQueryAttr)) {
        if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
          qDebug(msg, pQInfo, "only-last stable", pQueryAttr->order.order, TSDB_ORDER_DESC,
                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
2225

H
Haojun Liao 已提交
2226 2227
          SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
          doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2228
        }
2229

H
Haojun Liao 已提交
2230
        pQueryAttr->order.order = TSDB_ORDER_DESC;
2231 2232 2233 2234 2235
      }
    }
  }
}

2236
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
H
Haojun Liao 已提交
2237
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2238
  int32_t MIN_ROWS_PER_PAGE = 4;
2239

H
Haojun Liao 已提交
2240
  *rowsize = (int32_t)(pQueryAttr->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
2241 2242 2243 2244
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2249 2250
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2251 2252
}

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

H
Haojun Liao 已提交
2255
static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) {
H
Haojun Liao 已提交
2256
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2257

H
Haojun Liao 已提交
2258
  if (pDataStatis == NULL || pQueryAttr->numOfFilterCols == 0) {
2259 2260 2261
    return true;
  }

H
Haojun Liao 已提交
2262 2263
  for (int32_t k = 0; k < pQueryAttr->numOfFilterCols; ++k) {
    SSingleColumnFilterInfo *pFilterInfo = &pQueryAttr->pFilterInfo[k];
2264

H
Haojun Liao 已提交
2265
    int32_t index = -1;
H
Haojun Liao 已提交
2266
    for(int32_t i = 0; i < pQueryAttr->numOfCols; ++i) {
H
Haojun Liao 已提交
2267 2268 2269 2270 2271 2272
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2273
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2274
    if (index == -1) {
H
Haojun Liao 已提交
2275
      return true;
2276
    }
2277

2278
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2279
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2280
      return true;
2281
    }
2282

2283
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2284
    if (pDataStatis[index].numOfNull == numOfRows) {
2285 2286 2287 2288

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2289
        if (pFilterElem->fp == isNullOperator) {
2290 2291 2292 2293
          return true;
        }
      }

2294 2295
      continue;
    }
2296

H
Haojun Liao 已提交
2297 2298 2299
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2303
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2304
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2305 2306 2307 2308 2309
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2310
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2311 2312 2313 2314 2315
          return true;
        }
      }
    }
  }
2316

H
Haojun Liao 已提交
2317
  return false;
2318 2319
}

H
Haojun Liao 已提交
2320
static bool overlapWithTimeWindow(SQueryAttr* pQueryAttr, SDataBlockInfo* pBlockInfo) {
H
Haojun Liao 已提交
2321 2322
  STimeWindow w = {0};

H
Haojun Liao 已提交
2323 2324
  TSKEY sk = MIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
  TSKEY ek = MAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
2325

H
Haojun Liao 已提交
2326 2327
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
2328
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2329

H
Haojun Liao 已提交
2330
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2331 2332 2333 2334
      return true;
    }

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

H
Haojun Liao 已提交
2340 2341
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2342 2343 2344 2345
        return true;
      }
    }
  } else {
H
Haojun Liao 已提交
2346
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2347 2348 2349
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2350 2351 2352 2353
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2354
      getNextTimeWindow(pQueryAttr, &w);
H
Haojun Liao 已提交
2355 2356 2357 2358
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

H
Haojun Liao 已提交
2359 2360
      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2361 2362 2363 2364 2365 2366 2367 2368
        return true;
      }
    }
  }

  return false;
}

H
Haojun Liao 已提交
2369 2370 2371 2372 2373
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",
H
Haojun Liao 已提交
2374
         elem.ts, key, elem.tag.i64, pQueryAttr->order.order, pRuntimeEnv->pTsBuf->tsOrder,
H
Haojun Liao 已提交
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
         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;
}
2394

H
Haojun Liao 已提交
2395
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
2396
                           SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2397 2398 2399 2400 2401
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2402
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
    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 已提交
2423 2424

    // save the cursor status
H
Haojun Liao 已提交
2425
    pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
2426 2427 2428
  } else {
    for (int32_t i = 0; i < numOfRows; ++i) {
      bool qualified = false;
H
Haojun Liao 已提交
2429

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

H
Haojun Liao 已提交
2433 2434 2435
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2436

H
Haojun Liao 已提交
2437 2438 2439 2440 2441 2442 2443 2444
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2445
          } else {
H
Haojun Liao 已提交
2446 2447 2448 2449 2450 2451
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2452
          }
H
Haojun Liao 已提交
2453 2454

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2455 2456 2457 2458 2459
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2460
        if (!qualified) {
H
Haojun Liao 已提交
2461 2462 2463 2464
          break;
        }
      }

H
Haojun Liao 已提交
2465
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2466
      if (!qualified) {
H
Haojun Liao 已提交
2467
        all = false;
H
Haojun Liao 已提交
2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
      }
    }
  }

  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 已提交
2485
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2486 2487 2488
          }

          start += len;
2489
          len = 0;
H
Haojun Liao 已提交
2490 2491 2492 2493
        }
      }
    }

2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
    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 已提交
2507 2508 2509 2510
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

    if (start > 0) {
H
Haojun Liao 已提交
2511
      SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
2512 2513 2514 2515 2516
      if (pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP &&
             pColumnInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
        pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
        pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
      }
H
Haojun Liao 已提交
2517 2518 2519 2520 2521 2522
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2523 2524 2525
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 已提交
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544
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;
}

2545 2546
static void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock) {
  if (numOfFilterCols > 0 && pFilterInfo[0].pData != NULL) {
H
Haojun Liao 已提交
2547 2548 2549 2550
    return;
  }

  // set the initial static data value filter expression
2551
  for (int32_t i = 0; i < numOfFilterCols; ++i) {
H
Haojun Liao 已提交
2552 2553 2554
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j);

2555 2556
      if (pFilterInfo[i].info.colId == pColInfo->info.colId) {
        pFilterInfo[i].pData = pColInfo->pData;
H
Haojun Liao 已提交
2557 2558 2559 2560 2561 2562
        break;
      }
    }
  }
}

H
Haojun Liao 已提交
2563 2564
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2565
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2566
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2567
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2568

H
Haojun Liao 已提交
2569
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2570
  int64_t groupId = pRuntimeEnv->current->groupIndex;
H
Haojun Liao 已提交
2571
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
2572

H
Haojun Liao 已提交
2573
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2574 2575
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2576
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2577
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2578

H
Haojun Liao 已提交
2579
    if (pQueryAttr->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2580
      SExprInfo*   pExprInfo = &pTableScanInfo->pExpr[0];
H
Haojun Liao 已提交
2581
      int16_t      tagId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
2582
      SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagId);
H
Haojun Liao 已提交
2583 2584 2585

      // compare tag first
      tVariant t = {0};
H
Haojun Liao 已提交
2586 2587
      doSetTagValueInParam(pRuntimeEnv->current->pTable, tagId, &t, pColInfo->type, pColInfo->bytes);
      setTimestampListJoinInfo(pRuntimeEnv, &t, pRuntimeEnv->current);
H
Haojun Liao 已提交
2588 2589 2590 2591 2592 2593

      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 已提交
2594 2595 2596
    }
  }

H
Haojun Liao 已提交
2597 2598
  // Calculate all time windows that are overlapping or contain current data block.
  // If current data block is contained by all possible time window, do not load current data block.
H
Haojun Liao 已提交
2599 2600
  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 ||
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) {
H
Haojun Liao 已提交
2601 2602
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2603

H
Haojun Liao 已提交
2604 2605 2606 2607
  // 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
H
Haojun Liao 已提交
2608
    if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2609
      SResultRow* pResult = NULL;
H
Haojun Liao 已提交
2610

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

H
Haojun Liao 已提交
2614
      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2615 2616 2617 2618
      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 已提交
2619
      }
H
Haojun Liao 已提交
2620
    } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
2621 2622
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
H
Haojun Liao 已提交
2623
                               pRuntimeEnv->current->groupIndex);
H
Haojun Liao 已提交
2624
    }
H
Haojun Liao 已提交
2625 2626

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

H
Haojun Liao 已提交
2629
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2630
  *status = updateBlockLoadStatus(pRuntimeEnv->pQueryAttr, *status);
H
Haojun Liao 已提交
2631

2632
  if ((*status) == BLK_DATA_NO_NEEDED || (*status) == BLK_DATA_DISCARD) {
H
Haojun Liao 已提交
2633
    qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2634
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2635 2636 2637 2638
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2639
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2640

H
Haojun Liao 已提交
2641
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2642
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2643
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2644 2645 2646 2647 2648 2649
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2652
    if (pQueryAttr->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2653
      { // set previous window
H
Haojun Liao 已提交
2654
        if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2655 2656 2657 2658 2659
          SResultRow* pResult = NULL;

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

H
Haojun Liao 已提交
2660
          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2661 2662 2663 2664 2665 2666 2667
          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 已提交
2668
      bool load = false;
H
Haojun Liao 已提交
2669
      for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
H
Haojun Liao 已提交
2670
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2671
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2672 2673
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2674
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2675
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2676
            qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2677
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2678 2679 2680 2681 2682 2683 2684 2685
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2686
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2687
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2688
      qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2689
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2690
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2691
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2692 2693 2694 2695
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2696
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2697
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2698 2699
      return terrno;
    }
H
Haojun Liao 已提交
2700

2701
    doSetFilterColumnInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock);
H
Haojun Liao 已提交
2702 2703
    if (pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
      filterRowsInDataBlock(pRuntimeEnv, pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2704
    }
H
Haojun Liao 已提交
2705 2706 2707 2708 2709
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2710
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2711
  int32_t midPos = -1;
H
Haojun Liao 已提交
2712
  int32_t numOfRows;
2713

2714 2715 2716
  if (num <= 0) {
    return -1;
  }
2717

2718
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2719 2720

  TSKEY * keyList = (TSKEY *)pValue;
2721
  int32_t firstPos = 0;
2722
  int32_t lastPos = num - 1;
2723

2724
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2725 2726 2727 2728 2729
    // 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;
2730

H
Haojun Liao 已提交
2731 2732
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2733

H
hjxilinx 已提交
2734 2735 2736 2737 2738 2739 2740 2741
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2742

H
hjxilinx 已提交
2743 2744 2745 2746 2747
  } 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;
2748

H
hjxilinx 已提交
2749 2750 2751 2752 2753 2754 2755
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2756

H
Haojun Liao 已提交
2757
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2758
      midPos = (numOfRows >> 1u) + firstPos;
2759

H
hjxilinx 已提交
2760 2761 2762 2763 2764 2765 2766 2767 2768
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2769

H
hjxilinx 已提交
2770 2771 2772
  return midPos;
}

H
Haojun Liao 已提交
2773 2774 2775 2776 2777 2778
/*
 * 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);
2779

H
Haojun Liao 已提交
2780
  char* val = NULL;
H
Haojun Liao 已提交
2781
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2782
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2783 2784
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2785 2786
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2787

H
Haojun Liao 已提交
2788 2789 2790 2791
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2792

H
Haojun Liao 已提交
2793
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2794 2795 2796 2797
    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 已提交
2798 2799
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2800
  }
2801 2802
}

2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814
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 已提交
2815
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2816
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2817

H
Haojun Liao 已提交
2818 2819
  SExprInfo  *pExpr      = pOperatorInfo->pExpr;
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2820 2821

  SExprInfo* pExprInfo = &pExpr[0];
H
Haojun Liao 已提交
2822
  if (pQueryAttr->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP && pQueryAttr->stableQuery) {
H
Haojun Liao 已提交
2823 2824
    assert(pExprInfo->base.numOfParams == 1);

H
Haojun Liao 已提交
2825
    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
2826
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);
H
Haojun Liao 已提交
2827

2828
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2829
    return;
H
Haojun Liao 已提交
2830 2831 2832
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
H
Haojun Liao 已提交
2833
    memset(pRuntimeEnv->tagVal, 0, pQueryAttr->tagLen);
H
Haojun Liao 已提交
2834

H
Haojun Liao 已提交
2835 2836 2837 2838 2839 2840 2841 2842 2843
    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 已提交
2844 2845
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resType,
                           pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2846

H
Haojun Liao 已提交
2847 2848
      if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resType) || pLocalExprInfo->base.resType == TSDB_DATA_TYPE_BOOL) {
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2849
      } else {
2850
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2851 2852
      }

H
Haojun Liao 已提交
2853
      offset += pLocalExprInfo->base.resBytes;
H
Haojun Liao 已提交
2854 2855
    }

H
Haojun Liao 已提交
2856
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2857
    if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2858
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2859
    }
H
Haojun Liao 已提交
2860
  }
H
Haojun Liao 已提交
2861

H
Haojun Liao 已提交
2862 2863 2864
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2865 2866
  }
}
2867

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

2937
void UNUSED_FUNC displayInterResult(tFilePage **pdata, SQueryRuntimeEnv* pRuntimeEnv, int32_t numOfRows) {
H
Haojun Liao 已提交
2938 2939
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfCols = pQueryAttr->numOfOutput;
2940
  printf("super table query intermediate result, total:%d\n", numOfRows);
2941

2942 2943
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2944

H
Haojun Liao 已提交
2945
      switch (pQueryAttr->pExpr1[i].base.resType) {
2946
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2947 2948
          int32_t type = pQueryAttr->pExpr1[i].base.resType;
          printBinaryData(pQueryAttr->pExpr1[i].base.functionId, pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j,
2949 2950 2951 2952 2953
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2954
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2955 2956
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2957
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2958 2959
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2960
          printf("%f\t", *(float *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2961 2962
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2963
          printf("%lf\t", *(double *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2964 2965 2966 2967 2968 2969 2970
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2971
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2972
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2973
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2974 2975

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2976
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2977 2978 2979
    // 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 已提交
2980
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2981 2982 2983 2984
        return;
      }
    }

H
Haojun Liao 已提交
2985
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2986 2987

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2988
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2989 2990
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2991
        break;
H
Haojun Liao 已提交
2992 2993 2994
      }
    }

H
Haojun Liao 已提交
2995 2996 2997 2998
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2999
    }
H
Haojun Liao 已提交
3000

H
Haojun Liao 已提交
3001 3002
}

H
Haojun Liao 已提交
3003
static void updateTableQueryInfoForReverseScan(SQueryAttr *pQueryAttr, STableQueryInfo *pTableQueryInfo) {
3004 3005 3006
  if (pTableQueryInfo == NULL) {
    return;
  }
3007

3008 3009
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3010

3011 3012
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
3013

H
Haojun Liao 已提交
3014
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
3015
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
3016 3017
}

H
Haojun Liao 已提交
3018
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
3019
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3020

H
Haojun Liao 已提交
3021
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
3022 3023
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3024
    SArray *tableKeyGroup = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
3025

H
Haojun Liao 已提交
3026 3027 3028
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3029
      updateTableQueryInfoForReverseScan(pQueryAttr, pCheckInfo);
H
Haojun Liao 已提交
3030

H
Haojun Liao 已提交
3031 3032 3033 3034
      // 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 已提交
3035

H
Haojun Liao 已提交
3036
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
3037
    }
H
Haojun Liao 已提交
3038 3039
  }
}
H
Haojun Liao 已提交
3040

H
Haojun Liao 已提交
3041 3042 3043
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3044 3045 3046
  }
}

H
Haojun Liao 已提交
3047 3048 3049 3050 3051 3052
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3053

H
Haojun Liao 已提交
3054 3055 3056 3057 3058 3059 3060 3061
/*
 * 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 已提交
3062
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid, int32_t stage) {
H
Haojun Liao 已提交
3063 3064 3065 3066 3067
  SQLFunctionCtx* pCtx           = pInfo->pCtx;
  SSDataBlock* pDataBlock        = pInfo->pRes;
  int32_t* rowCellInfoOffset     = pInfo->rowCellInfoOffset;
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;

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

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

H
Haojun Liao 已提交
3074 3075 3076 3077 3078 3079 3080
    /*
     * 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);

H
Haojun Liao 已提交
3081 3082 3083
    pCtx[i].resultInfo   = pCellInfo;
    pCtx[i].pOutput      = pData->pData;
    pCtx[i].currentStage = stage;
H
Haojun Liao 已提交
3084
    assert(pCtx[i].pOutput != NULL);
3085

H
Haojun Liao 已提交
3086 3087 3088 3089 3090
    // 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;
    }
3091
  }
3092

H
Haojun Liao 已提交
3093
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3094
}
3095

H
Haojun Liao 已提交
3096
void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOfInputRows) {
H
Haojun Liao 已提交
3097
  SSDataBlock* pDataBlock = pBInfo->pRes;
3098

H
Haojun Liao 已提交
3099
  int32_t newSize = pDataBlock->info.rows + numOfInputRows + 5; // extra output buffer
H
Haojun Liao 已提交
3100
  if ((*bufCapacity) < newSize) {
H
Haojun Liao 已提交
3101 3102
    for(int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
H
Haojun Liao 已提交
3103

H
Haojun Liao 已提交
3104 3105 3106
      char* p = realloc(pColInfo->pData, newSize * pColInfo->info.bytes);
      if (p != NULL) {
        pColInfo->pData = p;
3107

H
Haojun Liao 已提交
3108 3109
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
H
Haojun Liao 已提交
3110
        (*bufCapacity) = newSize;
H
Haojun Liao 已提交
3111 3112
      } else {
        // longjmp
3113 3114
      }
    }
H
Haojun Liao 已提交
3115
  }
3116

H
Haojun Liao 已提交
3117 3118 3119
  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;
3120

H
Haojun Liao 已提交
3121 3122 3123 3124
    // 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 已提交
3125
    }
H
Haojun Liao 已提交
3126 3127
  }
}
3128

H
Haojun Liao 已提交
3129
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3130 3131 3132 3133
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3134 3135
    }

H
Haojun Liao 已提交
3136
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3137
  }
H
Haojun Liao 已提交
3138
}
3139

H
Haojun Liao 已提交
3140
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3141
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3142
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3143 3144
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3145 3146
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3147 3148
  }
}
3149

H
Haojun Liao 已提交
3150
static void setupEnvForReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
3151
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3152

H
Haojun Liao 已提交
3153 3154 3155 3156
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3157
  }
3158

H
Haojun Liao 已提交
3159
  // reverse order time range
H
Haojun Liao 已提交
3160
  SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
3161 3162

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3163
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3164

H
Haojun Liao 已提交
3165
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3166
  SWITCH_ORDER(pQueryAttr->order.order);
H
Haojun Liao 已提交
3167 3168

  setupQueryRangeForReverseScan(pRuntimeEnv);
3169 3170
}

H
Haojun Liao 已提交
3171
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3172
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3173
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3174 3175

  int32_t numOfOutput = pOperator->numOfOutput;
H
Haojun Liao 已提交
3176
  if (pQueryAttr->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQueryAttr) || pQueryAttr->sw.gap > 0) {
H
Haojun Liao 已提交
3177
    // for each group result, call the finalize function for each column
H
Haojun Liao 已提交
3178
    if (pQueryAttr->groupbyColumn) {
H
Haojun Liao 已提交
3179 3180 3181 3182 3183 3184 3185 3186 3187
      closeAllResultRows(pResultRowInfo);
    }

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

H
Haojun Liao 已提交
3188
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3189 3190 3191 3192 3193 3194 3195 3196 3197

      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 已提交
3198
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3199 3200 3201 3202 3203 3204 3205 3206 3207
    }

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

H
Haojun Liao 已提交
3208 3209 3210
static bool hasMainOutput(SQueryAttr *pQueryAttr) {
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
3211

3212 3213 3214 3215
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3216

3217 3218 3219
  return false;
}

H
Haojun Liao 已提交
3220
STableQueryInfo *createTableQueryInfo(SQueryAttr* pQueryAttr, void* pTable, bool groupbyColumn, STimeWindow win, void* buf) {
H
Haojun Liao 已提交
3221
  STableQueryInfo *pTableQueryInfo = buf;
3222

H
hjxilinx 已提交
3223 3224
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3225

3226
  pTableQueryInfo->pTable = pTable;
3227
  pTableQueryInfo->cur.vgroupIndex = -1;
3228

H
Haojun Liao 已提交
3229
  // set more initial size of interval/groupby query
H
Haojun Liao 已提交
3230
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr) || groupbyColumn) {
H
Haojun Liao 已提交
3231
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3232
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3233 3234 3235
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3236
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3237 3238
  }

3239 3240 3241
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3242
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3243 3244 3245
  if (pTableQueryInfo == NULL) {
    return;
  }
3246

H
Haojun Liao 已提交
3247
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3248
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3249 3250
}

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

H
Haojun Liao 已提交
3256
  int16_t offset = 0;
3257
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3258
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3259 3260 3261

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3262
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3263 3264
      continue;
    }
3265

H
Haojun Liao 已提交
3266
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQueryAttr, bufPage, pResult->offset, offset);
H
Haojun Liao 已提交
3267
    offset += pCtx[i].outputBytes;
3268

3269
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3270
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3271
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3272
    }
3273

3274
    if (!pResInfo->initialized) {
3275
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3276 3277 3278 3279
    }
  }
}

3280 3281
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3282
  int64_t uid = 0;
H
Haojun Liao 已提交
3283
  SResultRow* pResultRow =
3284
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3285
  assert (pResultRow != NULL);
3286

3287 3288 3289 3290 3291
  /*
   * not assign result buffer yet, add new result buffer
   * all group belong to one result set, and each group result has different group id so set the id to be one
   */
  if (pResultRow->pageId == -1) {
H
Haojun Liao 已提交
3292
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
3293
    if (ret != TSDB_CODE_SUCCESS) {
3294
      return;
3295 3296 3297
    }
  }

3298 3299 3300 3301 3302
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
}

void setExecutionContext(SQueryRuntimeEnv* pRuntimeEnv, SOptrBasicInfo* pInfo, int32_t numOfOutput, int32_t groupIndex,
                         TSKEY nextKey) {
H
Haojun Liao 已提交
3303
  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3304 3305 3306 3307 3308 3309 3310 3311 3312

  // 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);

3313 3314
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3315 3316
}

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

H
Haojun Liao 已提交
3322
  int16_t offset = 0;
3323
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3324
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQueryAttr, page, pResult->offset, offset);
H
Haojun Liao 已提交
3325
    offset += pCtx[i].outputBytes;
3326

3327 3328 3329
    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;
3330 3331
    }

3332 3333 3334 3335
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3336
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3337 3338 3339
  }
}

H
Haojun Liao 已提交
3340
void setCtxTagForJoin(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, SExprInfo* pExprInfo, void* pTable) {
H
Haojun Liao 已提交
3341
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
3342

H
Haojun Liao 已提交
3343
  SSqlExpr* pExpr = &pExprInfo->base;
H
Haojun Liao 已提交
3344
  if (pQueryAttr->stableQuery && (pRuntimeEnv->pTsBuf != NULL) &&
H
Haojun Liao 已提交
3345 3346 3347
      (pExpr->functionId == TSDB_FUNC_TS || pExpr->functionId == TSDB_FUNC_PRJ) &&
      (pExpr->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
    assert(pExpr->numOfParams == 1);
H
Haojun Liao 已提交
3348

H
Haojun Liao 已提交
3349
    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
3350
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);
H
Haojun Liao 已提交
3351 3352 3353 3354 3355

    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 已提交
3356
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%s", GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3357
             pExprInfo->base.param[0].i64, pCtx[0].tag.pz);
H
Haojun Liao 已提交
3358
    } else {
H
Haojun Liao 已提交
3359
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3360
             pExprInfo->base.param[0].i64, pCtx[0].tag.i64);
H
Haojun Liao 已提交
3361 3362 3363 3364 3365
    }
  }
}

int32_t setTimestampListJoinInfo(SQueryRuntimeEnv* pRuntimeEnv, tVariant* pTag, STableQueryInfo *pTableQueryInfo) {
H
Haojun Liao 已提交
3366
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3367

H
Haojun Liao 已提交
3368 3369 3370 3371 3372 3373
  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);

H
Haojun Liao 已提交
3374
    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQueryAttr->vgId, &pTableQueryInfo->tag);
H
Haojun Liao 已提交
3375 3376 3377 3378

    // 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 已提交
3379
        qError("QInfo:0x%"PRIx64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3380
      } else {
H
Haojun Liao 已提交
3381
        qError("QInfo:0x%"PRIx64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3382 3383 3384 3385 3386 3387 3388 3389
      }

      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 已提交
3390
      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 已提交
3391
    } else {
H
Haojun Liao 已提交
3392
      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 已提交
3393 3394 3395 3396 3397
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3398
      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 已提交
3399
    } else {
H
Haojun Liao 已提交
3400
      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 已提交
3401
    }
H
Haojun Liao 已提交
3402 3403
  }

H
Haojun Liao 已提交
3404 3405 3406
  return 0;
}

H
Haojun Liao 已提交
3407
void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExprInfo) {
H
Haojun Liao 已提交
3408
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3409

H
Haojun Liao 已提交
3410
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3411
  for(int32_t i = 0; i < numOfExprs; ++i) {
H
Haojun Liao 已提交
3412
    SExprInfo* pExprInfo1 = &(pExprInfo[i]);
H
Haojun Liao 已提交
3413
    if (pExprInfo1->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3414 3415 3416
      continue;
    }

H
Haojun Liao 已提交
3417
    SSqlExpr* pExpr = &pExprInfo1->base;
H
Haojun Liao 已提交
3418 3419

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3423 3424 3425
    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 已提交
3426
      if (pQueryAttr->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQueryAttr->tagLen) == 0) {
H
Haojun Liao 已提交
3427 3428
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3429
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
H
Haojun Liao 已提交
3430
          if (pres->colId == pExpr->colInfo.colId) {
H
Haojun Liao 已提交
3431 3432 3433 3434 3435 3436 3437 3438 3439
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3440

H
Haojun Liao 已提交
3441
void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes) {
H
Haojun Liao 已提交
3442
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3443

H
Haojun Liao 已提交
3444
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470
  for(int32_t i = 0; i < numOfExprs; ++i) {
    SSqlExpr* pExpr1 = &pExpr[i].base;
    if (pExpr1->functionId != TSDB_FUNC_STDDEV_DST) {
      continue;
    }

    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 == pExpr1->colInfo.colId) {
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }
}
D
fix bug  
dapan1121 已提交
3471

3472 3473 3474
/*
 * There are two cases to handle:
 *
H
Haojun Liao 已提交
3475 3476
 * 1. Query range is not set yet (queryRangeSet = 0). we need to set the query range info, including pQueryAttr->lastKey,
 *    pQueryAttr->window.skey, and pQueryAttr->eKey.
3477 3478 3479 3480
 * 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 已提交
3481
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3482
  SQueryAttr           *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3483
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
3484
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3485

H
Haojun Liao 已提交
3486 3487 3488
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3489

H
Haojun Liao 已提交
3490
  pTableQueryInfo->win.skey = key;
H
Haojun Liao 已提交
3491
  STimeWindow win = {.skey = key, .ekey = pQueryAttr->window.ekey};
3492

H
Haojun Liao 已提交
3493 3494 3495 3496 3497 3498
  /**
   * 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 已提交
3499
  STimeWindow w = TSWINDOW_INITIALIZER;
3500

H
Haojun Liao 已提交
3501 3502
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
H
Haojun Liao 已提交
3503
  getAlignQueryTimeWindow(pQueryAttr, win.skey, sk, ek, &w);
3504

H
Haojun Liao 已提交
3505
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3506 3507
    if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
      assert(win.ekey == pQueryAttr->window.ekey);
3508
    }
H
Haojun Liao 已提交
3509

H
Haojun Liao 已提交
3510
    pWindowResInfo->prevSKey = w.skey;
3511
  }
H
Haojun Liao 已提交
3512 3513

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3514 3515 3516
}

/**
H
Haojun Liao 已提交
3517
 * copyToOutputBuf support copy data in ascending/descending order
3518 3519 3520 3521 3522 3523 3524
 * 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 已提交
3525

H
Haojun Liao 已提交
3526
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3527
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3528 3529

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3530
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3531 3532 3533 3534

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3535
  qDebug("QInfo:0x%"PRIx64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
  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 已提交
3556 3557

    int16_t offset = 0;
H
Haojun Liao 已提交
3558 3559 3560 3561 3562
    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, j);
      int32_t bytes = pColInfoData->info.bytes;

      char *out = pColInfoData->pData + numOfResult * bytes;
H
Haojun Liao 已提交
3563
      char *in  = getPosInResultPage(pQueryAttr, page, pRow->offset, offset);
H
Haojun Liao 已提交
3564
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3565 3566

      offset += bytes;
H
Haojun Liao 已提交
3567 3568 3569
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3570
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3571 3572 3573 3574
      break;
    }
  }

H
Haojun Liao 已提交
3575
  qDebug("QInfo:0x%"PRIx64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3576 3577 3578 3579 3580 3581
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3583
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3584
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3585 3586 3587
    return;
  }

H
Haojun Liao 已提交
3588 3589
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t orderType = (pQueryAttr->pGroupbyExpr != NULL) ? pQueryAttr->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3590
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3591

H
Haojun Liao 已提交
3592
  // refactor : extract method
H
Haojun Liao 已提交
3593 3594
  SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0);

H
Haojun Liao 已提交
3595 3596 3597
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3598
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3599
  }
3600 3601
}

H
Haojun Liao 已提交
3602 3603 3604
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput,
                                        SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
3605

3606
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3607
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3608 3609
    return;
  }
3610

3611 3612
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3613

3614 3615
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3616 3617
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3618
      }
H
Haojun Liao 已提交
3619

H
Haojun Liao 已提交
3620
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3621
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3622 3623 3624 3625 3626
    }
  }
}

static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) {
H
Haojun Liao 已提交
3627
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3628
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3629

H
Haojun Liao 已提交
3630
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3631

H
Haojun Liao 已提交
3632 3633
  if (pQueryAttr->pExpr2 == NULL) {
    for (int32_t col = 0; col < pQueryAttr->numOfOutput; ++col) {
H
Haojun Liao 已提交
3634 3635 3636
      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 已提交
3637 3638
    }
  } else {
H
Haojun Liao 已提交
3639
    for (int32_t col = 0; col < pQueryAttr->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3640 3641 3642
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3643
    }
3644
  }
3645

H
Haojun Liao 已提交
3646
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3647 3648
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3649

3650
  int32_t total = 0;
H
Haojun Liao 已提交
3651
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3652

3653
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3654
    STableIdInfo* pDst = (STableIdInfo*)data;
3655 3656 3657 3658
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3659
    data += sizeof(STableIdInfo);
3660 3661
    total++;

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

H
Haojun Liao 已提交
3666
  qDebug("QInfo:0x%"PRIx64" set %d subscribe info", pQInfo->qId, total);
H
Haojun Liao 已提交
3667
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3668 3669
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3670
  }
3671 3672
}

H
Haojun Liao 已提交
3673
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3674 3675 3676 3677 3678 3679
  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 已提交
3680
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3681
  tfree(p);
H
Haojun Liao 已提交
3682 3683
  return pOutput->info.rows;
}
3684

H
Haojun Liao 已提交
3685
void queryCostStatis(SQInfo *pQInfo) {
3686
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3687
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3688

H
Haojun Liao 已提交
3689
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3690
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3691 3692
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3693 3694 3695
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3696
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3697 3698 3699 3700 3701 3702 3703
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3704

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

H
Haojun Liao 已提交
3710
  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 已提交
3711
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3712 3713
}

3714
//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
H
Haojun Liao 已提交
3715
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3716
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3717
//
H
Haojun Liao 已提交
3718
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3719
//
H
Haojun Liao 已提交
3720 3721 3722
//  if (pQueryAttr->limit.offset == pBlockInfo->rows) {  // current block will ignore completed
//    pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQueryAttr) ? pBlockInfo->window.ekey + step : pBlockInfo->window.skey + step;
//    pQueryAttr->limit.offset = 0;
3723 3724 3725
//    return;
//  }
//
H
Haojun Liao 已提交
3726 3727
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//    pQueryAttr->pos = (int32_t)pQueryAttr->limit.offset;
3728
//  } else {
H
Haojun Liao 已提交
3729
//    pQueryAttr->pos = pBlockInfo->rows - (int32_t)pQueryAttr->limit.offset - 1;
3730 3731
//  }
//
H
Haojun Liao 已提交
3732
//  assert(pQueryAttr->pos >= 0 && pQueryAttr->pos <= pBlockInfo->rows - 1);
3733 3734 3735 3736
//
//  SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//  SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
H
Haojun Liao 已提交
3737
//  // update the pQueryAttr->limit.offset value, and pQueryAttr->pos value
3738 3739 3740
//  TSKEY *keys = (TSKEY *) pColInfoData->pData;
//
//  // update the offset value
H
Haojun Liao 已提交
3741 3742
//  pTableQueryInfo->lastKey = keys[pQueryAttr->pos];
//  pQueryAttr->limit.offset = 0;
3743 3744 3745
//
//  int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//
H
Haojun Liao 已提交
3746
//  qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
3747 3748
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3749

3750
//void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
H
Haojun Liao 已提交
3751
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3752
//
H
Haojun Liao 已提交
3753
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0) {
3754 3755 3756
//    return;
//  }
//
H
Haojun Liao 已提交
3757 3758
//  pQueryAttr->pos = 0;
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3759
//
H
Haojun Liao 已提交
3760
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3761 3762 3763 3764
//  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pQueryHandle)) {
H
Haojun Liao 已提交
3765
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3766 3767 3768 3769 3770
//      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//    }
//
//    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3771 3772 3773
//    if (pQueryAttr->limit.offset > blockInfo.rows) {
//      pQueryAttr->limit.offset -= blockInfo.rows;
//      pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? blockInfo.window.ekey : blockInfo.window.skey;
3774 3775
//      pTableQueryInfo->lastKey += step;
//
H
Haojun Liao 已提交
3776
//      qDebug("QInfo:0x%"PRIx64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787
//             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 已提交
3788

3789
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
H
Haojun Liao 已提交
3790
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3791 3792
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
H
Haojun Liao 已提交
3793
//  assert(pQueryAttr->limit.offset == 0);
3794
//  STimeWindow tw = *win;
H
Haojun Liao 已提交
3795
//  getNextTimeWindow(pQueryAttr, &tw);
3796
//
H
Haojun Liao 已提交
3797 3798
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
3799 3800 3801 3802 3803 3804 3805 3806
//
//    // 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 =
H
Haojun Liao 已提交
3807
//        getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
3808 3809 3810
//    assert(startPos >= 0);
//
//    // set the abort info
H
Haojun Liao 已提交
3811
//    pQueryAttr->pos = startPos;
3812 3813 3814
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
H
Haojun Liao 已提交
3815
//    pQueryAttr->window.skey = pTableQueryInfo->win.skey;
3816 3817 3818 3819 3820 3821 3822 3823
//    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 已提交
3824
//    qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
H
Haojun Liao 已提交
3825
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
H
Haojun Liao 已提交
3826
//           pQueryAttr->current->lastKey);
3827 3828 3829
//
//    return key;
//  } else {  // do nothing
H
Haojun Liao 已提交
3830
//    pQueryAttr->window.skey      = tw.skey;
3831 3832 3833 3834 3835 3836 3837 3838 3839 3840
//    pWindowResInfo->prevSKey = tw.skey;
//    pTableQueryInfo->lastKey = tw.skey;
//
//    return tw.skey;
//  }
//
//  return true;
//}

//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
H
Haojun Liao 已提交
3841 3842
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3843
//    assert(*start <= pRuntimeEnv->current->lastKey);
3844
//  } else {
H
Haojun Liao 已提交
3845
//    assert(*start >= pRuntimeEnv->current->lastKey);
3846 3847 3848
//  }
//
//  // if queried with value filter, do NOT forward query start position
H
Haojun Liao 已提交
3849
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
3850 3851 3852 3853
//    return true;
//  }
//
//  /*
H
Haojun Liao 已提交
3854 3855 3856
//   * 1. for interval without interpolation query we forward pQueryAttr->interval.interval at a time for
//   *    pQueryAttr->limit.offset times. Since hole exists, pQueryAttr->interval.interval*pQueryAttr->limit.offset value is
//   *    not valid. otherwise, we only forward pQueryAttr->limit.offset number of points
3857 3858 3859 3860
//   */
//  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
//
//  STimeWindow w = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3861
//  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
3862 3863
//
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
3864
//  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3865 3866 3867 3868 3869
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
//    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3870
//    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
3871
//      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3872
//        getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey, &w);
3873 3874 3875
//        pWindowResInfo->prevSKey = w.skey;
//      }
//    } else {
H
Haojun Liao 已提交
3876
//      getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w);
3877 3878 3879 3880
//      pWindowResInfo->prevSKey = w.skey;
//    }
//
//    // the first time window
H
Haojun Liao 已提交
3881
//    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
3882
//
H
Haojun Liao 已提交
3883
//    while (pQueryAttr->limit.offset > 0) {
3884 3885 3886
//      STimeWindow tw = win;
//
//      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
3887
//        pQueryAttr->limit.offset -= 1;
3888 3889 3890 3891 3892 3893 3894 3895 3896
//        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;
//        }
//      }
//
H
Haojun Liao 已提交
3897
//      if (pQueryAttr->limit.offset == 0) {
3898 3899 3900 3901 3902
//        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//        return true;
//      }
//
//      // current window does not ended in current data block, try next data block
H
Haojun Liao 已提交
3903
//      getNextTimeWindow(pQueryAttr, &tw);
3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917
//
//      /*
//       * 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)) {
H
Haojun Liao 已提交
3918
//          pQueryAttr->limit.offset -= 1;
3919 3920
//        }
//
H
Haojun Liao 已提交
3921
//        if (pQueryAttr->limit.offset == 0) {
3922 3923 3924 3925 3926
//          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//          return true;
//        } else {
//          tw = win;
//          int32_t startPos =
H
Haojun Liao 已提交
3927
//              getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
3928 3929 3930
//          assert(startPos >= 0);
//
//          // set the abort info
H
Haojun Liao 已提交
3931
//          pQueryAttr->pos = startPos;
3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948
//          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;
//}
3949

H
Haojun Liao 已提交
3950 3951
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

H
Haojun Liao 已提交
3952 3953
static int32_t setupQueryHandle(void* tsdb, SQueryRuntimeEnv* pRuntimeEnv, int64_t qId, bool isSTableQuery) {
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3954

H
Haojun Liao 已提交
3955
  // TODO set the tags scan handle
H
Haojun Liao 已提交
3956
  if (onlyQueryTags(pQueryAttr)) {
B
Bomin Zhang 已提交
3957
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3958 3959
  }

H
Haojun Liao 已提交
3960 3961
  STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
  if (pQueryAttr->tsCompQuery || pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
3962 3963
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3964

B
Bomin Zhang 已提交
3965
  if (!isSTableQuery
H
Haojun Liao 已提交
3966
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3967
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3968 3969 3970
    && (!QUERY_IS_INTERVAL_QUERY(pQueryAttr))
    && (!pQueryAttr->groupbyColumn)
    && (!pQueryAttr->simpleAgg)
B
Bomin Zhang 已提交
3971
  ) {
H
Haojun Liao 已提交
3972
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3973 3974
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3975
  }
B
Bomin Zhang 已提交
3976

B
Bomin Zhang 已提交
3977
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3978
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
3979
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3980

H
Haojun Liao 已提交
3981
    // update the query time window
H
Haojun Liao 已提交
3982 3983
    pQueryAttr->window = cond.twindow;
    if (pQueryAttr->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3984
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3985
    } else {
H
Haojun Liao 已提交
3986
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3987
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3988
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3989

H
Haojun Liao 已提交
3990 3991 3992
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3993

H
Haojun Liao 已提交
3994
          pCheckInfo->win = pQueryAttr->window;
H
Haojun Liao 已提交
3995 3996
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
3997 3998
      }
    }
D
init  
dapan1121 已提交
3999 4000
  } else if (isCachedLastQuery(pQueryAttr)) {
    pRuntimeEnv->pQueryHandle = tsdbQueryCacheLast(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
4001
  } else if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
4002
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
4003
  } else {
H
Haojun Liao 已提交
4004
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
4005
  }
4006

B
Bomin Zhang 已提交
4007
  return terrno;
B
Bomin Zhang 已提交
4008 4009
}

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

H
Haojun Liao 已提交
4013
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
4014 4015 4016 4017
  if (pFillCol == NULL) {
    return NULL;
  }

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

H
Haojun Liao 已提交
4021
    pFillCol[i].col.bytes  = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
4022
    pFillCol[i].col.type   = (int8_t)pExprInfo->base.resType;
4023
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
4024
    pFillCol[i].col.colId  = pExprInfo->base.resColId;
H
Haojun Liao 已提交
4025
    pFillCol[i].tagIndex   = -2;
H
Haojun Liao 已提交
4026
    pFillCol[i].flag       = pExprInfo->base.colInfo.flag;    // always be the normal column for table query
4027
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
4028
    pFillCol[i].fillVal.i  = fillVal[i];
4029

H
Haojun Liao 已提交
4030
    offset += pExprInfo->base.resBytes;
4031
  }
4032

4033 4034 4035
  return pFillCol;
}

H
Haojun Liao 已提交
4036
int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, SArray* prevResult, void* tsdb, void* sourceOptr, int32_t tbScanner,
H
Haojun Liao 已提交
4037
                    SArray* pOperator, void* param) {
4038 4039
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;

H
Haojun Liao 已提交
4040
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
4041
  pQueryAttr->tsdb = tsdb;
H
Haojun Liao 已提交
4042

4043 4044
  pRuntimeEnv->prevResult = prevResult;

H
Haojun Liao 已提交
4045
  if (tsdb != NULL) {
H
Haojun Liao 已提交
4046
    int32_t code = setupQueryHandle(tsdb, pRuntimeEnv, pQInfo->qId, pQueryAttr->stableQuery);
H
Haojun Liao 已提交
4047 4048 4049
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
B
Bomin Zhang 已提交
4050
  }
4051

H
Haojun Liao 已提交
4052
  pQueryAttr->interBufSize = getOutputInterResultBufSize(pQueryAttr);
H
Haojun Liao 已提交
4053

H
Haojun Liao 已提交
4054
  pRuntimeEnv->groupResInfo.totalGroup = (int32_t) (pQueryAttr->stableQuery? GET_NUM_OF_TABLEGROUP(pRuntimeEnv):0);
4055

H
Haojun Liao 已提交
4056
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
4057
  pRuntimeEnv->pTsBuf = pTsBuf;
4058
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4059
  setResultBufSize(pQueryAttr, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4060

H
Haojun Liao 已提交
4061 4062
  switch(tbScanner) {
    case OP_TableBlockInfoScan: {
H
Haojun Liao 已提交
4063
      pRuntimeEnv->proot = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4064 4065 4066
      break;
    }
    case OP_TableSeqScan: {
H
Haojun Liao 已提交
4067
      pRuntimeEnv->proot = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4068 4069 4070
      break;
    }
    case OP_DataBlocksOptScan: {
H
Haojun Liao 已提交
4071
      pRuntimeEnv->proot = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), 1);
H
Haojun Liao 已提交
4072 4073 4074
      break;
    }
    case OP_TableScan: {
H
Haojun Liao 已提交
4075
      pRuntimeEnv->proot = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr));
H
Haojun Liao 已提交
4076 4077
      break;
    }
H
Haojun Liao 已提交
4078
    default: { // do nothing
H
Haojun Liao 已提交
4079 4080 4081
      break;
    }
  }
H
Haojun Liao 已提交
4082 4083

  if (sourceOptr != NULL) {
H
Haojun Liao 已提交
4084 4085
    assert(pRuntimeEnv->proot == NULL);
    pRuntimeEnv->proot = sourceOptr;
H
Haojun Liao 已提交
4086 4087
  }

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

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

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

H
Haojun Liao 已提交
4102
  // create runtime environment
H
Haojun Liao 已提交
4103
  int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4104
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
4105

H
Haojun Liao 已提交
4106
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQueryAttr->tableGroupInfo.numOfTables, pOperator, param);
H
Haojun Liao 已提交
4107 4108 4109 4110
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

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

H
Haojun Liao 已提交
4115 4116
static void doTableQueryInfoTimeWindowCheck(SQueryAttr* pQueryAttr, STableQueryInfo* pTableQueryInfo) {
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
4117 4118 4119
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey >= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4120
        (pTableQueryInfo->win.skey >= pQueryAttr->window.skey && pTableQueryInfo->win.ekey <= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4121 4122 4123 4124
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey <= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4125
        (pTableQueryInfo->win.skey <= pQueryAttr->window.skey && pTableQueryInfo->win.ekey >= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4126 4127 4128
  }
}

H
Haojun Liao 已提交
4129
STsdbQueryCond createTsdbQueryCond(SQueryAttr* pQueryAttr, STimeWindow* win) {
4130
  STsdbQueryCond cond = {
H
Haojun Liao 已提交
4131
      .colList   = pQueryAttr->tableCols,
H
Haojun Liao 已提交
4132 4133
      .order     = pQueryAttr->order.order,
      .numOfCols = pQueryAttr->numOfCols,
H
Haojun Liao 已提交
4134
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4135
      .loadExternalRows = false,
4136 4137
  };

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

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

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

  return tidInfo;
}

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

H
Haojun Liao 已提交
4157 4158
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4159 4160 4161 4162 4163 4164 4165 4166
  if (idinfo != NULL) {
    assert(idinfo->tid == tidInfo.tid && idinfo->uid == tidInfo.uid);
    idinfo->key = tidInfo.key;
  } else {
    taosHashPut(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo));
  }
}

H
Haojun Liao 已提交
4167 4168 4169 4170
static void doCloseAllTimeWindow(SQueryRuntimeEnv* pRuntimeEnv) {
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  for (int32_t i = 0; i < numOfGroup; ++i) {
    SArray* group = GET_TABLEGROUP(pRuntimeEnv, i);
4171

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

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

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

H
Haojun Liao 已提交
4189 4190
  *newgroup = false;

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

4196
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4197
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4198

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

H
Haojun Liao 已提交
4207
      pRuntimeEnv->current = *pTableQueryInfo;
H
Haojun Liao 已提交
4208
      doTableQueryInfoTimeWindowCheck(pQueryAttr, *pTableQueryInfo);
H
Haojun Liao 已提交
4209 4210
    }

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

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

    return pBlock;
  }
H
Haojun Liao 已提交
4225 4226

  return NULL;
H
Haojun Liao 已提交
4227 4228
}

H
Haojun Liao 已提交
4229
static SSDataBlock* doTableScan(void* param, bool *newgroup) {
H
Haojun Liao 已提交
4230 4231
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4232
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4233
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4234
  SQueryAttr       *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
4235

H
Haojun Liao 已提交
4236
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;
H
Haojun Liao 已提交
4237
  *newgroup = false;
H
Haojun Liao 已提交
4238

H
Haojun Liao 已提交
4239
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4240
    SSDataBlock* p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4241 4242
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4243 4244
    }

H
Haojun Liao 已提交
4245
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
D
fix bug  
dapan1121 已提交
4246
      if (pTableScanInfo->reverseTimes <= 0 || isTsdbCacheLastRow(pTableScanInfo->pQueryHandle)) {
H
Haojun Liao 已提交
4247 4248 4249 4250
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4251
    }
H
Haojun Liao 已提交
4252

H
Haojun Liao 已提交
4253
    // do prepare for the next round table scan operation
H
Haojun Liao 已提交
4254
    STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
H
Haojun Liao 已提交
4255
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4256

H
Haojun Liao 已提交
4257
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4258
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4259

H
Haojun Liao 已提交
4260 4261 4262 4263 4264
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4265 4266 4267 4268
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4269

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

H
Haojun Liao 已提交
4274
  SSDataBlock *p = NULL;
H
Haojun Liao 已提交
4275
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4276
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4277

H
Haojun Liao 已提交
4278
    STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
H
Haojun Liao 已提交
4279
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4280

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

H
Haojun Liao 已提交
4284 4285
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4286 4287
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4288 4289
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4290

H
Haojun Liao 已提交
4291 4292 4293 4294
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4295

H
Haojun Liao 已提交
4296
    p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4297
  }
H
Haojun Liao 已提交
4298

H
Haojun Liao 已提交
4299
  return p;
H
Haojun Liao 已提交
4300 4301
}

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

  STableScanInfo *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4309
  *newgroup = false;
H
Haojun Liao 已提交
4310 4311

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

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

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

H
Haojun Liao 已提交
4322 4323 4324 4325 4326 4327
  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 已提交
4328

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

H
Haojun Liao 已提交
4332
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4333

H
Haojun Liao 已提交
4334
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
H
Haojun Liao 已提交
4335
  pOperator->pRuntimeEnv->current = taosArrayGetP(g, 0);
H
Haojun Liao 已提交
4336 4337 4338

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

H
Haojun Liao 已提交
4341
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4342 4343
  assert(repeatTime > 0);

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

H
Haojun Liao 已提交
4351
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4352
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4353
  pOperator->operatorType = OP_TableScan;
H
Haojun Liao 已提交
4354
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4355 4356
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4357
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4358
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4359
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4360 4361 4362 4363

  return pOperator;
}

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

H
Haojun Liao 已提交
4367 4368 4369
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
H
Haojun Liao 已提交
4370
  pInfo->order            = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4371
  pInfo->current          = 0;
H
Haojun Liao 已提交
4372 4373

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

H
Haojun Liao 已提交
4383 4384 4385
  return pOperator;
}

H
Haojun Liao 已提交
4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404
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;
H
Haojun Liao 已提交
4405
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4406 4407 4408 4409 4410
  pOperator->exec         = doBlockInfoScan;

  return pOperator;
}

H
Haojun Liao 已提交
4411 4412 4413
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4414 4415 4416
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4417
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4418
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4419

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

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

H
Haojun Liao 已提交
4430
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4431
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4432

H
Haojun Liao 已提交
4433 4434 4435
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4436

H
Haojun Liao 已提交
4437
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4438
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4439

4440 4441
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4442 4443
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4444
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4445
    SArithOperatorInfo *pInfo = pDownstream->info;
4446

4447 4448 4449 4450 4451 4452
    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 已提交
4453 4454 4455
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4456 4457 4458
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4459 4460
}

H
Haojun Liao 已提交
4461
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4462 4463 4464 4465
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4466
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4467
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4468
  pInfo->current      = 0;
H
Haojun Liao 已提交
4469
  pInfo->order        = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4470 4471

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

  return pOptr;
H
Haojun Liao 已提交
4480 4481
}

H
Haojun Liao 已提交
4482 4483 4484 4485 4486 4487
SArray* getOrderCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4488 4489
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500
  }

  if (pQuery->interval.interval > 0) {
    if (pOrderColumns == NULL) {
      pOrderColumns = taosArrayInit(1, sizeof(SColIndex));
    }

    SColIndex colIndex = {.colIndex = 0, .colId = 0, .flag = TSDB_COL_NORMAL};
    taosArrayPush(pOrderColumns, &colIndex);
  }

H
Haojun Liao 已提交
4501 4502 4503 4504 4505
  {
    numOfCols = (int32_t) taosArrayGetSize(pOrderColumns);
    for(int32_t i = 0; i < numOfCols; ++i) {
      SColIndex* index = taosArrayGet(pOrderColumns, i);
      for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
4506 4507 4508 4509 4510
        SSqlExpr* pExpr = &pQuery->pExpr1[j].base;
        int32_t functionId = pExpr->functionId;

        if (index->colId == pExpr->colInfo.colId &&
            (functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TS)) {
H
Haojun Liao 已提交
4511
          index->colIndex = j;
4512
          index->colId = pExpr->resColId;
H
Haojun Liao 已提交
4513 4514 4515 4516
        }
      }
    }
  }
4517

H
Haojun Liao 已提交
4518 4519 4520
  return pOrderColumns;
}

H
Haojun Liao 已提交
4521 4522 4523 4524 4525 4526
SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4527 4528
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4529 4530 4531 4532
  }

  for(int32_t i = 0; i < numOfCols; ++i) {
    SColIndex* index = taosArrayGet(pOrderColumns, i);
H
Haojun Liao 已提交
4533 4534

    bool found = false;
H
Haojun Liao 已提交
4535
    for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4536 4537 4538 4539 4540 4541
      SSqlExpr* pExpr = &pQuery->pExpr1[j].base;

      // TSDB_FUNC_TAG_DUMMY function needs to be ignored
      if (index->colId == pExpr->colInfo.colId &&
          ((TSDB_COL_IS_TAG(pExpr->colInfo.flag) && pExpr->functionId == TSDB_FUNC_TAG) ||
           (TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && pExpr->functionId == TSDB_FUNC_PRJ))) {
H
Haojun Liao 已提交
4542
        index->colIndex = j;
H
Haojun Liao 已提交
4543 4544 4545
        index->colId = pExpr->resColId;
        found = true;
        break;
H
Haojun Liao 已提交
4546 4547
      }
    }
H
Haojun Liao 已提交
4548 4549

    assert(found && index->colIndex >= 0 && index->colIndex < pQuery->numOfOutput);
H
Haojun Liao 已提交
4550 4551 4552 4553
  }

  return pOrderColumns;
}
H
Haojun Liao 已提交
4554

4555 4556 4557
static void destroyGlobalAggOperatorInfo(void* param, int32_t numOfOutput) {
  SMultiwayMergeInfo *pInfo = (SMultiwayMergeInfo*) param;
  destroyBasicOperatorInfo(&pInfo->binfo, numOfOutput);
4558 4559 4560 4561 4562

  taosArrayDestroy(pInfo->orderColumnList);
  taosArrayDestroy(pInfo->groupColumnList);
  tfree(pInfo->prevRow);
  tfree(pInfo->currentGroupColData);
4563 4564
}

H
Haojun Liao 已提交
4565 4566 4567 4568 4569 4570
static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) {
  SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param;
  taosArrayDestroy(pInfo->orderColumnList);
  tfree(pInfo->prevRow);
}

H
Haojun Liao 已提交
4571
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream,
H
Haojun Liao 已提交
4572
                                                 SExprInfo* pExpr, int32_t numOfOutput, void* param) {
H
Haojun Liao 已提交
4573 4574
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

4575 4576 4577
  pInfo->resultRowFactor =
      (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery,
                                              false));
H
Haojun Liao 已提交
4578

H
Haojun Liao 已提交
4579 4580
  pRuntimeEnv->scanFlag = MERGE_STAGE;  // TODO init when creating pCtx

H
Haojun Liao 已提交
4581
  pInfo->pMerge = param;
H
Haojun Liao 已提交
4582
  pInfo->bufCapacity = 4096;
4583 4584

  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor);
H
Haojun Liao 已提交
4585 4586
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);

H
Haojun Liao 已提交
4587
  pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4588
  pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4589

H
Haojun Liao 已提交
4590 4591 4592
  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
4593
    len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4594 4595
  }

H
Haojun Liao 已提交
4596
  int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4597
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4598
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4599 4600

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4601 4602
    pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

H
Haojun Liao 已提交
4603 4604
    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
H
Haojun Liao 已提交
4605 4606
  }

H
Haojun Liao 已提交
4607
  numOfCols = (pInfo->groupColumnList != NULL)? (int32_t)taosArrayGetSize(pInfo->groupColumnList):0;
H
Haojun Liao 已提交
4608
  pInfo->currentGroupColData = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4609
  offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4610 4611

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4612
    pInfo->currentGroupColData[i] = (char*)pInfo->currentGroupColData + offset;
H
Haojun Liao 已提交
4613 4614 4615 4616 4617

    SColIndex* index = taosArrayGet(pInfo->groupColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
  }

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

  pInfo->seed = rand();
H
Haojun Liao 已提交
4621
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MERGE_STAGE);
H
Haojun Liao 已提交
4622 4623

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4624
  pOperator->name         = "GlobalAggregate";
H
Haojun Liao 已提交
4625 4626
  pOperator->operatorType = OP_GlobalAggregate;
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4627 4628 4629 4630 4631 4632 4633 4634
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;

  pOperator->exec         = doGlobalAggregate;
4635
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4636 4637 4638
  return pOperator;
}

H
Haojun Liao 已提交
4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652
SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SExprInfo *pExpr, int32_t numOfOutput,
                                              int32_t numOfRows, void *merger, bool groupMix) {
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

  pInfo->pMerge     = merger;
  pInfo->groupMix   = groupMix;
  pInfo->bufCapacity = numOfRows;

  pInfo->orderColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);

  {
    int32_t len = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
4653
      len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4654 4655
    }

H
Haojun Liao 已提交
4656
    int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4657
    pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4658
    int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4659 4660 4661 4662 4663

    for(int32_t i = 0; i < numOfCols; ++i) {
      pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

      SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
4664
      offset += pExpr[index->colIndex].base.colBytes;
H
Haojun Liao 已提交
4665 4666 4667 4668 4669
    }
  }

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "MultiwaySortOperator";
4670
  pOperator->operatorType = OP_MultiwayMergeSort;
H
Haojun Liao 已提交
4671 4672 4673 4674 4675
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4676
  pOperator->exec         = doMultiwayMergeSort;
4677
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4678 4679 4680
  return pOperator;
}

H
Haojun Liao 已提交
4681
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4682 4683 4684
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4685
// this is a blocking operator
H
Haojun Liao 已提交
4686
static SSDataBlock* doAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4687
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4688
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4689 4690
    return NULL;
  }
H
Haojun Liao 已提交
4691

H
Haojun Liao 已提交
4692
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4693 4694
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4695
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4696

H
Haojun Liao 已提交
4697 4698
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
4699

H
Haojun Liao 已提交
4700
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4701

H
Haojun Liao 已提交
4702
  while(1) {
H
Haojun Liao 已提交
4703
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4704 4705 4706 4707
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4708 4709 4710
    if (pRuntimeEnv->current != NULL) {
      setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
4711

H
Haojun Liao 已提交
4712
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4713
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4714 4715 4716
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4717
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4718
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4719
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4720 4721
  }

H
Haojun Liao 已提交
4722
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4723
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4724

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

H
Haojun Liao 已提交
4728
  return pInfo->pRes;
H
Haojun Liao 已提交
4729 4730
}

H
Haojun Liao 已提交
4731
static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4732
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4733
  if (pOperator->status == OP_EXEC_DONE) {
4734 4735
    return NULL;
  }
H
Haojun Liao 已提交
4736

H
Haojun Liao 已提交
4737
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4738 4739
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4740
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4741

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

H
Haojun Liao 已提交
4745 4746
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4747 4748
    }

H
Haojun Liao 已提交
4749
    return pInfo->pRes;
4750
  }
H
Haojun Liao 已提交
4751

H
Haojun Liao 已提交
4752 4753
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
4754 4755 4756 4757

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
4758
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
4759 4760 4761 4762
    if (pBlock == NULL) {
      break;
    }

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

H
Haojun Liao 已提交
4765
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4766
      STableScanInfo* pScanInfo = upstream->info;
4767 4768 4769 4770
      order = getTableScanOrder(pScanInfo);
    }

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

H
Haojun Liao 已提交
4773
    TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
H
Haojun Liao 已提交
4774
    setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pRuntimeEnv->current->groupIndex, key);
H
Haojun Liao 已提交
4775
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
4776
  }
H
Haojun Liao 已提交
4777

H
Haojun Liao 已提交
4778 4779
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4780

H
Haojun Liao 已提交
4781
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4782
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4783

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

H
Haojun Liao 已提交
4786 4787 4788
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes);
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4789 4790
  }

H
Haojun Liao 已提交
4791
  return pInfo->pRes;
4792 4793
}

H
Haojun Liao 已提交
4794
static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
4795 4796
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4797 4798
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4799
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4800

H
Haojun Liao 已提交
4801
  SSDataBlock* pRes = pInfo->pRes;
H
Haojun Liao 已提交
4802
  int32_t order = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4803 4804

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

H
Haojun Liao 已提交
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
  if (pArithInfo->existDataBlock) {  // TODO refactor
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;

    SSDataBlock* pBlock = pArithInfo->existDataBlock;
    pArithInfo->existDataBlock = NULL;
    *newgroup = true;

    // todo dynamic set tags
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }

    // the pDataBlock are always the same one, no need to call this again
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
    updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);

    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);

    if (pTableQueryInfo != NULL) { // TODO refactor
      updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
    }

    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
      clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
      return pRes;
    }
  }

H
Haojun Liao 已提交
4835
  while(1) {
H
Haojun Liao 已提交
4836 4837 4838 4839
    bool prevVal = *newgroup;

    // The upstream exec may change the value of the newgroup, so use a local variable instead.
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4840
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4841 4842 4843
      assert(*newgroup == false);

      *newgroup = prevVal;
H
Haojun Liao 已提交
4844
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4845
      break;
H
Haojun Liao 已提交
4846 4847
    }

H
Haojun Liao 已提交
4848
    // Return result of the previous group in the firstly.
4849
    if (*newgroup && pRes->info.rows > 0) {
H
Haojun Liao 已提交
4850 4851 4852 4853 4854
      pArithInfo->existDataBlock = pBlock;
      clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
      return pInfo->pRes;
    }

H
Haojun Liao 已提交
4855
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
4856 4857

    // todo dynamic set tags
H
Haojun Liao 已提交
4858 4859 4860
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
H
Haojun Liao 已提交
4861

H
Haojun Liao 已提交
4862
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4863
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4864
    updateOutputBuf(&pArithInfo->binfo, &pArithInfo->bufCapacity, pBlock->info.rows);
4865

H
Haojun Liao 已提交
4866
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4867 4868 4869 4870

    if (pTableQueryInfo != NULL) { // TODO refactor
      updateTableIdInfo(pTableQueryInfo, pBlock, pRuntimeEnv->pTableRetrieveTsMap, order);
    }
H
Haojun Liao 已提交
4871

H
Haojun Liao 已提交
4872 4873
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4874 4875 4876 4877
      break;
    }
  }

H
Haojun Liao 已提交
4878
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4879
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4880 4881
}

H
Haojun Liao 已提交
4882
static SSDataBlock* doLimit(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4883
  SOperatorInfo* pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4884
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4885
    return NULL;
H
Haojun Liao 已提交
4886 4887
  }

H
Haojun Liao 已提交
4888
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4889
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4890

H
Haojun Liao 已提交
4891
  SSDataBlock* pBlock = NULL;
H
Haojun Liao 已提交
4892
  while (1) {
H
Haojun Liao 已提交
4893
    pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4894
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4895
      setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4896
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4897 4898 4899
      return NULL;
    }

H
Haojun Liao 已提交
4900
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4901
      break;
4902
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4903
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4904
    } else {
sangshuduo's avatar
sangshuduo 已提交
4905
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4906 4907 4908
      pBlock->info.rows = remain;

      for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
H
Haojun Liao 已提交
4909
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
H
Haojun Liao 已提交
4910 4911

        int16_t bytes = pColInfoData->info.bytes;
H
Haojun Liao 已提交
4912
        memmove(pColInfoData->pData, pColInfoData->pData + bytes * pRuntimeEnv->currentOffset, remain * bytes);
H
Haojun Liao 已提交
4913 4914
      }

H
Haojun Liao 已提交
4915
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4916
      break;
H
Haojun Liao 已提交
4917 4918
    }
  }
H
Haojun Liao 已提交
4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930

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

    setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
    pOperator->status = OP_EXEC_DONE;
  } else {
    pInfo->total += pBlock->info.rows;
  }

  return pBlock;
H
Haojun Liao 已提交
4931 4932
}

D
dapan1121 已提交
4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945

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;
    }
  }
H
Haojun Liao 已提交
4946

D
dapan1121 已提交
4947 4948 4949 4950 4951 4952 4953
  if (fp(filterElem, input, input, p->info.type)) {
    return true;
  }

  return false;
}

4954
static SSDataBlock* doFilter(void* param, bool* newgroup) {
D
dapan1121 已提交
4955 4956 4957 4958 4959
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

H
Haojun Liao 已提交
4960
  SFilterOperatorInfo* pCondInfo = pOperator->info;
D
dapan1121 已提交
4961 4962 4963
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

  while (1) {
H
Haojun Liao 已提交
4964
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
D
dapan1121 已提交
4965
    if (pBlock == NULL) {
4966
      break;
D
dapan1121 已提交
4967
    }
H
Haojun Liao 已提交
4968

4969 4970 4971
    doSetFilterColumnInfo(pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock);
    assert(pRuntimeEnv->pTsBuf == NULL);
    filterRowsInDataBlock(pRuntimeEnv, pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock, true);
D
dapan1121 已提交
4972

4973 4974 4975
    if (pBlock->info.rows > 0) {
      return pBlock;
    }
D
dapan1121 已提交
4976 4977
  }

4978 4979 4980 4981
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  pOperator->status = OP_EXEC_DONE;
  return NULL;
}
D
dapan1121 已提交
4982

H
Haojun Liao 已提交
4983
static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4984
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4985
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4986 4987 4988
    return NULL;
  }

H
Haojun Liao 已提交
4989
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4990

H
Haojun Liao 已提交
4991
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4992
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4993 4994
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4995
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4996
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4997 4998 4999 5000
    }

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

H
Haojun Liao 已提交
5002 5003 5004
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
H
Haojun Liao 已提交
5005

H
Haojun Liao 已提交
5006
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
5007 5008

  while(1) {
H
Haojun Liao 已提交
5009
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5010 5011 5012 5013 5014
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5015
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
H
Haojun Liao 已提交
5016
    hashIntervalAgg(pOperator, &pIntervalInfo->resultRowInfo, pBlock, 0);
H
Haojun Liao 已提交
5017 5018
  }

5019
  // restore the value
H
Haojun Liao 已提交
5020 5021
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
5022

H
Haojun Liao 已提交
5023
  pOperator->status = OP_RES_TO_RETURN;
5024
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
5025
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
5026
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5027

H
Haojun Liao 已提交
5028
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
5029
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
5030

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

H
Haojun Liao 已提交
5035
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
5036 5037
}

H
Haojun Liao 已提交
5038
static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5039
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5040
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5041 5042 5043
    return NULL;
  }

H
Haojun Liao 已提交
5044
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
5045
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5046

H
Haojun Liao 已提交
5047
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5048
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5049
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5050
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5051 5052 5053 5054 5055
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
5056 5057
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
5058

H
Haojun Liao 已提交
5059
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
5060 5061

  while(1) {
H
Haojun Liao 已提交
5062
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5063
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5064
      break;
H
Haojun Liao 已提交
5065 5066
    }

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

H
Haojun Liao 已提交
5070
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5071
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
5072
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
5073

H
Haojun Liao 已提交
5074
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
5075
  }
H
Haojun Liao 已提交
5076

H
Haojun Liao 已提交
5077
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5078
  pQueryAttr->order.order = order;   // TODO : restore the order
5079
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
5080
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
5081

H
Haojun Liao 已提交
5082
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5083
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5084
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5085 5086 5087 5088
  }

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

H
Haojun Liao 已提交
5090
static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109
  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;
  }

H
Haojun Liao 已提交
5110 5111 5112
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
5113 5114 5115 5116

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5117
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
5118 5119 5120 5121 5122
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5123
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQueryAttr->order.order);
5124 5125 5126 5127
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

  // restore the value
H
Haojun Liao 已提交
5128 5129
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145

  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 已提交
5146
static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5147
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5148
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5149 5150 5151
    return NULL;
  }

H
Haojun Liao 已提交
5152
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5153

H
Haojun Liao 已提交
5154
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5155
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5156
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5157 5158

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

H
Haojun Liao 已提交
5162
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5163 5164 5165 5166 5167
  }

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5168
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5169 5170 5171 5172 5173
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5174
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQueryAttr->order.order);
H
Haojun Liao 已提交
5175
    setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5176
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
5177
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQueryAttr->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
5178 5179
    }

H
Haojun Liao 已提交
5180
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5181 5182
  }

H
Haojun Liao 已提交
5183
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5184
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5185
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5186

H
Haojun Liao 已提交
5187
  if (!pRuntimeEnv->pQueryAttr->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5188 5189 5190
    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);
5191 5192
  }

H
Haojun Liao 已提交
5193
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5194
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5195

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

H
Haojun Liao 已提交
5200
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5201 5202
}

H
Haojun Liao 已提交
5203
static SSDataBlock* doFill(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5204
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5205
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5206 5207 5208
    return NULL;
  }

H
Haojun Liao 已提交
5209
  SFillOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5210
  SQueryRuntimeEnv  *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5211

H
Haojun Liao 已提交
5212
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
H
Haojun Liao 已提交
5213
    *newgroup = false;
sangshuduo's avatar
sangshuduo 已提交
5214
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5215 5216 5217
    return pInfo->pRes;
  }

H
Haojun Liao 已提交
5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232
  // handle the cached new group data block
  if (pInfo->existNewGroupBlock) {
    pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
    int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey;
    taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);

    taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
    taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
    pInfo->existNewGroupBlock = NULL;
    *newgroup = true;
    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
  }

H
Haojun Liao 已提交
5233
  while(1) {
H
Haojun Liao 已提交
5234 5235 5236 5237 5238 5239 5240 5241
    SSDataBlock* pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
    if (*newgroup) {
      assert(pBlock != NULL);
    }

    if (*newgroup && pInfo->totalInputRows > 0) {  // there are already processed current group data block
      pInfo->existNewGroupBlock = pBlock;
      *newgroup = false;
H
Haojun Liao 已提交
5242

H
Haojun Liao 已提交
5243 5244
      // fill the previous group data block
      // before handle a new data block, close the fill operation for previous group data block
H
Haojun Liao 已提交
5245
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
H
Haojun Liao 已提交
5246
    } else {
H
Haojun Liao 已提交
5247 5248 5249 5250 5251 5252 5253 5254 5255
      if (pBlock == NULL) {
        if (pInfo->totalInputRows == 0) {
          pOperator->status = OP_EXEC_DONE;
          return NULL;
        }

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

H
Haojun Liao 已提交
5257 5258
        int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
                                                                            : */pBlock->info.window.ekey;
H
Haojun Liao 已提交
5259

H
Haojun Liao 已提交
5260 5261 5262
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
H
Haojun Liao 已提交
5263 5264
    }

H
Haojun Liao 已提交
5265
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285
    if (pInfo->pRes->info.rows > 0) {  // current group has no more result to return
      return pInfo->pRes;
    } else if (pInfo->existNewGroupBlock) {  // try next group
      pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
      int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey
                                                                          :*/ pInfo->existNewGroupBlock->info.window.ekey;
      taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start);

      taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
      taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

      doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
      pInfo->existNewGroupBlock = NULL;
      *newgroup = true;

      return (pInfo->pRes->info.rows > 0) ? pInfo->pRes : NULL;
    } else {
      return NULL;
    }
    //    return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
5286 5287
  }
}
H
Haojun Liao 已提交
5288

H
Haojun Liao 已提交
5289
// todo set the attribute of query scan count
H
Haojun Liao 已提交
5290 5291 5292
static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = pQueryAttr->pExpr1[i].base.functionId;
H
Haojun Liao 已提交
5293 5294 5295 5296 5297 5298 5299 5300
    if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) {
      return 2;
    }
  }

  return 1;
}

H
Haojun Liao 已提交
5301 5302 5303 5304 5305
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5306
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5307
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5308 5309
  }

H
Haojun Liao 已提交
5310
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5311
  tfree(pOperator->info);
H
Haojun Liao 已提交
5312 5313 5314
  tfree(pOperator);
}

H
Haojun Liao 已提交
5315
SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5316 5317
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5318 5319
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
H
Haojun Liao 已提交
5320 5321

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

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

H
Haojun Liao 已提交
5326
  pInfo->seed = rand();
H
Haojun Liao 已提交
5327
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5328

H
Haojun Liao 已提交
5329
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5330
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5331
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5332
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5333
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5334
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5335
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5336 5337 5338
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5339

H
Haojun Liao 已提交
5340 5341
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5342 5343 5344
  return pOperator;
}

H
Haojun Liao 已提交
5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361
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 已提交
5362
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5363 5364 5365 5366
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5367
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5368
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5369
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5370 5371 5372 5373 5374 5375 5376
}

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

H
Haojun Liao 已提交
5377 5378 5379 5380 5381
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

5382
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5383
  SFilterOperatorInfo* pInfo = (SFilterOperatorInfo*) param;
5384
  doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
D
dapan1121 已提交
5385 5386
}

5387 5388 5389 5390 5391 5392
static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) {
  SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param;
  taosHashCleanup(pInfo->pSet);
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

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

H
Haojun Liao 已提交
5396
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5397

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

5402
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5403 5404
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5405
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5406
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5407
  pOperator->info         = pInfo;
5408
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5409 5410 5411
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5412

H
Haojun Liao 已提交
5413 5414 5415
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5416
  return pOperator;
H
Haojun Liao 已提交
5417 5418
}

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

H
Haojun Liao 已提交
5422
  pInfo->seed = rand();
H
Haojun Liao 已提交
5423
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5424

H
Haojun Liao 已提交
5425
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5426
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5427 5428 5429
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5430
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5431 5432

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5433 5434
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5435
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5436
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5437
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5438
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5439 5440 5441
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5442

H
Haojun Liao 已提交
5443 5444 5445
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

H
Haojun Liao 已提交
5446 5447 5448
  return pOperator;
}

H
Haojun Liao 已提交
5449
SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5450
                                           int32_t numOfOutput) {
H
Haojun Liao 已提交
5451
  SFilterOperatorInfo* pInfo = calloc(1, sizeof(SFilterOperatorInfo));
D
dapan1121 已提交
5452

5453 5454
  {
    SColumnInfo* pCols = calloc(numOfOutput, sizeof(SColumnInfo));
D
dapan1121 已提交
5455

5456 5457 5458 5459 5460
    int32_t numOfFilter = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
      if (pExpr[i].base.flist.numOfFilters > 0) {
        numOfFilter += 1;
      }
D
dapan1121 已提交
5461

5462 5463 5464
      pCols[i].type = pExpr[i].base.resType;
      pCols[i].bytes = pExpr[i].base.resBytes;
      pCols[i].colId = pExpr[i].base.resColId;
H
Haojun Liao 已提交
5465

5466 5467 5468
      pCols[i].flist.numOfFilters = pExpr[i].base.flist.numOfFilters;
      pCols[i].flist.filterInfo = calloc(pCols[i].flist.numOfFilters, sizeof(SColumnFilterInfo));
      memcpy(pCols[i].flist.filterInfo, pExpr[i].base.flist.filterInfo, pCols[i].flist.numOfFilters * sizeof(SColumnFilterInfo));
D
dapan1121 已提交
5469 5470
    }

5471 5472 5473
    assert(numOfFilter > 0);
    doCreateFilterInfo(pCols, numOfOutput, numOfFilter, &pInfo->pFilterInfo, 0);
    pInfo->numOfFilterCols = numOfFilter;
D
dapan1121 已提交
5474

5475 5476
    for(int32_t i = 0; i < numOfOutput; ++i) {
      tfree(pCols[i].flist.filterInfo);
D
dapan1121 已提交
5477 5478
    }

5479
    tfree(pCols);
D
dapan1121 已提交
5480 5481 5482 5483
  }

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

5484
  pOperator->name         = "ConditionOperator";
H
Haojun Liao 已提交
5485
  pOperator->operatorType = OP_Filter;
D
dapan1121 已提交
5486 5487 5488 5489 5490
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
5491
  pOperator->exec         = doFilter;
D
dapan1121 已提交
5492 5493
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5494
  pOperator->cleanup      = destroyConditionOperatorInfo;
D
dapan1121 已提交
5495 5496 5497 5498

  return pOperator;
}

H
Haojun Liao 已提交
5499
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5500
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
H
Haojun Liao 已提交
5501
  pInfo->limit = pRuntimeEnv->pQueryAttr->limit.limit;
H
Haojun Liao 已提交
5502 5503 5504

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

H
Haojun Liao 已提交
5505 5506
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5507
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5508
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5509
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5510
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5511 5512
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5513 5514 5515 5516

  return pOperator;
}

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

H
Haojun Liao 已提交
5520
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5521
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5522
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5523 5524 5525

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

H
Haojun Liao 已提交
5526
  pOperator->name         = "TimeIntervalAggOperator";
5527
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5528
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5529
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5530
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5531 5532 5533 5534
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5535
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5536 5537
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5538 5539 5540
  return pOperator;
}

5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565
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 已提交
5566
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5567
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5568

H
Haojun Liao 已提交
5569
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5570
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5571
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5572 5573

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5574 5575
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5576
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5577
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5578
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5579 5580
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5581 5582
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5583

H
Haojun Liao 已提交
5584 5585 5586
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5587 5588 5589
  return pOperator;
}

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

H
Haojun Liao 已提交
5594
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5595
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5596
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5597 5598

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5599
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5600
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5601 5602
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5603
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5604 5605 5606 5607
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5608
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5609 5610
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5611 5612
  return pOperator;
}
H
Haojun Liao 已提交
5613

H
Haojun Liao 已提交
5614
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5615
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5616
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5617 5618 5619
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);

  {
H
Haojun Liao 已提交
5620 5621
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQueryAttr->fillVal);
H
Haojun Liao 已提交
5622 5623
    STimeWindow w = TSWINDOW_INITIALIZER;

H
Haojun Liao 已提交
5624 5625 5626
    TSKEY sk = MIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
    TSKEY ek = MAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
    getAlignQueryTimeWindow(pQueryAttr, pQueryAttr->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
5627

H
Haojun Liao 已提交
5628 5629 5630 5631
    pInfo->pFillInfo =
        taosCreateFillInfo(pQueryAttr->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput,
                           pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit,
                           (int8_t)pQueryAttr->precision, pQueryAttr->fillType, pColInfo, pRuntimeEnv->qinfo);
H
Haojun Liao 已提交
5632
  }
H
Haojun Liao 已提交
5633 5634 5635

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

H
Haojun Liao 已提交
5636
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5637
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5638 5639 5640
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5641
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5642 5643 5644 5645
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5646

H
Haojun Liao 已提交
5647 5648 5649
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5650 5651 5652
  return pOperator;
}

H
Haojun Liao 已提交
5653
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) {
H
Haojun Liao 已提交
5654 5655
  SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo));

H
Haojun Liao 已提交
5656 5657 5658
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;

  pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr);
H
Haojun Liao 已提交
5659 5660
  pInfo->slimit          = pQueryAttr->slimit;
  pInfo->limit           = pQueryAttr->limit;
H
Haojun Liao 已提交
5661 5662 5663

  pInfo->currentGroupOffset = pQueryAttr->slimit.offset;
  pInfo->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
5664 5665 5666 5667 5668 5669 5670

  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
    len += pExpr[i].base.resBytes;
  }

H
Haojun Liao 已提交
5671
  int32_t numOfCols = pInfo->orderColumnList != NULL? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
5672
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
5673
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
5674 5675 5676 5677 5678 5679 5680

  for(int32_t i = 0; i < numOfCols; ++i) {
    pInfo->prevRow[i] = (char*)pInfo->prevRow + offset;

    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
  }
H
Haojun Liao 已提交
5681 5682 5683 5684 5685 5686 5687 5688

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

  pOperator->name         = "SLimitOperator";
  pOperator->operatorType = OP_SLimit;
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5689
  pOperator->exec         = doSLimit;
H
Haojun Liao 已提交
5690 5691
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5692
  pOperator->cleanup      = destroySlimitOperatorInfo;
H
Haojun Liao 已提交
5693 5694 5695
  return pOperator;
}

H
Haojun Liao 已提交
5696
static SSDataBlock* doTagScan(void* param, bool* newgroup) {
5697
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5698
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5699 5700
    return NULL;
  }
5701

H
Haojun Liao 已提交
5702
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5703

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

H
Haojun Liao 已提交
5706 5707
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
H
Haojun Liao 已提交
5708
  *newgroup = false;
5709 5710

  int32_t count = 0;
H
Haojun Liao 已提交
5711 5712 5713 5714
  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
H
Haojun Liao 已提交
5715 5716
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    assert(pQueryAttr->numOfOutput == 1);
5717 5718

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
H
Haojun Liao 已提交
5719
    int32_t rsize = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
5720

5721 5722
    count = 0;

H
Haojun Liao 已提交
5723 5724
    int16_t bytes = pExprInfo->base.resBytes;
    int16_t type  = pExprInfo->base.resType;
5725

H
Haojun Liao 已提交
5726 5727 5728 5729
    for(int32_t i = 0; i < pQueryAttr->numOfTags; ++i) {
      if (pQueryAttr->tagColList[i].colId == pExprInfo->base.colInfo.colId) {
        bytes = pQueryAttr->tagColList[i].bytes;
        type = pQueryAttr->tagColList[i].type;
5730 5731 5732 5733
        break;
      }
    }

H
Haojun Liao 已提交
5734 5735 5736 5737
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5740
      char *output = pColInfo->pData + count * rsize;
5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754
      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);

H
Haojun Liao 已提交
5755 5756
      *(int32_t *)output = pQueryAttr->vgId;
      output += sizeof(pQueryAttr->vgId);
5757

H
Haojun Liao 已提交
5758
      char* data = NULL;
5759
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5760
        data = tsdbGetTableName(item->pTable);
5761
      } else {
H
Haojun Liao 已提交
5762
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5763 5764
      }

H
Haojun Liao 已提交
5765
      doSetTagValueToResultBuf(output, data, type, bytes);
5766 5767 5768
      count += 1;
    }

H
Haojun Liao 已提交
5769
    qDebug("QInfo:0x%"PRIx64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5770 5771 5772
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5773
    count = 1;
H
Haojun Liao 已提交
5774 5775

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

H
Haojun Liao 已提交
5780 5781 5782
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793

      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 已提交
5794
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5795 5796
        type  = pExprInfo[j].base.resType;
        bytes = pExprInfo[j].base.resBytes;
5797 5798 5799 5800 5801 5802 5803

        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 已提交
5804
        dst  = pColInfo->pData + count * pExprInfo[j].base.resBytes;
5805 5806
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5807

5808 5809 5810
      count += 1;
    }

H
Haojun Liao 已提交
5811 5812 5813 5814
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

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

H
Haojun Liao 已提交
5818
  pRes->info.rows = count;
H
Haojun Liao 已提交
5819
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5820 5821
}

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

H
Haojun Liao 已提交
5826 5827 5828 5829 5830 5831
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5832
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5833
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5834
  pOperator->operatorType = OP_TagScan;
5835
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5836
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5837 5838
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5839 5840
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5841
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5842
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5843

5844 5845
  return pOperator;
}
H
Haojun Liao 已提交
5846

5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912
static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SDistinctOperatorInfo* pInfo = pOperator->info;
  SSDataBlock* pRes = pInfo->pRes;

  pRes->info.rows = 0;
  SSDataBlock* pBlock = NULL;
  while(1) {
    pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
    if (pBlock == NULL) {
      setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
      pOperator->status = OP_EXEC_DONE;
      return NULL;
    }

    assert(pBlock->info.numOfCols == 1);
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);

    int16_t bytes = pColInfoData->info.bytes;
    int16_t type = pColInfoData->info.type;

    // ensure the output buffer size
    SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, 0);
    if (pRes->info.rows + pBlock->info.rows > pInfo->outputCapacity) {
      int32_t newSize = pRes->info.rows + pBlock->info.rows;
      char* tmp = realloc(pResultColInfoData->pData, newSize * bytes);
      if (tmp == NULL) {
        return NULL;
      } else {
        pResultColInfoData->pData = tmp;
        pInfo->outputCapacity = newSize;
      }
    }

    for(int32_t i = 0; i < pBlock->info.rows; ++i) {
      char* val = ((char*)pColInfoData->pData) + bytes * i;
      if (isNull(val, type)) {
        continue;
      }

      void* res = taosHashGet(pInfo->pSet, val, bytes);
      if (res == NULL) {
        taosHashPut(pInfo->pSet, val, bytes, NULL, 0);
        char* start = pResultColInfoData->pData + bytes * pInfo->pRes->info.rows;
        memcpy(start, val, bytes);
        pRes->info.rows += 1;
      }
    }

    if (pRes->info.rows >= pInfo->threshold) {
      break;
    }
  }

  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
}

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

  pInfo->outputCapacity = 4096;
  pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(pExpr->base.colType), false, HASH_NO_LOCK);
H
Haojun Liao 已提交
5913
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity);
5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "DistinctOperator";
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Distinct;
  pOperator->upstream     = upstream;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = hashDistinct;
  pOperator->cleanup      = destroyDistinctOperatorInfo;
  return pOperator;
}

H
Haojun Liao 已提交
5929
static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
5930
  int32_t j = 0;
5931

H
Haojun Liao 已提交
5932 5933
  if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
    if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5934
      return TSDB_TBNAME_COLUMN_INDEX;
H
Haojun Liao 已提交
5935
    } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
Y
yihaoDeng 已提交
5936
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5937
    }
Y
yihaoDeng 已提交
5938
    
H
Haojun Liao 已提交
5939

H
Haojun Liao 已提交
5940 5941
    while(j < pTableInfo->numOfTags) {
      if (pExpr->colInfo.colId == pTagCols[j].colId) {
5942 5943
        return j;
      }
5944

5945 5946
      j += 1;
    }
5947

H
Haojun Liao 已提交
5948
  } else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5949
    return TSDB_UD_COLUMN_INDEX;
5950
  } else {
H
Haojun Liao 已提交
5951 5952
    while (j < pTableInfo->numOfCols) {
      if (pExpr->colInfo.colId == pTableInfo->colList[j].colId) {
5953 5954
        return j;
      }
5955

5956
      j += 1;
5957 5958
    }
  }
5959 5960

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5961 5962
}

H
Haojun Liao 已提交
5963 5964
bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols);
5965
  return j != INT32_MIN;
5966 5967
}

5968
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5969 5970
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5971
    return false;
5972 5973
  }

5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984
  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 已提交
5985
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5986
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5987
    return false;
5988 5989
  }

H
hjxilinx 已提交
5990
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5991
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5992
    return false;
5993 5994
  }

5995 5996
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5997
    return false;
5998 5999
  }

6000 6001 6002
  return true;
}

H
Haojun Liao 已提交
6003 6004 6005 6006 6007
static UNUSED_FUNC bool validateQueryTableCols(SQueriedTableInfo* pTableInfo, SSqlExpr** pExpr, int32_t numOfOutput,
                                   SColumnInfo* pTagCols, void* pMsg) {
  int32_t numOfTotal = pTableInfo->numOfCols + pTableInfo->numOfTags;
  if (pTableInfo->numOfCols < 0 || pTableInfo->numOfTags < 0 || numOfTotal > TSDB_MAX_COLUMNS) {
    qError("qmsg:%p illegal value of numOfCols %d numOfTags:%d", pMsg, pTableInfo->numOfCols, pTableInfo->numOfTags);
6008
    return false;
6009 6010
  }

H
Haojun Liao 已提交
6011 6012 6013 6014 6015 6016 6017
  if (numOfTotal == 0) {  // table total columns are not required.
    for(int32_t i = 0; i < numOfOutput; ++i) {
      SSqlExpr* p = pExpr[i];
      if ((p->functionId == TSDB_FUNC_TAGPRJ) ||
          (p->functionId == TSDB_FUNC_TID_TAG && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (p->functionId == TSDB_FUNC_COUNT && p->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) ||
          (p->functionId == TSDB_FUNC_BLKINFO)) {
6018
        continue;
6019
      }
6020

6021
      return false;
6022 6023
    }
  }
6024

H
Haojun Liao 已提交
6025 6026
  for(int32_t i = 0; i < numOfOutput; ++i) {
    if (!validateExprColumnInfo(pTableInfo, pExpr[i], pTagCols)) {
6027 6028 6029 6030
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

6031
  return true;
6032 6033
}

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

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

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

6042
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
6043 6044
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
6045

H
hjxilinx 已提交
6046 6047 6048
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
6049

H
hjxilinx 已提交
6050 6051
  return pMsg;
}
6052

6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083
static int32_t deserializeColFilterInfo(SColumnFilterInfo* pColFilters, int16_t numOfFilters, char** pMsg) {
  for (int32_t f = 0; f < numOfFilters; ++f) {
    SColumnFilterInfo *pFilterMsg = (SColumnFilterInfo *)(*pMsg);

    SColumnFilterInfo *pColFilter = &pColFilters[f];
    pColFilter->filterstr = htons(pFilterMsg->filterstr);

    (*pMsg) += sizeof(SColumnFilterInfo);

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

      pColFilter->pz = (int64_t)calloc(1, (size_t)(pColFilter->len + 1 * TSDB_NCHAR_SIZE)); // note: null-terminator
      if (pColFilter->pz == 0) {
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }

      memcpy((void *)pColFilter->pz, (*pMsg), (size_t)pColFilter->len);
      (*pMsg) += (pColFilter->len + 1);
    } else {
      pColFilter->lowerBndi = htobe64(pFilterMsg->lowerBndi);
      pColFilter->upperBndi = htobe64(pFilterMsg->upperBndi);
    }

    pColFilter->lowerRelOptr = htons(pFilterMsg->lowerRelOptr);
    pColFilter->upperRelOptr = htons(pFilterMsg->upperRelOptr);
  }

  return TSDB_CODE_SUCCESS;
}

6084
/**
H
hjxilinx 已提交
6085
 * pQueryMsg->head has been converted before this function is called.
6086
 *
H
hjxilinx 已提交
6087
 * @param pQueryMsg
6088 6089 6090 6091
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
6092
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
6093 6094
  int32_t code = TSDB_CODE_SUCCESS;

6095 6096 6097 6098
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

6099 6100 6101
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);
  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
6102 6103 6104
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
6105 6106
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
6107
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
6108

6109 6110
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
6111
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
6112
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
6113 6114

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
6115
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
6116
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
6117
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
H
Haojun Liao 已提交
6118 6119 6120 6121
  pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset);
  pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen);
  pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks);
  pQueryMsg->tsBuf.tsOrder = htonl(pQueryMsg->tsBuf.tsOrder);
6122
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
6123
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6124
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
6125
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
6126
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
6127 6128
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
H
Haojun Liao 已提交
6129 6130
  pQueryMsg->tableScanOperator = htonl(pQueryMsg->tableScanOperator);
  pQueryMsg->numOfOperator = htonl(pQueryMsg->numOfOperator);
6131

6132
  // query msg safety check
6133
  if (!validateQueryMsg(pQueryMsg)) {
6134 6135
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
6136 6137
  }

H
Haojun Liao 已提交
6138
  char *pMsg = (char *)(pQueryMsg->tableCols) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
H
hjxilinx 已提交
6139
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
H
Haojun Liao 已提交
6140
    SColumnInfo *pColInfo = &pQueryMsg->tableCols[col];
6141

H
hjxilinx 已提交
6142
    pColInfo->colId = htons(pColInfo->colId);
6143
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
6144
    pColInfo->bytes = htons(pColInfo->bytes);
6145
    pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters);
6146

6147 6148 6149 6150 6151
    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;
    }
6152

6153
    int32_t numOfFilters = pColInfo->flist.numOfFilters;
6154
    if (numOfFilters > 0) {
6155 6156
      pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo));
      if (pColInfo->flist.filterInfo == NULL) {
H
Haojun Liao 已提交
6157 6158 6159
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
6160 6161
    }

6162 6163 6164
    code = deserializeColFilterInfo(pColInfo->flist.filterInfo, numOfFilters, &pMsg);
    if (code != TSDB_CODE_SUCCESS) {
      goto _cleanup;
6165 6166 6167
    }
  }

H
Haojun Liao 已提交
6168
  param->tableScanOperator = pQueryMsg->tableScanOperator;
H
Haojun Liao 已提交
6169 6170
  param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExpr == NULL) {
H
Haojun Liao 已提交
6171 6172 6173 6174
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

H
Haojun Liao 已提交
6175
  SSqlExpr *pExprMsg = (SSqlExpr *)pMsg;
6176

6177
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
6178
    param->pExpr[i] = pExprMsg;
6179

6180
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
6181
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6182
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6183
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6184 6185 6186 6187
    pExprMsg->colType       = htons(pExprMsg->colType);

    pExprMsg->resType       = htons(pExprMsg->resType);
    pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6188

H
Haojun Liao 已提交
6189 6190 6191
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
6192
    pExprMsg->flist.numOfFilters  = htons(pExprMsg->flist.numOfFilters);
H
Haojun Liao 已提交
6193
    pMsg += sizeof(SSqlExpr);
6194 6195

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6196 6197
      pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
      pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
6198

H
Haojun Liao 已提交
6199 6200 6201
      if (pExprMsg->param[j].nType == TSDB_DATA_TYPE_BINARY) {
        pExprMsg->param[j].pz = pMsg;
        pMsg += pExprMsg->param[j].nLen;  // one more for the string terminated char.
6202
      } else {
H
Haojun Liao 已提交
6203
        pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
6204 6205 6206
      }
    }

H
Haojun Liao 已提交
6207 6208
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
6209
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
6210 6211
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
6212 6213 6214
      }
    }

6215 6216 6217 6218 6219
    if (pExprMsg->flist.numOfFilters > 0) {
      pExprMsg->flist.filterInfo = calloc(pExprMsg->flist.numOfFilters, sizeof(SColumnFilterInfo));
    }

    deserializeColFilterInfo(pExprMsg->flist.filterInfo, pExprMsg->flist.numOfFilters, &pMsg);
H
Haojun Liao 已提交
6220
    pExprMsg = (SSqlExpr *)pMsg;
6221
  }
6222

H
Haojun Liao 已提交
6223
  if (pQueryMsg->secondStageOutput) {
H
Haojun Liao 已提交
6224 6225
    pExprMsg = (SSqlExpr *)pMsg;
    param->pSecExpr = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
6226

H
Haojun Liao 已提交
6227
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
H
Haojun Liao 已提交
6228
      param->pSecExpr[i] = pExprMsg;
H
Haojun Liao 已提交
6229 6230 6231

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6232
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6233 6234
      pExprMsg->resType       = htons(pExprMsg->resType);
      pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6235
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6236
      pExprMsg->colType       = htons(pExprMsg->colType);
H
Haojun Liao 已提交
6237

H
Haojun Liao 已提交
6238 6239 6240
      pExprMsg->functionId = htons(pExprMsg->functionId);
      pExprMsg->numOfParams = htons(pExprMsg->numOfParams);

H
Haojun Liao 已提交
6241
      pMsg += sizeof(SSqlExpr);
H
Haojun Liao 已提交
6242 6243

      for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6244 6245
        pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
        pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
H
Haojun Liao 已提交
6246

H
Haojun Liao 已提交
6247 6248 6249
        if (pExprMsg->param[j].nType == TSDB_DATA_TYPE_BINARY) {
          pExprMsg->param[j].pz = pMsg;
          pMsg += pExprMsg->param[j].nLen;  // one more for the string terminated char.
H
Haojun Liao 已提交
6250
        } else {
H
Haojun Liao 已提交
6251
          pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
H
Haojun Liao 已提交
6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262
        }
      }

      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;
        }
      }

H
Haojun Liao 已提交
6263
      pExprMsg = (SSqlExpr *)pMsg;
H
Haojun Liao 已提交
6264 6265 6266
    }
  }

6267
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
6268

H
hjxilinx 已提交
6269
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
6270 6271
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
6272 6273 6274
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6275 6276

    for (int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
6277 6278
      param->pGroupColIndex[i].colId = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colId);
6279

6280 6281
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
6282

6283 6284
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
6285

6286 6287
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
6288
    }
6289

H
hjxilinx 已提交
6290 6291
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
6292 6293
  }

6294 6295
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
6296
    pQueryMsg->fillVal = (uint64_t)(pMsg);
6297 6298

    int64_t *v = (int64_t *)pMsg;
6299
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
6300 6301
      v[i] = htobe64(v[i]);
    }
6302

6303
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
6304
  }
6305

6306
  if (pQueryMsg->numOfTags > 0) {
6307 6308
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
6309 6310 6311 6312
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6313 6314
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6315

6316 6317 6318
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
6319
      pTagCol->flist.numOfFilters = 0;
6320

6321
      param->pTagColumnInfo[i] = *pTagCol;
6322
      pMsg += sizeof(SColumnInfo);
6323
    }
H
hjxilinx 已提交
6324
  }
6325

6326 6327
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6328 6329
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6330 6331 6332
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6333 6334

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6335 6336
    pMsg += pQueryMsg->tagCondLen;
  }
6337

6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348
  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 已提交
6349
  if (pQueryMsg->tbnameCondLen > 0) {
6350 6351
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6352 6353 6354 6355
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6356
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6357
    pMsg += pQueryMsg->tbnameCondLen;
6358 6359
  }

D
dapan1121 已提交
6360
  //skip ts buf
H
Haojun Liao 已提交
6361 6362
  if ((pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen;
D
dapan1121 已提交
6363 6364
  }

H
Haojun Liao 已提交
6365 6366 6367 6368 6369 6370 6371 6372
  param->pOperator = taosArrayInit(pQueryMsg->numOfOperator, sizeof(int32_t));
  for(int32_t i = 0; i < pQueryMsg->numOfOperator; ++i) {
    int32_t op = htonl(*(int32_t*)pMsg);
    taosArrayPush(param->pOperator, &op);

    pMsg += sizeof(int32_t);
  }

6373
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6374

H
Haojun Liao 已提交
6375
  SQueriedTableInfo info = { .numOfTags = pQueryMsg->numOfTags, .numOfCols = pQueryMsg->numOfCols, .colList = pQueryMsg->tableCols};
H
Haojun Liao 已提交
6376
  if (!validateQueryTableCols(&info, param->pExpr, pQueryMsg->numOfOutput, param->pTagColumnInfo, pQueryMsg)) {
6377 6378
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6379
  }
6380

6381
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6382 6383
         "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,
6384
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6385
         pQueryMsg->fillType, pQueryMsg->tsBuf.tsLen, pQueryMsg->tsBuf.tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6386

6387
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6388
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6389 6390

_cleanup:
6391
  freeParam(param);
6392
  return code;
6393 6394
}

H
Haojun Liao 已提交
6395 6396 6397 6398
  int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
    if (filterNum <= 0) {
      return TSDB_CODE_SUCCESS;
    }
D
dapan1121 已提交
6399

H
Haojun Liao 已提交
6400 6401 6402 6403
    *dst = calloc(filterNum, sizeof(*src));
    if (*dst == NULL) {
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
D
dapan1121 已提交
6404

H
Haojun Liao 已提交
6405
    memcpy(*dst, src, sizeof(*src) * filterNum);
D
dapan1121 已提交
6406

H
Haojun Liao 已提交
6407 6408 6409
    for (int32_t i = 0; i < filterNum; i++) {
      if ((*dst)[i].filterstr && dst[i]->len > 0) {
        void *pz = calloc(1, (size_t)(*dst)[i].len + 1);
D
dapan1121 已提交
6410

H
Haojun Liao 已提交
6411 6412 6413 6414 6415 6416
        if (pz == NULL) {
          if (i == 0) {
            free(*dst);
          } else {
            freeColumnFilterInfo(*dst, i);
          }
D
dapan1121 已提交
6417

H
Haojun Liao 已提交
6418 6419
          return TSDB_CODE_QRY_OUT_OF_MEMORY;
        }
D
dapan1121 已提交
6420

H
Haojun Liao 已提交
6421
        memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6422

H
Haojun Liao 已提交
6423 6424 6425
        (*dst)[i].pz = (int64_t)pz;
      }
    }
D
dapan1121 已提交
6426

H
Haojun Liao 已提交
6427 6428 6429
    return TSDB_CODE_SUCCESS;
  }

6430
int32_t buildArithmeticExprFromMsg(SExprInfo *pExprInfo, void *pQueryMsg) {
H
Haojun Liao 已提交
6431
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6432 6433

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6434
  TRY(TSDB_MAX_TAG_CONDITIONS) {
6435
    pExprNode = exprTreeFromBinary(pExprInfo->base.param[0].pz, pExprInfo->base.param[0].nLen);
weixin_48148422's avatar
weixin_48148422 已提交
6436 6437
  } CATCH( code ) {
    CLEANUP_EXECUTE();
6438
    qError("qmsg:%p failed to create arithmetic expression string from:%s, reason: %s", pQueryMsg, pExprInfo->base.param[0].pz, tstrerror(code));
weixin_48148422's avatar
weixin_48148422 已提交
6439 6440 6441
    return code;
  } END_TRY

H
hjxilinx 已提交
6442
  if (pExprNode == NULL) {
6443
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pExprInfo->base.param[0].pz);
6444
    return TSDB_CODE_QRY_APP_ERROR;
6445
  }
6446

6447
  pExprInfo->pExpr = pExprNode;
6448 6449 6450
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6451 6452

static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6453 6454 6455 6456
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int16_t functId = pExprs[i].base.functionId;

    if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
6457 6458
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
      if (j < 0 || j >= pTableInfo->numOfCols) {
H
Haojun Liao 已提交
6459 6460
        return TSDB_CODE_QRY_INVALID_MSG;
      } else {
H
Haojun Liao 已提交
6461 6462 6463
        SColumnInfo* pCol = &pTableInfo->colList[j];
        int32_t ret = getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.param[0].i64,
                                        &pExprs[i].base.resType, &pExprs[i].base.resBytes, &pExprs[i].base.interBytes, tagLen, superTable);
H
Haojun Liao 已提交
6464 6465 6466 6467 6468 6469 6470 6471
        assert(ret == TSDB_CODE_SUCCESS);
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6472
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6473 6474
int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo,
                        SSqlExpr** pExprMsg, SColumnInfo* pTagCols, int32_t queryType, void* pMsg) {
6475
  *pExprInfo = NULL;
H
hjxilinx 已提交
6476
  int32_t code = TSDB_CODE_SUCCESS;
6477

6478
  SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo));
6479
  if (pExprs == NULL) {
6480
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6481 6482
  }

H
Haojun Liao 已提交
6483
  bool    isSuperTable = QUERY_IS_STABLE_QUERY(queryType);
6484 6485
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6486
  for (int32_t i = 0; i < numOfOutput; ++i) {
6487
    pExprs[i].base = *pExprMsg[i];
H
Haojun Liao 已提交
6488 6489 6490 6491 6492
    memset(pExprs[i].base.param, 0, sizeof(tVariant) * tListLen(pExprs[i].base.param));

    for (int32_t j = 0; j < pExprMsg[i]->numOfParams; ++j) {
      tVariantAssign(&pExprs[i].base.param[j], &pExprMsg[i]->param[j]);
    }
6493 6494 6495 6496

    int16_t type = 0;
    int16_t bytes = 0;

6497
    // parse the arithmetic expression
6498
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6499
      code = buildArithmeticExprFromMsg(&pExprs[i], pMsg);
6500

6501
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6502
        tfree(pExprs);
6503
        return code;
6504 6505
      }

6506
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6507
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6508
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6509 6510 6511
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6512 6513 6514 6515
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
H
Haojun Liao 已提交
6516
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) {
6517
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6518 6519
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

H
Haojun Liao 已提交
6520 6521
      type = pExprs[i].base.param[1].nType;
      bytes = pExprs[i].base.param[1].nLen;
H
Haojun Liao 已提交
6522 6523 6524 6525
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
H
Haojun Liao 已提交
6526
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
6527
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
H
Haojun Liao 已提交
6528
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pTableInfo->numOfTags) {
6529 6530 6531
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      } else {
H
Haojun Liao 已提交
6532
        if (j < PRIMARYKEY_TIMESTAMP_COL_INDEX || j >= pTableInfo->numOfCols) {
6533 6534 6535
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      }
H
Haojun Liao 已提交
6536

dengyihao's avatar
dengyihao 已提交
6537
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6538
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j];
H
Haojun Liao 已提交
6539 6540 6541
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6542
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6543

6544 6545
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6546
      }
D
dapan1121 已提交
6547

6548 6549 6550
      if (pExprs[i].base.flist.numOfFilters > 0) {
        int32_t ret = cloneExprFilterInfo(&pExprs[i].base.flist.filterInfo, pExprMsg[i]->flist.filterInfo,
            pExprMsg[i]->flist.numOfFilters);
D
dapan1121 已提交
6551 6552 6553 6554
        if (ret) {
          return ret;
        }
      }
6555 6556
    }

H
Haojun Liao 已提交
6557
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
H
Haojun Liao 已提交
6558
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
H
Haojun Liao 已提交
6559
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6560 6561 6562 6563
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6564 6565
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].base.resType, &pExprs[i].base.resBytes,
                          &pExprs[i].base.interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6566
      tfree(pExprs);
6567
      return TSDB_CODE_QRY_INVALID_MSG;
6568 6569
    }

6570
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
H
Haojun Liao 已提交
6571
      tagLen += pExprs[i].base.resBytes;
6572
    }
6573

H
Haojun Liao 已提交
6574
    assert(isValidDataType(pExprs[i].base.resType));
6575 6576
  }

H
Haojun Liao 已提交
6577
  // the tag length is affected by other tag columns, so this should be update.
H
Haojun Liao 已提交
6578
  updateOutputBufForTopBotQuery(pTableInfo, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6579

6580
  *pExprInfo = pExprs;
6581 6582 6583
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6584
// todo refactor
H
Haojun Liao 已提交
6585 6586
int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                           SSqlExpr** pExpr, SExprInfo* prevExpr) {
H
Haojun Liao 已提交
6587 6588 6589 6590 6591 6592 6593 6594
  *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 已提交
6595
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6596 6597

  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
6598
    pExprs[i].base = *pExpr[i];
H
Haojun Liao 已提交
6599 6600 6601 6602 6603 6604
    memset(pExprs[i].base.param, 0, sizeof(tVariant) * tListLen(pExprs[i].base.param));

    for (int32_t j = 0; j < pExpr[i]->numOfParams; ++j) {
      tVariantAssign(&pExprs[i].base.param[j], &pExpr[i]->param[j]);
    }

H
Haojun Liao 已提交
6605
    pExprs[i].base.resType = 0;
H
Haojun Liao 已提交
6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624

    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 已提交
6625 6626
      type  = prevExpr[index].base.resType;
      bytes = prevExpr[index].base.resBytes;
H
Haojun Liao 已提交
6627 6628
    }

H
Haojun Liao 已提交
6629 6630 6631
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
    if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].base.resType, &pExprs[i].base.resBytes,
                          &pExprs[i].base.interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
6632 6633 6634 6635
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6636
    assert(isValidDataType(pExprs[i].base.resType));
H
Haojun Liao 已提交
6637 6638 6639 6640 6641 6642
  }

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6643
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6644 6645 6646 6647 6648
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6649
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6650
  if (pGroupbyExpr == NULL) {
6651
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6652 6653 6654 6655 6656 6657 6658
    return NULL;
  }

  pGroupbyExpr->numOfGroupCols = pQueryMsg->numOfGroupCols;
  pGroupbyExpr->orderType = pQueryMsg->orderType;
  pGroupbyExpr->orderIndex = pQueryMsg->orderByIdx;

6659 6660 6661 6662
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6663

6664 6665 6666
  return pGroupbyExpr;
}

6667 6668 6669 6670
static int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols,
                                  SSingleColumnFilterInfo** pFilterInfo, uint64_t qId) {
  *pFilterInfo = calloc(1, sizeof(SSingleColumnFilterInfo) * numOfFilterCols);
  if (pFilterInfo == NULL) {
H
Haojun Liao 已提交
6671 6672
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6673

6674 6675 6676
  for (int32_t i = 0, j = 0; i < numOfCols; ++i) {
    if (pCols[i].flist.numOfFilters > 0) {
      SSingleColumnFilterInfo* pFilter = &((*pFilterInfo)[j]);
6677

6678 6679
      memcpy(&pFilter->info, &pCols[i], sizeof(SColumnInfo));
      pFilter->info = pCols[i];
6680

6681 6682 6683
      pFilter->numOfFilters = pCols[i].flist.numOfFilters;
      pFilter->pFilters = calloc(pFilter->numOfFilters, sizeof(SColumnFilterElem));
      if (pFilter->pFilters == NULL) {
H
Haojun Liao 已提交
6684 6685
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6686

6687 6688 6689
      for (int32_t f = 0; f < pFilter->numOfFilters; ++f) {
        SColumnFilterElem* pSingleColFilter = &pFilter->pFilters[f];
        pSingleColFilter->filterInfo = pCols[i].flist.filterInfo[f];
6690 6691 6692 6693

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
H
Haojun Liao 已提交
6694
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6695
          return TSDB_CODE_QRY_INVALID_MSG;
6696 6697
        }

6698 6699
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
H
Haojun Liao 已提交
6700
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6701
          return TSDB_CODE_QRY_INVALID_MSG;
6702 6703
        }

6704
        pSingleColFilter->bytes = pCols[i].bytes;
6705 6706 6707 6708 6709 6710 6711 6712 6713
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741
void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) {
  for (int32_t i = 0; i < numOfFilterCols; ++i) {
    if (pFilterInfo[i].numOfFilters > 0) {
      tfree(pFilterInfo[i].pFilters);
    }
  }

  tfree(pFilterInfo);
  return NULL;
}

static int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) {
  for (int32_t i = 0; i < pQueryAttr->numOfCols; ++i) {
    if (pQueryAttr->tableCols[i].flist.numOfFilters > 0) {
      pQueryAttr->numOfFilterCols++;
    }
  }

  if (pQueryAttr->numOfFilterCols == 0) {
    return TSDB_CODE_SUCCESS;
  }

  doCreateFilterInfo(pQueryAttr->tableCols, pQueryAttr->numOfCols, pQueryAttr->numOfFilterCols,
                     &pQueryAttr->pFilterInfo, qId);

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6742 6743
static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) {
  assert(pQueryAttr->pExpr1 != NULL && pQueryAttr != NULL);
6744

H
Haojun Liao 已提交
6745 6746
  for (int32_t k = 0; k < pQueryAttr->numOfOutput; ++k) {
    SSqlExpr *pSqlExprMsg = &pQueryAttr->pExpr1[k].base;
6747
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6748 6749
      continue;
    }
6750

6751
    // todo opt performance
H
Haojun Liao 已提交
6752
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6753
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6754
      int32_t f = 0;
H
Haojun Liao 已提交
6755
      for (f = 0; f < pQueryAttr->numOfCols; ++f) {
H
Haojun Liao 已提交
6756
        if (pColIndex->colId == pQueryAttr->tableCols[f].colId) {
H
Haojun Liao 已提交
6757
          pColIndex->colIndex = f;
6758 6759 6760
          break;
        }
      }
H
Haojun Liao 已提交
6761

H
Haojun Liao 已提交
6762
      assert(f < pQueryAttr->numOfCols);
6763 6764
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6765 6766
    } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      pColIndex->colIndex = 0;// only one source column, so it must be 0;
H
Haojun Liao 已提交
6767
      assert(pQueryAttr->numOfOutput == 1);
6768
    } else {
6769
      int32_t f = 0;
H
Haojun Liao 已提交
6770 6771
      for (f = 0; f < pQueryAttr->numOfTags; ++f) {
        if (pColIndex->colId == pQueryAttr->tagColList[f].colId) {
H
Haojun Liao 已提交
6772
          pColIndex->colIndex = f;
6773 6774
          break;
        }
6775
      }
6776

H
Haojun Liao 已提交
6777
      assert(f < pQueryAttr->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6778 6779 6780 6781
    }
  }
}

H
Haojun Liao 已提交
6782
void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo) {
H
Haojun Liao 已提交
6783 6784 6785 6786 6787 6788 6789
  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 已提交
6790

H
Haojun Liao 已提交
6791 6792
  if (isProjQuery(pQueryAttr)) {
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQueryAttr->resultRowSize;
H
Haojun Liao 已提交
6793 6794
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6795
    }
H
Haojun Liao 已提交
6796

H
Haojun Liao 已提交
6797
    pResultInfo->capacity  = numOfRes;
6798
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6799
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6800
  }
H
Haojun Liao 已提交
6801 6802 6803

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
  pResultInfo->total = 0;
H
Haojun Liao 已提交
6804 6805
}

D
fix bug  
dapan1121 已提交
6806 6807 6808 6809
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6810
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
H
Haojun Liao 已提交
6811
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId,
D
dapan1121 已提交
6812
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6813 6814 6815
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6816 6817
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6818
    goto _cleanup_qinfo;
6819
  }
6820

D
dapan1121 已提交
6821 6822
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6823 6824
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859
  SQueryAttr* pQueryAttr = &pQInfo->query;
  pQInfo->runtimeEnv.pQueryAttr = pQueryAttr;

  pQueryAttr->tableGroupInfo  = *pTableGroupInfo;
  pQueryAttr->numOfCols       = numOfCols;
  pQueryAttr->numOfOutput     = numOfOutput;
  pQueryAttr->limit.limit     = pQueryMsg->limit;
  pQueryAttr->limit.offset    = pQueryMsg->offset;
  pQueryAttr->order.order     = pQueryMsg->order;
  pQueryAttr->order.orderColId = pQueryMsg->orderColId;
  pQueryAttr->pExpr1          = pExprs;
  pQueryAttr->pExpr2          = pSecExprs;
  pQueryAttr->numOfExpr2      = pQueryMsg->secondStageOutput;
  pQueryAttr->pGroupbyExpr    = pGroupbyExpr;
  memcpy(&pQueryAttr->interval, &pQueryMsg->interval, sizeof(pQueryAttr->interval));
  pQueryAttr->fillType        = pQueryMsg->fillType;
  pQueryAttr->numOfTags       = pQueryMsg->numOfTags;
  pQueryAttr->tagColList      = pTagCols;
  pQueryAttr->prjInfo.vgroupLimit = pQueryMsg->vgroupLimit;
  pQueryAttr->prjInfo.ts      = (pQueryMsg->order == TSDB_ORDER_ASC)? INT64_MIN:INT64_MAX;
  pQueryAttr->sw              = pQueryMsg->sw;

  pQueryAttr->stableQuery     = pQueryMsg->stableQuery;
  pQueryAttr->topBotQuery     = pQueryMsg->topBotQuery;
  pQueryAttr->groupbyColumn   = pQueryMsg->groupbyColumn;
  pQueryAttr->hasTagResults   = pQueryMsg->hasTagResults;
  pQueryAttr->timeWindowInterpo = pQueryMsg->timeWindowInterpo;
  pQueryAttr->queryBlockDist  = pQueryMsg->queryBlockDist;
  pQueryAttr->stabledev       = pQueryMsg->stabledev;
  pQueryAttr->tsCompQuery     = pQueryMsg->tsCompQuery;
  pQueryAttr->simpleAgg       = pQueryMsg->simpleAgg;
  pQueryAttr->pointInterpQuery = pQueryMsg->pointInterpQuery;
  pQueryAttr->needReverseScan  = pQueryMsg->needReverseScan;
  pQueryAttr->vgId            = vgId;

H
Haojun Liao 已提交
6860 6861
  pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
  if (pQueryAttr->tableCols == NULL) {
6862
    goto _cleanup;
6863
  }
6864

H
Haojun Liao 已提交
6865 6866
  pQueryAttr->srcRowSize = 0;
  pQueryAttr->maxTableColumnWidth = 0;
H
hjxilinx 已提交
6867
  for (int16_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
6868
    pQueryAttr->tableCols[i] = pQueryMsg->tableCols[i];
6869
    pQueryAttr->tableCols[i].flist.filterInfo = tFilterInfoDup(pQueryMsg->tableCols[i].flist.filterInfo, pQueryAttr->tableCols[i].flist.numOfFilters);
6870

H
Haojun Liao 已提交
6871 6872 6873
    pQueryAttr->srcRowSize += pQueryAttr->tableCols[i].bytes;
    if (pQueryAttr->maxTableColumnWidth < pQueryAttr->tableCols[i].bytes) {
      pQueryAttr->maxTableColumnWidth = pQueryAttr->tableCols[i].bytes;
6874
    }
H
hjxilinx 已提交
6875
  }
6876

6877
  // calculate the result row size
6878
  for (int16_t col = 0; col < numOfOutput; ++col) {
H
Haojun Liao 已提交
6879
    assert(pExprs[col].base.resBytes > 0);
H
Haojun Liao 已提交
6880
    pQueryAttr->resultRowSize += pExprs[col].base.resBytes;
6881 6882 6883

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
H
Haojun Liao 已提交
6884
      pQueryAttr->tagLen += pExprs[col].base.resBytes;
6885
    }
D
dapan1121 已提交
6886

6887
    if (pExprs[col].base.flist.filterInfo) {
H
Haojun Liao 已提交
6888
      ++pQueryAttr->havingNum;
D
dapan1121 已提交
6889
    }
6890
  }
6891

H
Haojun Liao 已提交
6892
  doUpdateExprColumnIndex(pQueryAttr);
H
Haojun Liao 已提交
6893
  int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId);
6894
  if (ret != TSDB_CODE_SUCCESS) {
6895
    goto _cleanup;
6896 6897
  }

H
Haojun Liao 已提交
6898 6899 6900
  if (pQueryAttr->fillType != TSDB_FILL_NONE) {
    pQueryAttr->fillVal = malloc(sizeof(int64_t) * pQueryAttr->numOfOutput);
    if (pQueryAttr->fillVal == NULL) {
6901
      goto _cleanup;
6902 6903 6904
    }

    // the first column is the timestamp
H
Haojun Liao 已提交
6905
    memcpy(pQueryAttr->fillVal, (char *)pQueryMsg->fillVal, pQueryAttr->numOfOutput * sizeof(int64_t));
6906 6907
  }

dengyihao's avatar
dengyihao 已提交
6908 6909 6910
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6911
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6912

6913 6914 6915
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6916
  }
H
Haojun Liao 已提交
6917

H
Haojun Liao 已提交
6918
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6919 6920 6921 6922
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6923
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6924
  pQInfo->rspContext = NULL;
6925
  pQInfo->sql = sql;
6926
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6927
  tsem_init(&pQInfo->ready, 0, 0);
6928

H
Haojun Liao 已提交
6929 6930
  pQueryAttr->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, pQueryAttr->stableQuery);
6931

H
Haojun Liao 已提交
6932
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6933
  STimeWindow window = pQueryAttr->window;
H
Haojun Liao 已提交
6934

H
Haojun Liao 已提交
6935
  int32_t index = 0;
H
hjxilinx 已提交
6936
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6937
    SArray* pa = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
6938

H
Haojun Liao 已提交
6939
    size_t s = taosArrayGetSize(pa);
6940
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6941 6942 6943
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6944

H
Haojun Liao 已提交
6945
    taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1);
6946

H
hjxilinx 已提交
6947
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6948
      STableKeyInfo* info = taosArrayGet(pa, j);
6949
      window.skey = info->lastKey;
6950 6951

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
H
Haojun Liao 已提交
6952
      STableQueryInfo* item = createTableQueryInfo(pQueryAttr, info->pTable, pQueryAttr->groupbyColumn, window, buf);
B
Bomin Zhang 已提交
6953 6954 6955
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6956

6957
      item->groupIndex = i;
H
hjxilinx 已提交
6958
      taosArrayPush(p1, &item);
6959 6960

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6961
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6962
      index += 1;
H
hjxilinx 已提交
6963 6964
    }
  }
6965

H
Haojun Liao 已提交
6966
  colIdCheck(pQueryAttr, pQInfo->qId);
6967

6968
  // todo refactor
H
Haojun Liao 已提交
6969
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6970

H
Haojun Liao 已提交
6971
  qDebug("qmsg:%p QInfo:0x%" PRIx64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6972 6973
  return pQInfo;

B
Bomin Zhang 已提交
6974
_cleanup_qinfo:
H
Haojun Liao 已提交
6975
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6976

6977 6978 6979 6980
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6981

S
TD-1848  
Shengliang Guan 已提交
6982
  tfree(pTagCols);
B
Bomin Zhang 已提交
6983 6984 6985
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6986 6987
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6988
    }
D
dapan1121 已提交
6989

6990 6991
    if (pExprInfo->base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo->base.flist.filterInfo, pExprInfo->base.flist.numOfFilters);
D
dapan1121 已提交
6992
    }
B
Bomin Zhang 已提交
6993
  }
H
Haojun Liao 已提交
6994

S
TD-1848  
Shengliang Guan 已提交
6995
  tfree(pExprs);
B
Bomin Zhang 已提交
6996

6997
_cleanup:
dengyihao's avatar
dengyihao 已提交
6998
  freeQInfo(pQInfo);
6999 7000 7001
  return NULL;
}

H
Haojun Liao 已提交
7002
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
7003 7004 7005 7006
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
7007

H
hjxilinx 已提交
7008 7009 7010 7011
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
7012
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
7013 7014 7015
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
7016
int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start,
H
Haojun Liao 已提交
7017
                  int32_t prevResultLen, void* merger) {
H
hjxilinx 已提交
7018
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
7019 7020

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
7021 7022
  pRuntimeEnv->qinfo = pQInfo;

H
Haojun Liao 已提交
7023
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
7024

7025
  STSBuf *pTsBuf = NULL;
H
Haojun Liao 已提交
7026 7027
  if (pTsBufInfo->tsLen > 0) { // open new file to save the result
    char *tsBlock = start + pTsBufInfo->tsOffset;
H
Haojun Liao 已提交
7028
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pTsBufInfo->tsNumOfBlocks, pTsBufInfo->tsLen, pTsBufInfo->tsOrder,
H
Haojun Liao 已提交
7029
        pQueryAttr->vgId);
7030

7031 7032
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
dengyihao's avatar
dengyihao 已提交
7033
    UNUSED(ret);
H
hjxilinx 已提交
7034
  }
7035

7036
  SArray* prevResult = NULL;
H
Haojun Liao 已提交
7037 7038
  if (prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, prevResultLen);
7039 7040
  }

H
Haojun Liao 已提交
7041
  if (tsdb != NULL) {
H
Haojun Liao 已提交
7042
    pQueryAttr->precision = tsdbGetCfg(tsdb)->precision;
H
Haojun Liao 已提交
7043
  }
7044

H
Haojun Liao 已提交
7045 7046
  if ((QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.skey > pQueryAttr->window.ekey)) ||
      (!QUERY_IS_ASC_QUERY(pQueryAttr) && (pQueryAttr->window.ekey > pQueryAttr->window.skey))) {
H
Haojun Liao 已提交
7047
    qDebug("QInfo:0x%"PRIx64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQueryAttr->window.skey,
H
Haojun Liao 已提交
7048
           pQueryAttr->window.ekey, pQueryAttr->order.order);
H
Haojun Liao 已提交
7049
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
7050
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
7051
    // todo free memory
7052 7053
    return TSDB_CODE_SUCCESS;
  }
7054

H
Haojun Liao 已提交
7055
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
7056
    qDebug("QInfo:0x%"PRIx64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
7057
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
7058 7059
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
7060 7061

  // filter the qualified
H
Haojun Liao 已提交
7062
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, sourceOptr, param->tableScanOperator, param->pOperator, merger)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
7063 7064
    goto _error;
  }
7065

H
hjxilinx 已提交
7066 7067 7068 7069
  return code;

_error:
  // table query ref will be decrease during error handling
7070
  freeQInfo(pQInfo);
H
hjxilinx 已提交
7071 7072 7073
  return code;
}

7074
//TODO refactor
H
Haojun Liao 已提交
7075
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
7076
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
7077 7078
      return;
    }
H
Haojun Liao 已提交
7079

B
Bomin Zhang 已提交
7080
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
7081
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
7082 7083 7084
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
7085

B
Bomin Zhang 已提交
7086 7087 7088
    free(pFilter);
}

H
Haojun Liao 已提交
7089 7090
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
7091
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112
    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 已提交
7113 7114 7115 7116 7117 7118 7119 7120
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 已提交
7121
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
7122
    }
D
dapan1121 已提交
7123

7124 7125
    if (pExprInfo[i].base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo[i].base.flist.filterInfo, pExprInfo[i].base.flist.numOfFilters);
D
dapan1121 已提交
7126
    }
H
Haojun Liao 已提交
7127 7128 7129 7130

    for(int32_t j = 0; j < pExprInfo[i].base.numOfParams; ++j) {
      tVariantDestroy(&pExprInfo[i].base.param[j]);
    }
H
Haojun Liao 已提交
7131 7132 7133 7134 7135 7136
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
7137
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
7138 7139 7140
  if (!isValidQInfo(pQInfo)) {
    return;
  }
7141

H
Haojun Liao 已提交
7142
  qDebug("QInfo:0x%"PRIx64" start to free QInfo", pQInfo->qId);
7143

H
Haojun Liao 已提交
7144
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7145
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
7146 7147

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
7148
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
7149

H
Haojun Liao 已提交
7150
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
7151
  freeQueryAttr(pQueryAttr);
7152

7153 7154
  tsdbDestroyTableGroup(&pQueryAttr->tableGroupInfo);

S
TD-1848  
Shengliang Guan 已提交
7155
  tfree(pQInfo->pBuf);
7156 7157
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
7158
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
7159
  pQInfo->signature = 0;
7160

H
Haojun Liao 已提交
7161
  qDebug("QInfo:0x%"PRIx64" QInfo is freed", pQInfo->qId);
7162

S
TD-1848  
Shengliang Guan 已提交
7163
  tfree(pQInfo);
H
hjxilinx 已提交
7164 7165
}

H
Haojun Liao 已提交
7166
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
7167
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
7168
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7169
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
7170

H
hjxilinx 已提交
7171
  // load data from file to msg buffer
H
Haojun Liao 已提交
7172
  if (pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
7173 7174
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
7175

H
hjxilinx 已提交
7176
    // make sure file exist
D
fix bug  
dapan1121 已提交
7177 7178
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
7179
      assert(s == pRuntimeEnv->outputBuf->info.rows);
7180

H
Haojun Liao 已提交
7181
      qDebug("QInfo:0x%"PRIx64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
7182 7183
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
7184
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
7185
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
7186 7187
          assert(0);
        }
H
Haojun Liao 已提交
7188
      } else {
7189
        UNUSED(s);
D
dapan1121 已提交
7190 7191 7192 7193
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
7194
      // dump error info
D
dapan1121 已提交
7195 7196 7197
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
7198
      }
H
Haojun Liao 已提交
7199

D
fix bug  
dapan1121 已提交
7200
      fclose(f);
D
dapan1121 已提交
7201
      *(FILE **)pColInfoData->pData = NULL;
H
hjxilinx 已提交
7202
    }
7203

H
hjxilinx 已提交
7204
    // all data returned, set query over
H
Haojun Liao 已提交
7205 7206
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
7207
    }
H
hjxilinx 已提交
7208
  } else {
H
Haojun Liao 已提交
7209
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
7210
  }
7211

H
Haojun Liao 已提交
7212
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
7213
  qDebug("QInfo:0x%"PRIx64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
7214
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
7215

H
Haojun Liao 已提交
7216
  if (pQueryAttr->limit.limit > 0 && pQueryAttr->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
7217
    qDebug("QInfo:0x%"PRIx64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQueryAttr->limit.limit);
H
Haojun Liao 已提交
7218
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
7219
  }
7220

H
hjxilinx 已提交
7221
  return TSDB_CODE_SUCCESS;
7222 7223
}

H
Haojun Liao 已提交
7224
bool doBuildResCheck(SQInfo* pQInfo) {
7225 7226 7227 7228 7229
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
7230
  buildRes = needBuildResAfterQueryComplete(pQInfo);
7231

H
Haojun Liao 已提交
7232 7233
  // 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 已提交
7234
  assert(pQInfo->owner == taosGetSelfPthreadId());
7235
  pQInfo->owner = 0;
H
Haojun Liao 已提交
7236

H
Haojun Liao 已提交
7237
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
7238

7239
  // used in retrieve blocking model.
H
Haojun Liao 已提交
7240
  tsem_post(&pQInfo->ready);
7241 7242 7243
  return buildRes;
}

H
Haojun Liao 已提交
7244 7245 7246 7247
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
7248 7249
  }

7250 7251 7252
  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 已提交
7253
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
7254 7255 7256 7257 7258
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
7259
  } else {
H
Haojun Liao 已提交
7260
    memcpy(output, val, bytes);
7261 7262 7263
  }
}

H
Haojun Liao 已提交
7264
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
7265 7266 7267 7268
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
7269
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
7270 7271
}

H
Haojun Liao 已提交
7272
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
7273
  int64_t t = getQuerySupportBufSize(numOfTables);
7274
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7275
    return TSDB_CODE_SUCCESS;
7276
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
7277 7278

    while(1) {
7279
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
7280 7281
      int64_t remain = s - t;
      if (remain >= 0) {
7282
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294
          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 已提交
7295
void releaseQueryBuf(size_t numOfTables) {
7296
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7297 7298 7299 7300 7301 7302
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
7303
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
7304
}
7305 7306 7307 7308 7309 7310 7311

void freeQueryAttr(SQueryAttr* pQueryAttr) {
  if (pQueryAttr != NULL) {
    if (pQueryAttr->fillVal != NULL) {
      tfree(pQueryAttr->fillVal);
    }

H
Haojun Liao 已提交
7312
    pQueryAttr->pFilterInfo = doDestroyFilterInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols);
7313 7314 7315

    pQueryAttr->pExpr1 = destroyQueryFuncExpr(pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
    pQueryAttr->pExpr2 = destroyQueryFuncExpr(pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
H
Haojun Liao 已提交
7316
    pQueryAttr->pExpr3 = destroyQueryFuncExpr(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
7317 7318 7319 7320

    tfree(pQueryAttr->tagColList);
    tfree(pQueryAttr->pFilterInfo);

H
Haojun Liao 已提交
7321
    if (pQueryAttr->tableCols != NULL) {
7322
      for (int32_t i = 0; i < pQueryAttr->numOfCols; i++) {
H
Haojun Liao 已提交
7323
        SColumnInfo* column = pQueryAttr->tableCols + i;
7324
        freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters);
7325
      }
H
Haojun Liao 已提交
7326
      tfree(pQueryAttr->tableCols);
7327 7328 7329 7330 7331 7332 7333 7334 7335
    }

    if (pQueryAttr->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo);
      tfree(pQueryAttr->pGroupbyExpr);
    }
  }
}