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

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

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

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

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

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

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

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

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

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

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

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

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

D
fix bug  
dapan1121 已提交
94 95
uint64_t queryHandleId = 0;

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

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

D
dapan1121 已提交
104
  uid = did << 54;
H
Haojun Liao 已提交
105

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

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

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

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

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

  uid |= sid;

  return uid;
}

H
Haojun Liao 已提交
121 122 123 124 125
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;
126 127 128
    return;
  }

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

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

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

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

H
Haojun Liao 已提交
151
  if (pQueryAttr->precision == TSDB_TIME_PRECISION_MICRO) {
152 153 154 155 156 157
    tw->skey *= 1000L;
    tw->ekey *= 1000L;
  }
  tw->ekey -= 1;
}

H
Haojun Liao 已提交
158
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
H
Haojun Liao 已提交
159 160
static void setResultOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRow* pResult, SQLFunctionCtx* pCtx,
                               int32_t numOfCols, int32_t* rowCellInfoOffset);
H
Haojun Liao 已提交
161

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

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

H
Haojun Liao 已提交
167
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
H
Haojun Liao 已提交
168
static bool hasMainOutput(SQueryAttr *pQueryAttr);
169

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

H
Haojun Liao 已提交
176
static void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream);
177 178 179
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 已提交
180

H
Haojun Liao 已提交
181
static int32_t getNumOfScanTimes(SQueryAttr* pQueryAttr);
H
Haojun Liao 已提交
182

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

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

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

H
Haojun Liao 已提交
195
static void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size);
H
Haojun Liao 已提交
196 197
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 已提交
198 199
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 已提交
200
static void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput, SExprInfo* pExpr, char* val, int16_t bytes);
201 202 203
static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo,
                                     SQLFunctionCtx* pCtx, int32_t* rowCellInfoOffset, int32_t numOfOutput,
                                     int32_t groupIndex);
H
Haojun Liao 已提交
204

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

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

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

H
Haojun Liao 已提交
219 220
    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 已提交
221 222
    taosArrayPush(res->pDataBlock, &idata);
  }
H
Haojun Liao 已提交
223 224

  return res;
H
Haojun Liao 已提交
225 226
}

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

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

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

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

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

  return true;
}

H
Haojun Liao 已提交
307 308 309 310 311 312 313 314 315 316 317 318
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;
}

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

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

374
  if (!existed) {
375
    prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
376

377 378 379 380 381 382 383 384 385 386 387 388
    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;
389
    }
H
Haojun Liao 已提交
390

391
    pResultRowInfo->pResult[pResultRowInfo->size] = pResult;
H
Haojun Liao 已提交
392
    pResultRowInfo->curIndex = pResultRowInfo->size++;
393
  }
394

395
  // too many time window in query
H
Haojun Liao 已提交
396
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
397 398 399
    longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
400
  return getResultRow(pResultRowInfo, pResultRowInfo->curIndex);
401 402
}

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

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

      if (key >= ts) {
        break;
      }

      w->skey = key;
    }
  }
}

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

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

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

450
  if (w.skey > ts || w.ekey < ts) {
H
Haojun Liao 已提交
451 452 453
    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;
454 455
    } else {
      int64_t st = w.skey;
456

457
      if (st > ts) {
H
Haojun Liao 已提交
458
        st -= ((st - ts + pQueryAttr->interval.sliding - 1) / pQueryAttr->interval.sliding) * pQueryAttr->interval.sliding;
459
      }
460

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

466
      w.skey = st;
H
Haojun Liao 已提交
467
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
468
    }
469
  }
470

471 472 473 474
  /*
   * 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 已提交
475 476
  if (w.ekey > pQueryAttr->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
    w.ekey = pQueryAttr->window.ekey;
477
  }
478

479 480 481
  return w;
}

H
Haojun Liao 已提交
482 483
// 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) {
484
  if (pWindowRes->pageId != -1) {
485 486
    return 0;
  }
487

488
  tFilePage *pData = NULL;
489

490 491
  // in the first scan, new space needed for results
  int32_t pageId = -1;
H
Haojun Liao 已提交
492
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);
493

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

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

511 512 513
  if (pData == NULL) {
    return -1;
  }
514

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

H
Haojun Liao 已提交
520
    pData->num += size;
521
    assert(pWindowRes->pageId >= 0);
522
  }
523

524 525 526
  return 0;
}

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

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

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

547
  // set time window for current result
H
Haojun Liao 已提交
548
  pResultRow->win = (*win);
549
  *pResult = pResultRow;
H
Haojun Liao 已提交
550
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
551

552 553 554
  return TSDB_CODE_SUCCESS;
}

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

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

H
Haojun Liao 已提交
582 583 584 585 586 587 588 589 590 591 592 593
      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;
      }
594 595
    }
  }
596

H
Haojun Liao 已提交
597
  assert(forwardStep > 0);
598 599 600
  return forwardStep;
}

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

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

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

635 636 637 638 639
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
      SResultRow *pResult = pResultRowInfo->pResult[i];
      if (pResult->closed) {
        break;
      }
640
    }
641

D
fix bug  
dapan1121 已提交
642
    if (i == pResultRowInfo->size - 1) {
643
      pResultRowInfo->curIndex = i;
D
fix bug  
dapan1121 已提交
644 645 646 647
    } else {
      pResultRowInfo->curIndex = i + 1;  // current not closed result object
    }

648
    pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->curIndex]->win.skey;
649
  }
650
}
651

H
Haojun Liao 已提交
652 653 654
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))) {
655 656 657
    closeAllResultRows(pResultRowInfo);
    pResultRowInfo->curIndex = pResultRowInfo->size - 1;
  } else {
H
Haojun Liao 已提交
658
    int32_t step = ascQuery ? 1 : -1;
H
Haojun Liao 已提交
659
    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, pQueryAttr->timeWindowInterpo);
660
  }
661 662
}

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

H
Haojun Liao 已提交
669
  int32_t num   = -1;
H
Haojun Liao 已提交
670
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
671
  int32_t step  = GET_FORWARD_DIRECTION_FACTOR(order);
672

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

H
Haojun Liao 已提交
699
  assert(num > 0);
700 701 702
  return num;
}

H
Haojun Liao 已提交
703 704
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 已提交
705
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
706 707
  bool hasPrev = pCtx[0].preAggVals.isSet;

708
  for (int32_t k = 0; k < numOfOutput; ++k) {
709
    pCtx[k].size = forwardStep;
H
Haojun Liao 已提交
710
    pCtx[k].startTs = pWin->skey;
H
Haojun Liao 已提交
711

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

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

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

H
Haojun Liao 已提交
723
    int32_t functionId = pCtx[k].functionId;
H
Haojun Liao 已提交
724

725 726 727 728 729
    // 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 已提交
730

731 732
    if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
      aAggs[functionId].xFunction(&pCtx[k]);
733
    }
734 735 736

    // restore it
    pCtx[k].preAggVals.isSet = hasPrev;
737
    pCtx[k].pInput = start;
738 739 740 741
  }
}


H
Haojun Liao 已提交
742
static int32_t getNextQualifiedWindow(SQueryAttr* pQueryAttr, STimeWindow *pNext, SDataBlockInfo *pDataBlockInfo,
H
Haojun Liao 已提交
743
    TSKEY *primaryKeys, __block_search_fn_t searchFn, int32_t prevPosition) {
H
Haojun Liao 已提交
744
  getNextTimeWindow(pQueryAttr, pNext);
745

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

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

H
Haojun Liao 已提交
765
  int32_t startPos = 0;
H
Haojun Liao 已提交
766

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

H
Haojun Liao 已提交
781 782 783 784
  /*
   * 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 已提交
785
  if (primaryKeys == NULL) {
H
Haojun Liao 已提交
786
    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
787
      assert(pDataBlockInfo->window.skey <= pNext->ekey);
788
    } else {
H
Haojun Liao 已提交
789
      assert(pDataBlockInfo->window.ekey >= pNext->skey);
790
    }
H
Haojun Liao 已提交
791
  } else {
H
Haojun Liao 已提交
792
    if (QUERY_IS_ASC_QUERY(pQueryAttr) && primaryKeys[startPos] > pNext->ekey) {
H
Haojun Liao 已提交
793
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
794 795 796
      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 已提交
797
      } else {
H
Haojun Liao 已提交
798 799
        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 已提交
800
      }
H
Haojun Liao 已提交
801
    } else if ((!QUERY_IS_ASC_QUERY(pQueryAttr)) && primaryKeys[startPos] < pNext->skey) {
H
Haojun Liao 已提交
802
      TSKEY next = primaryKeys[startPos];
H
Haojun Liao 已提交
803 804 805
      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 已提交
806
      } else {
H
Haojun Liao 已提交
807 808
        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 已提交
809
      }
810
    }
811
  }
812

H
Haojun Liao 已提交
813
  return startPos;
814 815
}

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

830 831 832
  return ekey;
}

H
Haojun Liao 已提交
833 834 835 836 837 838 839 840 841 842 843 844
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;
    }
  }
}

845
// window start key interpolation
H
Haojun Liao 已提交
846

847

H
Haojun Liao 已提交
848
static void saveDataBlockLastRow(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pDataBlockInfo, SArray* pDataBlock,
849
    int32_t rowIndex) {
850 851 852 853
  if (pDataBlock == NULL) {
    return;
  }

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

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

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

  return ts;
}

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

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

H
Haojun Liao 已提交
901 902 903 904
    setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo);
  }
}

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

    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 已提交
934 935
      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 已提交
936 937
        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
H
Haojun Liao 已提交
938

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

H
Haojun Liao 已提交
943
        uint32_t status = aAggs[pCtx[i].functionId].status;
H
Haojun Liao 已提交
944
        if ((status & (TSDB_FUNCSTATE_SELECTIVITY | TSDB_FUNCSTATE_NEED_TS)) != 0) {
H
Haojun Liao 已提交
945
          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
H
Haojun Liao 已提交
946
          pCtx[i].ptsList = (int64_t*) tsInfo->pData;
H
Haojun Liao 已提交
947
        }
H
Haojun Liao 已提交
948 949 950 951 952 953 954 955 956 957
      } 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 已提交
958 959 960 961 962
      }
    }
  }
}

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

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

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

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

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

986
    aAggs[pCtx[k].functionId].xFunction(&pCtx[k]);
H
Haojun Liao 已提交
987 988 989
  }
}

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

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

H
Haojun Liao 已提交
1050
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1051

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

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

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

H
Haojun Liao 已提交
1071 1072
  doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos,
      key, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1073 1074 1075 1076
  return true;
}

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

  TSKEY   actualEndKey = tsCols[endRowIndex];

H
Haojun Liao 已提交
1084
  TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? win->ekey:win->skey;
H
Haojun Liao 已提交
1085 1086

  // not ended in current data block, do not invoke interpolation
H
Haojun Liao 已提交
1087
  if ((key > blockEkey && QUERY_IS_ASC_QUERY(pQueryAttr)) || (key < blockEkey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
H
Haojun Liao 已提交
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
    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 已提交
1098
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1099 1100 1101 1102
  int32_t nextRowIndex = endRowIndex + step;
  assert(nextRowIndex >= 0);

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

  assert(pBlock != NULL);
H
Haojun Liao 已提交
1117
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
H
Haojun Liao 已提交
1118 1119 1120 1121 1122 1123 1124 1125

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

  // point interpolation does not require the end key time window interpolation.
H
Haojun Liao 已提交
1135
  if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
1136 1137 1138 1139 1140 1141 1142 1143
    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 已提交
1144
    TSKEY endKey = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey:pBlock->info.window.skey;
H
Haojun Liao 已提交
1145 1146 1147 1148 1149
    bool  interp = setTimeWindowInterpolationEndTs(pOperatorInfo, pCtx, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
    }
  } else {
H
Haojun Liao 已提交
1150
    setNotInterpoWindowKey(pCtx, pQueryAttr->numOfOutput, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1151 1152 1153
  }
}

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

H
Haojun Liao 已提交
1157 1158
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
  int32_t           numOfOutput = pOperatorInfo->numOfOutput;
H
Haojun Liao 已提交
1159
  SQueryAttr*           pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1160

H
Haojun Liao 已提交
1161 1162
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
1163

H
Haojun Liao 已提交
1164
  int32_t prevIndex = curTimeWindowIndex(pResultRowInfo);
H
Haojun Liao 已提交
1165

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

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

H
Haojun Liao 已提交
1177
  STimeWindow win = getActiveTimeWindow(pResultRowInfo, ts, pQueryAttr);
H
Haojun Liao 已提交
1178
  bool masterScan = IS_MASTER_SCAN(pRuntimeEnv);
H
Haojun Liao 已提交
1179

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

  int32_t forwardStep = 0;
H
Haojun Liao 已提交
1188
  TSKEY   ekey = reviseWindowEkey(pQueryAttr, &win);
H
Haojun Liao 已提交
1189
  forwardStep =
H
Haojun Liao 已提交
1190
      getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1191 1192

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

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

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

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

H
Haojun Liao 已提交
1215
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
H
Haojun Liao 已提交
1216
      setNotInterpoWindowKey(pInfo->pCtx, pQueryAttr->numOfOutput, RESULT_ROW_START_INTERP);
H
Haojun Liao 已提交
1217

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

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

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

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

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

H
Haojun Liao 已提交
1248
    ekey = reviseWindowEkey(pQueryAttr, &nextWin);
H
Haojun Liao 已提交
1249
    forwardStep = getNumOfRowsInTimeWindow(pRuntimeEnv, &pSDataBlock->info, tsCols, startPos, ekey, binarySearchForKey, true);
H
Haojun Liao 已提交
1250 1251

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

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

H
Haojun Liao 已提交
1261
  updateResultRowInfoActiveIndex(pResultRowInfo, pQueryAttr, pRuntimeEnv->current->lastKey);
H
Haojun Liao 已提交
1262 1263
}

H
Haojun Liao 已提交
1264 1265
static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) {
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
1266
  STableQueryInfo*  item = pRuntimeEnv->current;
H
Haojun Liao 已提交
1267

H
Haojun Liao 已提交
1268
  SColumnInfoData* pColInfoData = taosArrayGet(pSDataBlock->pDataBlock, pInfo->colIndex);
H
Haojun Liao 已提交
1269 1270 1271 1272

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

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

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

1285
    // Compare with the previous row of this column, and do not set the output buffer again if they are identical.
H
Haojun Liao 已提交
1286 1287 1288 1289 1290 1291 1292
    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 已提交
1293 1294 1295 1296
      if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
        setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, val, bytes);
      }

H
Haojun Liao 已提交
1297 1298 1299 1300 1301
      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 已提交
1302 1303
    }

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

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

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

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

H
Haojun Liao 已提交
1324
  int64_t gap = pOperator->pRuntimeEnv->pQueryAttr->sw.gap;
1325 1326 1327 1328 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
  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 已提交
1374
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
H
Haojun Liao 已提交
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
  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 已提交
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
}

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

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

H
Haojun Liao 已提交
1416 1417
  setResultOutputBuf(pRuntimeEnv, pResultRow, pCtx, numOfCols, rowCellInfoOffset);
  initCtxOutputBuffer(pCtx, numOfCols);
H
Haojun Liao 已提交
1418 1419
  return TSDB_CODE_SUCCESS;
}
1420

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

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

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

1451 1452 1453
  if (pResInfo->complete || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
    return false;
  }
1454

1455
  if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
H
Haojun Liao 已提交
1456
    return QUERY_IS_ASC_QUERY(pQueryAttr);
H
hjxilinx 已提交
1457
  }
1458

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

1464 1465 1466
  // 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)) {
1467 1468
    return false;
  }
1469

1470 1471 1472
  return true;
}

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

H
Haojun Liao 已提交
1476 1477 1478 1479
  if (pSDataBlock->pBlockStatis != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
    pStatis = &pSDataBlock->pBlockStatis[pColIndex->colIndex];

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

H
Haojun Liao 已提交
1486
  pCtx->hasNull = hasNullRv(pColIndex, pStatis);
H
Haojun Liao 已提交
1487 1488

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

H
Haojun Liao 已提交
1496 1497 1498 1499 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
// 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;
}
1537

H
Haojun Liao 已提交
1538
static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput,
H
Haojun Liao 已提交
1539
                                            int32_t** rowCellInfoOffset) {
H
Haojun Liao 已提交
1540
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1541

1542 1543
  SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
  if (pFuncCtx == NULL) {
H
Haojun Liao 已提交
1544
    return NULL;
1545 1546
  }

H
Haojun Liao 已提交
1547
  *rowCellInfoOffset = calloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1548 1549 1550 1551
  if (*rowCellInfoOffset == 0) {
    tfree(pFuncCtx);
    return NULL;
  }
H
Haojun Liao 已提交
1552

H
Haojun Liao 已提交
1553
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
1554
    SSqlExpr *pSqlExpr = &pExpr[i].base;
1555
    SQLFunctionCtx* pCtx = &pFuncCtx[i];
1556

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

Y
TD-1230  
yihaoDeng 已提交
1559
    if (TSDB_COL_REQ_NULL(pIndex->flag)) {
1560 1561
      pCtx->requireNull = true;
      pIndex->flag &= ~(TSDB_COL_NULL);
Y
TD-1230  
yihaoDeng 已提交
1562
    } else {
1563 1564
      pCtx->requireNull = false;
    }
Y
TD-1230  
yihaoDeng 已提交
1565

H
Haojun Liao 已提交
1566 1567
    pCtx->inputBytes = pSqlExpr->colBytes;
    pCtx->inputType  = pSqlExpr->colType;
H
Haojun Liao 已提交
1568

1569
    pCtx->ptsOutputBuf = NULL;
1570

H
Haojun Liao 已提交
1571 1572
    pCtx->outputBytes  = pSqlExpr->resBytes;
    pCtx->outputType   = pSqlExpr->resType;
1573

H
Haojun Liao 已提交
1574
    pCtx->order        = pQueryAttr->order.order;
H
Haojun Liao 已提交
1575
    pCtx->functionId   = pSqlExpr->functionId;
H
Haojun Liao 已提交
1576
    pCtx->stableQuery  = pQueryAttr->stableQuery;
H
Haojun Liao 已提交
1577
    pCtx->interBufBytes = pSqlExpr->interBytes;
1578 1579
    pCtx->start.key    = INT64_MIN;
    pCtx->end.key      = INT64_MIN;
1580

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

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

1596 1597
    // set the order information for top/bottom query
    int32_t functionId = pCtx->functionId;
1598

1599
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
H
Haojun Liao 已提交
1600
      int32_t f = pExpr[0].base.functionId;
1601
      assert(f == TSDB_FUNC_TS || f == TSDB_FUNC_TS_DUMMY);
1602

H
Haojun Liao 已提交
1603
      pCtx->param[2].i64 = pQueryAttr->order.order;
1604
      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
1605
      pCtx->param[3].i64 = functionId;
1606
      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
1607

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

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

H
Haojun Liao 已提交
1638 1639
  setCtxTagColumnInfo(pFuncCtx, numOfOutput);

1640
  return pFuncCtx;
H
Haojun Liao 已提交
1641 1642
}

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

  pRuntimeEnv->prevGroupId = INT32_MIN;
H
Haojun Liao 已提交
1666
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
1667 1668

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

H
Haojun Liao 已提交
1675 1676 1677
  // 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 已提交
1678
  pRuntimeEnv->sasArray = calloc(pQueryAttr->numOfOutput, sizeof(SArithmeticSupport));
H
Haojun Liao 已提交
1679

H
Haojun Liao 已提交
1680 1681
  if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL ||
      pRuntimeEnv->prevRow == NULL  || pRuntimeEnv->tagVal == NULL) {
H
Haojun Liao 已提交
1682 1683 1684
    goto _clean;
  }

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

H
Haojun Liao 已提交
1692 1693
    *(int64_t*) pRuntimeEnv->prevRow[0] = INT64_MIN;
  }
1694

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

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

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

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

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

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

H
Haojun Liao 已提交
1777 1778 1779 1780 1781 1782
      case OP_Fill: {
        SOperatorInfo* pInfo = pRuntimeEnv->proot;
        pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput);
        break;
      }

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

H
Haojun Liao 已提交
1793
      case OP_GlobalAggregate: {
1794 1795
        pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
                                                               pQueryAttr->numOfExpr3, merger);
H
Haojun Liao 已提交
1796 1797 1798 1799
        break;
      }

      case OP_SLimit: {
H
Haojun Liao 已提交
1800
        pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3,
1801 1802 1803 1804 1805 1806
                                                      pQueryAttr->numOfExpr3, merger);
        break;
      }

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

H
Haojun Liao 已提交
1810 1811
      default: {
        assert(0);
H
Haojun Liao 已提交
1812
      }
H
Haojun Liao 已提交
1813
    }
H
Haojun Liao 已提交
1814
  }
H
Haojun Liao 已提交
1815

H
Haojun Liao 已提交
1816
  return TSDB_CODE_SUCCESS;
1817

1818
_clean:
1819
  tfree(pRuntimeEnv->sasArray);
H
Haojun Liao 已提交
1820 1821 1822 1823
  tfree(pRuntimeEnv->pResultRowHashTable);
  tfree(pRuntimeEnv->keyBuf);
  tfree(pRuntimeEnv->prevRow);
  tfree(pRuntimeEnv->tagVal);
1824

1825
  return TSDB_CODE_QRY_OUT_OF_MEMORY;
1826 1827
}

H
Haojun Liao 已提交
1828
static void doFreeQueryHandle(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
1829
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
1830 1831 1832 1833

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

H
Haojun Liao 已提交
1834
  SMemRef* pMemRef = &pQueryAttr->memRef;
1835
  assert(pMemRef->ref == 0 && pMemRef->snapshot.imem == NULL && pMemRef->snapshot.mem == NULL);
H
Haojun Liao 已提交
1836 1837
}

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

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

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

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

    tfree(pRuntimeEnv->sasArray);
  }

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

H
Haojun Liao 已提交
1869 1870
  destroyTsComp(pRuntimeEnv, pQueryAttr);

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

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

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

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

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

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

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

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

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

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

  return false;
}

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

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

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

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

1960 1961 1962 1963 1964
    if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
        functionId == TSDB_FUNC_AVG_IRATE) {
      return true;
    }
  }
1965

1966 1967 1968
  return false;
}

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

1977 1978 1979
  return false;
}

H
Haojun Liao 已提交
1980 1981 1982 1983
/**
 * 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 已提交
1984 1985 1986
bool onlyQueryTags(SQueryAttr* pQueryAttr) {
  for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pQueryAttr->pExpr1[i];
H
Haojun Liao 已提交
1987 1988

    int32_t functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
1989 1990 1991 1992

    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 已提交
1993
        (!(functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) {
H
hjxilinx 已提交
1994 1995 1996
      return false;
    }
  }
1997

H
hjxilinx 已提交
1998 1999 2000
  return true;
}

2001 2002
/////////////////////////////////////////////////////////////////////////////////////////////

H
Haojun Liao 已提交
2003 2004 2005
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 已提交
2006 2007

  /*
H
Haojun Liao 已提交
2008
   * if the realSkey > INT64_MAX - pQueryAttr->interval.interval, the query duration between
H
Haojun Liao 已提交
2009 2010
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
H
Haojun Liao 已提交
2011 2012
  if (keyFirst > (INT64_MAX - pQueryAttr->interval.interval)) {
    assert(keyLast - keyFirst < pQueryAttr->interval.interval);
2013
    win->ekey = INT64_MAX;
H
Haojun Liao 已提交
2014 2015
  } 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 已提交
2016
  } else {
H
Haojun Liao 已提交
2017
    win->ekey = win->skey + pQueryAttr->interval.interval - 1;
2018 2019 2020 2021 2022 2023
  }
}

/*
 * todo add more parameters to check soon..
 */
H
Haojun Liao 已提交
2024
bool colIdCheck(SQueryAttr *pQueryAttr, uint64_t qId) {
2025
  // load data column information is incorrect
H
Haojun Liao 已提交
2026
  for (int32_t i = 0; i < pQueryAttr->numOfCols - 1; ++i) {
H
Haojun Liao 已提交
2027
    if (pQueryAttr->tableCols[i].colId == pQueryAttr->tableCols[i + 1].colId) {
H
Haojun Liao 已提交
2028
      qError("QInfo:0x%"PRIx64" invalid data load column for query", qId);
2029 2030 2031
      return false;
    }
  }
2032

2033 2034 2035 2036 2037
  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 已提交
2038 2039 2040
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;
2041

2042 2043 2044 2045
    if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG ||
        functionId == TSDB_FUNC_TAG_DUMMY) {
      continue;
    }
2046

2047 2048 2049 2050
    if (functionId != functId && functionId != functIdDst) {
      return false;
    }
  }
2051

2052 2053 2054
  return true;
}

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

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

H
Haojun Liao 已提交
2059
static int32_t updateBlockLoadStatus(SQueryAttr *pQuery, int32_t status) {
H
Haojun Liao 已提交
2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
  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;
}

2093
static void doExchangeTimeWindow(SQInfo* pQInfo, STimeWindow* win) {
H
Haojun Liao 已提交
2094 2095
  SQueryAttr* pQueryAttr = &pQInfo->query;
  size_t t = taosArrayGetSize(pQueryAttr->tableGroupInfo.pGroupList);
H
Haojun Liao 已提交
2096
  for(int32_t i = 0; i < t; ++i) {
H
Haojun Liao 已提交
2097
    SArray* p1 = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2098 2099 2100

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

2103 2104 2105 2106
      // 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 已提交
2107 2108 2109 2110
    }
  }
}

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

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

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

H
Haojun Liao 已提交
2123 2124 2125
    pQueryAttr->order.order = TSDB_ORDER_ASC;
    if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
      SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
2126
    }
2127

2128 2129
    return;
  }
2130

H
Haojun Liao 已提交
2131 2132 2133 2134
  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 已提交
2135
    }
H
Haojun Liao 已提交
2136

H
Haojun Liao 已提交
2137
    doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
H
Haojun Liao 已提交
2138 2139 2140
    return;
  }

H
Haojun Liao 已提交
2141 2142 2143 2144
  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 已提交
2145
    }
2146

H
Haojun Liao 已提交
2147
    pQueryAttr->order.order = TSDB_ORDER_ASC;
2148 2149
    return;
  }
2150

H
Haojun Liao 已提交
2151 2152 2153 2154 2155
  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);
2156

H
Haojun Liao 已提交
2157 2158
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2159
      }
2160

H
Haojun Liao 已提交
2161 2162 2163 2164 2165
      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);
2166

H
Haojun Liao 已提交
2167 2168
        SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
        doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2169
      }
2170

H
Haojun Liao 已提交
2171
      pQueryAttr->order.order = TSDB_ORDER_DESC;
2172
    }
2173

2174
  } else {  // interval query
2175
    if (stableQuery) {
H
Haojun Liao 已提交
2176 2177 2178 2179
      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);
2180

H
Haojun Liao 已提交
2181 2182
          SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
          doExchangeTimeWindow(pQInfo, &pQueryAttr->window);
2183
        }
2184

H
Haojun Liao 已提交
2185 2186 2187 2188 2189
        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);
2190

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

H
Haojun Liao 已提交
2195
        pQueryAttr->order.order = TSDB_ORDER_DESC;
2196 2197 2198 2199 2200
      }
    }
  }
}

2201
static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
H
Haojun Liao 已提交
2202
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2203
  int32_t MIN_ROWS_PER_PAGE = 4;
2204

H
Haojun Liao 已提交
2205
  *rowsize = (int32_t)(pQueryAttr->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
2206 2207 2208 2209
  int32_t overhead = sizeof(tFilePage);

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

H
Haojun Liao 已提交
2214 2215
//  pRuntimeEnv->numOfRowsPerPage = ((*ps) - sizeof(tFilePage)) / (*rowsize);
//  assert(pRuntimeEnv->numOfRowsPerPage <= MAX_ROWS_PER_RESBUF_PAGE);
2216 2217
}

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

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

H
Haojun Liao 已提交
2223
  if (pDataStatis == NULL || pQueryAttr->numOfFilterCols == 0) {
2224 2225 2226
    return true;
  }

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

H
Haojun Liao 已提交
2230
    int32_t index = -1;
H
Haojun Liao 已提交
2231
    for(int32_t i = 0; i < pQueryAttr->numOfCols; ++i) {
H
Haojun Liao 已提交
2232 2233 2234 2235 2236 2237
      if (pDataStatis[i].colId == pFilterInfo->info.colId) {
        index = i;
        break;
      }
    }

2238
    // no statistics data, load the true data block
H
Haojun Liao 已提交
2239
    if (index == -1) {
H
Haojun Liao 已提交
2240
      return true;
2241
    }
2242

2243
    // not support pre-filter operation on binary/nchar data type
H
Haojun Liao 已提交
2244
    if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) {
H
Haojun Liao 已提交
2245
      return true;
2246
    }
2247

2248
    // all data in current column are NULL, no need to check its boundary value
H
Haojun Liao 已提交
2249
    if (pDataStatis[index].numOfNull == numOfRows) {
2250 2251 2252 2253

      // if isNULL query exists, load the null data column
      for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) {
        SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j];
2254
        if (pFilterElem->fp == isNullOperator) {
2255 2256 2257 2258
          return true;
        }
      }

2259 2260
      continue;
    }
2261

H
Haojun Liao 已提交
2262 2263 2264
    SDataStatis* pDataBlockst = &pDataStatis[index];

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

2268
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2269
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT)) {
2270 2271 2272 2273 2274
          return true;
        }
      }
    } else {
      for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
2275
        if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type)) {
2276 2277 2278 2279 2280
          return true;
        }
      }
    }
  }
2281

H
Haojun Liao 已提交
2282
  return false;
2283 2284
}

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

H
Haojun Liao 已提交
2288 2289
  TSKEY sk = MIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
  TSKEY ek = MAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
2290

H
Haojun Liao 已提交
2291 2292
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.skey, sk, ek, &w);
H
Haojun Liao 已提交
2293
    assert(w.ekey >= pBlockInfo->window.skey);
H
Haojun Liao 已提交
2294

H
Haojun Liao 已提交
2295
    if (w.ekey < pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2296 2297 2298 2299
      return true;
    }

    while(1) {
H
Haojun Liao 已提交
2300
      getNextTimeWindow(pQueryAttr, &w);
H
Haojun Liao 已提交
2301
      if (w.skey > pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
2302 2303 2304
        break;
      }

H
Haojun Liao 已提交
2305 2306
      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2307 2308 2309 2310
        return true;
      }
    }
  } else {
H
Haojun Liao 已提交
2311
    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.ekey, sk, ek, &w);
H
Haojun Liao 已提交
2312 2313 2314
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
H
Haojun Liao 已提交
2315 2316 2317 2318
      return true;
    }

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

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

  return false;
}

H
Haojun Liao 已提交
2334 2335 2336 2337 2338
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 已提交
2339
         elem.ts, key, elem.tag.i64, pQueryAttr->order.order, pRuntimeEnv->pTsBuf->tsOrder,
H
Haojun Liao 已提交
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358
         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;
}
2359

H
Haojun Liao 已提交
2360
void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols,
2361
                           SSDataBlock* pBlock, bool ascQuery) {
H
Haojun Liao 已提交
2362 2363 2364 2365 2366
  int32_t numOfRows = pBlock->info.rows;

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

H
Haojun Liao 已提交
2367
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
    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 已提交
2388 2389

    // save the cursor status
H
Haojun Liao 已提交
2390
    pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf);
H
Haojun Liao 已提交
2391 2392 2393
  } else {
    for (int32_t i = 0; i < numOfRows; ++i) {
      bool qualified = false;
H
Haojun Liao 已提交
2394

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

H
Haojun Liao 已提交
2398 2399 2400
        qualified = false;
        for (int32_t j = 0; j < pFilterInfo[k].numOfFilters; ++j) {
          SColumnFilterElem* pFilterElem = &pFilterInfo[k].pFilters[j];
H
Haojun Liao 已提交
2401

H
Haojun Liao 已提交
2402 2403 2404 2405 2406 2407 2408 2409
          bool isnull = isNull(pElem, pFilterInfo[k].info.type);
          if (isnull) {
            if (pFilterElem->fp == isNullOperator) {
              qualified = true;
              break;
            } else {
              continue;
            }
H
Haojun Liao 已提交
2410
          } else {
H
Haojun Liao 已提交
2411 2412 2413 2414 2415 2416
            if (pFilterElem->fp == notNullOperator) {
              qualified = true;
              break;
            } else if (pFilterElem->fp == isNullOperator) {
              continue;
            }
H
Haojun Liao 已提交
2417
          }
H
Haojun Liao 已提交
2418 2419

          if (pFilterElem->fp(pFilterElem, pElem, pElem, pFilterInfo[k].info.type)) {
H
Haojun Liao 已提交
2420 2421 2422 2423 2424
            qualified = true;
            break;
          }
        }

H
Haojun Liao 已提交
2425
        if (!qualified) {
H
Haojun Liao 已提交
2426 2427 2428 2429
          break;
        }
      }

H
Haojun Liao 已提交
2430
      p[i] = qualified ? 1 : 0;
H
Haojun Liao 已提交
2431
      if (!qualified) {
H
Haojun Liao 已提交
2432
        all = false;
H
Haojun Liao 已提交
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449
      }
    }
  }

  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 已提交
2450
            memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
H
Haojun Liao 已提交
2451 2452 2453
          }

          start += len;
2454
          len = 0;
H
Haojun Liao 已提交
2455 2456 2457 2458
        }
      }
    }

2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471
    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 已提交
2472 2473 2474 2475
    pBlock->info.rows = start;
    pBlock->pBlockStatis = NULL;  // clean the block statistics info

    if (start > 0) {
H
Haojun Liao 已提交
2476
      SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
2477 2478 2479 2480 2481
      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 已提交
2482 2483 2484 2485 2486 2487
    }
  }

  tfree(p);
}

H
Haojun Liao 已提交
2488 2489 2490
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 已提交
2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
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;
}

2510 2511
static void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock) {
  if (numOfFilterCols > 0 && pFilterInfo[0].pData != NULL) {
H
Haojun Liao 已提交
2512 2513 2514 2515
    return;
  }

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

2520 2521
      if (pFilterInfo[i].info.colId == pColInfo->info.colId) {
        pFilterInfo[i].pData = pColInfo->pData;
H
Haojun Liao 已提交
2522 2523 2524 2525 2526 2527
        break;
      }
    }
  }
}

H
Haojun Liao 已提交
2528 2529
int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
H
Haojun Liao 已提交
2530
  *status = BLK_DATA_NO_NEEDED;
H
Haojun Liao 已提交
2531
  pBlock->pDataBlock = NULL;
H
Haojun Liao 已提交
2532
  pBlock->pBlockStatis = NULL;
H
Haojun Liao 已提交
2533

H
Haojun Liao 已提交
2534
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2535
  int64_t groupId = pRuntimeEnv->current->groupIndex;
H
Haojun Liao 已提交
2536
  bool    ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
H
Haojun Liao 已提交
2537

H
Haojun Liao 已提交
2538
  SQInfo*         pQInfo = pRuntimeEnv->qinfo;
H
Haojun Liao 已提交
2539 2540
  SQueryCostInfo* pCost = &pQInfo->summary;

H
Haojun Liao 已提交
2541
  if (pRuntimeEnv->pTsBuf != NULL) {
H
Haojun Liao 已提交
2542
    (*status) = BLK_DATA_ALL_NEEDED;
H
Haojun Liao 已提交
2543

H
Haojun Liao 已提交
2544
    if (pQueryAttr->stableQuery) {  // todo refactor
H
Haojun Liao 已提交
2545
      SExprInfo*   pExprInfo = &pTableScanInfo->pExpr[0];
H
Haojun Liao 已提交
2546
      int16_t      tagId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
2547
      SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagId);
H
Haojun Liao 已提交
2548 2549 2550

      // compare tag first
      tVariant t = {0};
H
Haojun Liao 已提交
2551 2552
      doSetTagValueInParam(pRuntimeEnv->current->pTable, tagId, &t, pColInfo->type, pColInfo->bytes);
      setTimestampListJoinInfo(pRuntimeEnv, &t, pRuntimeEnv->current);
H
Haojun Liao 已提交
2553 2554 2555 2556 2557 2558

      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 已提交
2559 2560 2561
    }
  }

H
Haojun Liao 已提交
2562 2563
  // 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 已提交
2564 2565
  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 ||
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) {
H
Haojun Liao 已提交
2566 2567
    (*status) = BLK_DATA_ALL_NEEDED;
  }
H
Haojun Liao 已提交
2568

H
Haojun Liao 已提交
2569 2570 2571 2572
  // 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 已提交
2573
    if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2574
      SResultRow* pResult = NULL;
H
Haojun Liao 已提交
2575

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

H
Haojun Liao 已提交
2579
      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2580 2581 2582 2583
      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 已提交
2584
      }
H
Haojun Liao 已提交
2585
    } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
2586 2587
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
H
Haojun Liao 已提交
2588
                               pRuntimeEnv->current->groupIndex);
H
Haojun Liao 已提交
2589
    }
H
Haojun Liao 已提交
2590 2591

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

H
Haojun Liao 已提交
2594
  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
2595
  *status = updateBlockLoadStatus(pRuntimeEnv->pQueryAttr, *status);
H
Haojun Liao 已提交
2596

2597
  if ((*status) == BLK_DATA_NO_NEEDED || (*status) == BLK_DATA_DISCARD) {
H
Haojun Liao 已提交
2598
    qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2599
           pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2600 2601 2602 2603
    pCost->discardBlocks += 1;
  } else if ((*status) == BLK_DATA_STATIS_NEEDED) {
    // this function never returns error?
    pCost->loadBlockStatis += 1;
H
Haojun Liao 已提交
2604
    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pQueryHandle, &pBlock->pBlockStatis);
H
Haojun Liao 已提交
2605

H
Haojun Liao 已提交
2606
    if (pBlock->pBlockStatis == NULL) {  // data block statistics does not exist, load data block
H
Haojun Liao 已提交
2607
      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2608
      pCost->totalCheckedRows += pBlock->info.rows;
H
Haojun Liao 已提交
2609 2610 2611 2612 2613 2614
    }
  } else {
    assert((*status) == BLK_DATA_ALL_NEEDED);

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

H
Haojun Liao 已提交
2617
    if (pQueryAttr->topBotQuery && pBlock->pBlockStatis != NULL) {
H
Haojun Liao 已提交
2618
      { // set previous window
H
Haojun Liao 已提交
2619
        if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
2620 2621 2622 2623 2624
          SResultRow* pResult = NULL;

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

H
Haojun Liao 已提交
2625
          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
H
Haojun Liao 已提交
2626 2627 2628 2629 2630 2631 2632
          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 已提交
2633
      bool load = false;
H
Haojun Liao 已提交
2634
      for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
H
Haojun Liao 已提交
2635
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
H
Haojun Liao 已提交
2636
        if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
H
Haojun Liao 已提交
2637 2638
          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockStatis[i].min),
                                         (char*)&(pBlock->pBlockStatis[i].max));
H
Haojun Liao 已提交
2639
          if (!load) { // current block has been discard due to filter applied
H
Haojun Liao 已提交
2640
            pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2641
            qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
H
Haojun Liao 已提交
2642
                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2643 2644 2645 2646 2647 2648 2649 2650
            (*status) = BLK_DATA_DISCARD;
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
H
Haojun Liao 已提交
2651
    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockStatis, pTableScanInfo->pCtx, pBlockInfo->rows)) {
H
Haojun Liao 已提交
2652
      pCost->discardBlocks += 1;
H
Haojun Liao 已提交
2653
      qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
H
Haojun Liao 已提交
2654
             pBlockInfo->window.ekey, pBlockInfo->rows);
H
Haojun Liao 已提交
2655
      (*status) = BLK_DATA_DISCARD;
H
Haojun Liao 已提交
2656
      return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2657 2658 2659 2660
    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
H
Haojun Liao 已提交
2661
    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pQueryHandle, NULL);
H
Haojun Liao 已提交
2662
    if (pBlock->pDataBlock == NULL) {
H
Haojun Liao 已提交
2663 2664
      return terrno;
    }
H
Haojun Liao 已提交
2665

2666
    doSetFilterColumnInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock);
H
Haojun Liao 已提交
2667 2668
    if (pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) {
      filterRowsInDataBlock(pRuntimeEnv, pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock, ascQuery);
H
Haojun Liao 已提交
2669
    }
H
Haojun Liao 已提交
2670 2671 2672 2673 2674
  }

  return TSDB_CODE_SUCCESS;
}

H
hjxilinx 已提交
2675
int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
2676
  int32_t midPos = -1;
H
Haojun Liao 已提交
2677
  int32_t numOfRows;
2678

2679 2680 2681
  if (num <= 0) {
    return -1;
  }
2682

2683
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
2684 2685

  TSKEY * keyList = (TSKEY *)pValue;
2686
  int32_t firstPos = 0;
2687
  int32_t lastPos = num - 1;
2688

2689
  if (order == TSDB_ORDER_DESC) {
H
hjxilinx 已提交
2690 2691 2692 2693 2694
    // 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;
2695

H
Haojun Liao 已提交
2696 2697
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2698

H
hjxilinx 已提交
2699 2700 2701 2702 2703 2704 2705 2706
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2707

H
hjxilinx 已提交
2708 2709 2710 2711 2712
  } 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;
2713

H
hjxilinx 已提交
2714 2715 2716 2717 2718 2719 2720
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2721

H
Haojun Liao 已提交
2722
      numOfRows = lastPos - firstPos + 1;
H
Haojun Liao 已提交
2723
      midPos = (numOfRows >> 1u) + firstPos;
2724

H
hjxilinx 已提交
2725 2726 2727 2728 2729 2730 2731 2732 2733
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2734

H
hjxilinx 已提交
2735 2736 2737
  return midPos;
}

H
Haojun Liao 已提交
2738 2739 2740 2741 2742 2743
/*
 * 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);
2744

H
Haojun Liao 已提交
2745
  char* val = NULL;
H
Haojun Liao 已提交
2746
  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
2747
    val = tsdbGetTableName(pTable);
H
Haojun Liao 已提交
2748 2749
    assert(val != NULL);
  } else {
H
Haojun Liao 已提交
2750 2751
    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  }
H
Haojun Liao 已提交
2752

H
Haojun Liao 已提交
2753 2754 2755 2756
  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }
H
Haojun Liao 已提交
2757

H
Haojun Liao 已提交
2758
  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
2759 2760 2761 2762
    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 已提交
2763 2764
  } else {
    tVariantCreateFromBinary(tag, val, bytes, type);
2765
  }
2766 2767
}

2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779
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 已提交
2780
void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCtx, int32_t numOfOutput) {
H
Haojun Liao 已提交
2781
  SQueryRuntimeEnv* pRuntimeEnv = pOperatorInfo->pRuntimeEnv;
H
Haojun Liao 已提交
2782

H
Haojun Liao 已提交
2783 2784
  SExprInfo  *pExpr      = pOperatorInfo->pExpr;
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2785 2786

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

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

2793
    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
2794
    return;
H
Haojun Liao 已提交
2795 2796 2797
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
H
Haojun Liao 已提交
2798
    memset(pRuntimeEnv->tagVal, 0, pQueryAttr->tagLen);
H
Haojun Liao 已提交
2799

H
Haojun Liao 已提交
2800 2801 2802 2803 2804 2805 2806 2807 2808
    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 已提交
2809 2810
      doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resType,
                           pLocalExprInfo->base.resBytes);
H
Haojun Liao 已提交
2811

H
Haojun Liao 已提交
2812 2813
      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 已提交
2814
      } else {
2815
        memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
H
Haojun Liao 已提交
2816 2817
      }

H
Haojun Liao 已提交
2818
      offset += pLocalExprInfo->base.resBytes;
H
Haojun Liao 已提交
2819 2820
    }

H
Haojun Liao 已提交
2821
    //todo : use index to avoid iterator all possible output columns
H
Haojun Liao 已提交
2822
    if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) {
H
Haojun Liao 已提交
2823
      setParamForStableStddev(pRuntimeEnv, pCtx, numOfOutput, pExprInfo);
H
Haojun Liao 已提交
2824
    }
H
Haojun Liao 已提交
2825
  }
H
Haojun Liao 已提交
2826

H
Haojun Liao 已提交
2827 2828 2829
  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
H
Haojun Liao 已提交
2830 2831
  }
}
2832

2833
static UNUSED_FUNC void printBinaryData(int32_t functionId, char *data, int32_t srcDataType) {
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901
  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);
  }
}

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

2907 2908
  for (int32_t j = 0; j < numOfRows; ++j) {
    for (int32_t i = 0; i < numOfCols; ++i) {
2909

H
Haojun Liao 已提交
2910
      switch (pQueryAttr->pExpr1[i].base.resType) {
2911
        case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
2912 2913
          int32_t type = pQueryAttr->pExpr1[i].base.resType;
          printBinaryData(pQueryAttr->pExpr1[i].base.functionId, pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j,
2914 2915 2916 2917 2918
                          type);
          break;
        }
        case TSDB_DATA_TYPE_TIMESTAMP:
        case TSDB_DATA_TYPE_BIGINT:
H
Haojun Liao 已提交
2919
          printf("%" PRId64 "\t", *(int64_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2920 2921
          break;
        case TSDB_DATA_TYPE_INT:
H
Haojun Liao 已提交
2922
          printf("%d\t", *(int32_t *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2923 2924
          break;
        case TSDB_DATA_TYPE_FLOAT:
H
Haojun Liao 已提交
2925
          printf("%f\t", *(float *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2926 2927
          break;
        case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
2928
          printf("%lf\t", *(double *)(pdata[i]->data + pQueryAttr->pExpr1[i].base.resBytes * j));
2929 2930 2931 2932 2933 2934 2935
          break;
      }
    }
    printf("\n");
  }
}

H
Haojun Liao 已提交
2936
void copyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, int32_t threshold, SSDataBlock* pBlock, int32_t* offset) {
H
Haojun Liao 已提交
2937
  SGroupResInfo* pGroupResInfo = &pRuntimeEnv->groupResInfo;
H
Haojun Liao 已提交
2938
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
2939 2940

  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2941
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
H
Haojun Liao 已提交
2942 2943 2944
    // 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 已提交
2945
      if ((code = mergeIntoGroupResult(&pRuntimeEnv->groupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2946 2947 2948 2949
        return;
      }
    }

H
Haojun Liao 已提交
2950
    doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, TSDB_ORDER_ASC, pBlock);
H
Haojun Liao 已提交
2951 2952

    // current data are all dumped to result buffer, clear it
H
Haojun Liao 已提交
2953
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2954 2955
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
2956
        break;
H
Haojun Liao 已提交
2957 2958 2959
      }
    }

H
Haojun Liao 已提交
2960 2961 2962 2963
      // enough results in data buffer, return
      if (pBlock->info.rows >= threshold) {
        break;
      }
H
Haojun Liao 已提交
2964
    }
H
Haojun Liao 已提交
2965

H
Haojun Liao 已提交
2966 2967
}

H
Haojun Liao 已提交
2968
static void updateTableQueryInfoForReverseScan(SQueryAttr *pQueryAttr, STableQueryInfo *pTableQueryInfo) {
2969 2970 2971
  if (pTableQueryInfo == NULL) {
    return;
  }
2972

2973 2974
  SWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey, TSKEY);
  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
2975

2976 2977
  SWITCH_ORDER(pTableQueryInfo->cur.order);
  pTableQueryInfo->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
2978

H
Haojun Liao 已提交
2979
  // set the index to be the end slot of result rows array
H
Haojun Liao 已提交
2980
  pTableQueryInfo->resInfo.curIndex = pTableQueryInfo->resInfo.size - 1;
2981 2982
}

H
Haojun Liao 已提交
2983
static void setupQueryRangeForReverseScan(SQueryRuntimeEnv* pRuntimeEnv) {
H
Haojun Liao 已提交
2984
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
2985

H
Haojun Liao 已提交
2986
  int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pRuntimeEnv));
H
Haojun Liao 已提交
2987 2988
  for(int32_t i = 0; i < numOfGroups; ++i) {
    SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
2989
    SArray *tableKeyGroup = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
H
Haojun Liao 已提交
2990

H
Haojun Liao 已提交
2991 2992 2993
    size_t t = taosArrayGetSize(group);
    for (int32_t j = 0; j < t; ++j) {
      STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
2994
      updateTableQueryInfoForReverseScan(pQueryAttr, pCheckInfo);
H
Haojun Liao 已提交
2995

H
Haojun Liao 已提交
2996 2997 2998 2999
      // 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 已提交
3000

H
Haojun Liao 已提交
3001
      assert(pCheckInfo->pTable == pTableKeyInfo->pTable);
H
Haojun Liao 已提交
3002
    }
H
Haojun Liao 已提交
3003 3004
  }
}
H
Haojun Liao 已提交
3005

H
Haojun Liao 已提交
3006 3007 3008
void switchCtxOrder(SQLFunctionCtx* pCtx, int32_t numOfOutput) {
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SWITCH_ORDER(pCtx[i].order);
H
Haojun Liao 已提交
3009 3010 3011
  }
}

H
Haojun Liao 已提交
3012 3013 3014 3015 3016 3017
int32_t initResultRow(SResultRow *pResultRow) {
  pResultRow->pCellInfo = (SResultRowCellInfo*)((char*)pResultRow + sizeof(SResultRow));
  pResultRow->pageId    = -1;
  pResultRow->offset    = -1;
  return TSDB_CODE_SUCCESS;
}
3018

H
Haojun Liao 已提交
3019 3020 3021 3022 3023 3024 3025 3026
/*
 * 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 已提交
3027
void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, int64_t uid, int32_t stage) {
H
Haojun Liao 已提交
3028 3029 3030 3031 3032
  SQLFunctionCtx* pCtx           = pInfo->pCtx;
  SSDataBlock* pDataBlock        = pInfo->pRes;
  int32_t* rowCellInfoOffset     = pInfo->rowCellInfoOffset;
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;

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

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

H
Haojun Liao 已提交
3039 3040 3041 3042 3043 3044 3045
    /*
     * 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 已提交
3046 3047 3048
    pCtx[i].resultInfo   = pCellInfo;
    pCtx[i].pOutput      = pData->pData;
    pCtx[i].currentStage = stage;
H
Haojun Liao 已提交
3049
    assert(pCtx[i].pOutput != NULL);
3050

H
Haojun Liao 已提交
3051 3052 3053 3054 3055
    // 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;
    }
3056
  }
3057

H
Haojun Liao 已提交
3058
  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
H
Haojun Liao 已提交
3059
}
3060

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

H
Haojun Liao 已提交
3064
  int32_t newSize = pDataBlock->info.rows + numOfInputRows + 5; // extra output buffer
H
Haojun Liao 已提交
3065
  if ((*bufCapacity) < newSize) {
H
Haojun Liao 已提交
3066 3067
    for(int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
H
Haojun Liao 已提交
3068

H
Haojun Liao 已提交
3069 3070 3071
      char* p = realloc(pColInfo->pData, newSize * pColInfo->info.bytes);
      if (p != NULL) {
        pColInfo->pData = p;
3072

H
Haojun Liao 已提交
3073 3074
        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
H
Haojun Liao 已提交
3075
        (*bufCapacity) = newSize;
H
Haojun Liao 已提交
3076 3077
      } else {
        // longjmp
3078 3079
      }
    }
H
Haojun Liao 已提交
3080
  }
3081

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

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

H
Haojun Liao 已提交
3094
void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) {
H
Haojun Liao 已提交
3095 3096 3097 3098
  for (int32_t j = 0; j < size; ++j) {
    SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
    if (pResInfo->initialized) {
      continue;
D
fix bug  
dapan1121 已提交
3099 3100
    }

H
Haojun Liao 已提交
3101
    aAggs[pCtx[j].functionId].init(&pCtx[j]);
3102
  }
H
Haojun Liao 已提交
3103
}
3104

H
Haojun Liao 已提交
3105
void setQueryStatus(SQueryRuntimeEnv *pRuntimeEnv, int8_t status) {
H
Haojun Liao 已提交
3106
  if (status == QUERY_NOT_COMPLETED) {
H
Haojun Liao 已提交
3107
    pRuntimeEnv->status = status;
H
Haojun Liao 已提交
3108 3109
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
H
Haojun Liao 已提交
3110 3111
    CLEAR_QUERY_STATUS(pRuntimeEnv, QUERY_NOT_COMPLETED);
    pRuntimeEnv->status |= status;
H
Haojun Liao 已提交
3112 3113
  }
}
3114

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

H
Haojun Liao 已提交
3118 3119 3120 3121
  if (pRuntimeEnv->pTsBuf) {
    SWITCH_ORDER(pRuntimeEnv->pTsBuf->cur.order);
    bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
    assert(ret);
3122
  }
3123

H
Haojun Liao 已提交
3124
  // reverse order time range
H
Haojun Liao 已提交
3125
  SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
H
Haojun Liao 已提交
3126 3127

  SET_REVERSE_SCAN_FLAG(pRuntimeEnv);
H
Haojun Liao 已提交
3128
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
3129

H
Haojun Liao 已提交
3130
  switchCtxOrder(pCtx, numOfOutput);
H
Haojun Liao 已提交
3131
  SWITCH_ORDER(pQueryAttr->order.order);
H
Haojun Liao 已提交
3132 3133

  setupQueryRangeForReverseScan(pRuntimeEnv);
3134 3135
}

H
Haojun Liao 已提交
3136
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
H
Haojun Liao 已提交
3137
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
3138
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3139 3140

  int32_t numOfOutput = pOperator->numOfOutput;
H
Haojun Liao 已提交
3141
  if (pQueryAttr->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQueryAttr) || pQueryAttr->sw.gap > 0) {
H
Haojun Liao 已提交
3142
    // for each group result, call the finalize function for each column
H
Haojun Liao 已提交
3143
    if (pQueryAttr->groupbyColumn) {
H
Haojun Liao 已提交
3144 3145 3146 3147 3148 3149 3150 3151 3152
      closeAllResultRows(pResultRowInfo);
    }

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

H
Haojun Liao 已提交
3153
      setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
H
Haojun Liao 已提交
3154 3155 3156 3157 3158 3159 3160 3161 3162

      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 已提交
3163
      buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv, pCtx, numOfOutput);
H
Haojun Liao 已提交
3164 3165 3166 3167 3168 3169 3170 3171 3172
    }

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

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

3177 3178 3179 3180
    if (functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_TAG && functionId != TSDB_FUNC_TAGPRJ) {
      return true;
    }
  }
3181

3182 3183 3184
  return false;
}

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

H
hjxilinx 已提交
3188 3189
  pTableQueryInfo->win = win;
  pTableQueryInfo->lastKey = win.skey;
3190

3191
  pTableQueryInfo->pTable = pTable;
3192
  pTableQueryInfo->cur.vgroupIndex = -1;
3193

H
Haojun Liao 已提交
3194
  // set more initial size of interval/groupby query
H
Haojun Liao 已提交
3195
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr) || groupbyColumn) {
H
Haojun Liao 已提交
3196
    int32_t initialSize = 128;
H
Haojun Liao 已提交
3197
    int32_t code = initResultRowInfo(&pTableQueryInfo->resInfo, initialSize, TSDB_DATA_TYPE_INT);
B
Bomin Zhang 已提交
3198 3199 3200
    if (code != TSDB_CODE_SUCCESS) {
      return NULL;
    }
H
Haojun Liao 已提交
3201
  } else { // in other aggregate query, do not initialize the windowResInfo
H
Haojun Liao 已提交
3202 3203
  }

3204 3205 3206
  return pTableQueryInfo;
}

H
Haojun Liao 已提交
3207
void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo) {
3208 3209 3210
  if (pTableQueryInfo == NULL) {
    return;
  }
3211

H
Haojun Liao 已提交
3212
  tVariantDestroy(&pTableQueryInfo->tag);
H
Haojun Liao 已提交
3213
  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
3214 3215
}

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

H
Haojun Liao 已提交
3221
  int16_t offset = 0;
3222
  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
3223
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3224 3225 3226

    SResultRowCellInfo* pResInfo = pCtx[i].resultInfo;
    if (pResInfo->initialized && pResInfo->complete) {
H
Haojun Liao 已提交
3227
      offset += pCtx[i].outputBytes;
H
Haojun Liao 已提交
3228 3229
      continue;
    }
3230

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

3234
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
3235
    if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
3236
      pCtx[i].ptsOutputBuf = pCtx[0].pOutput;
H
Haojun Liao 已提交
3237
    }
3238

3239
    if (!pResInfo->initialized) {
3240
      aAggs[functionId].init(&pCtx[i]);
H
Haojun Liao 已提交
3241 3242 3243 3244
    }
  }
}

3245 3246
void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, SQLFunctionCtx* pCtx,
                              int32_t* rowCellInfoOffset, int32_t numOfOutput, int32_t groupIndex) {
3247
  int64_t uid = 0;
H
Haojun Liao 已提交
3248
  SResultRow* pResultRow =
3249
      doPrepareResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&groupIndex, sizeof(groupIndex), true, uid);
3250
  assert (pResultRow != NULL);
3251

3252 3253 3254 3255 3256
  /*
   * 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 已提交
3257
    int32_t ret = addNewWindowResultBuf(pResultRow, pRuntimeEnv->pResultBuf, groupIndex, pRuntimeEnv->pQueryAttr->resultRowSize);
3258
    if (ret != TSDB_CODE_SUCCESS) {
3259
      return;
3260 3261 3262
    }
  }

3263 3264 3265 3266 3267
  setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
}

void setExecutionContext(SQueryRuntimeEnv* pRuntimeEnv, SOptrBasicInfo* pInfo, int32_t numOfOutput, int32_t groupIndex,
                         TSKEY nextKey) {
H
Haojun Liao 已提交
3268
  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3269 3270 3271 3272 3273 3274 3275 3276 3277

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

3278 3279
  // record the current active group id
  pRuntimeEnv->prevGroupId = groupIndex;
3280 3281
}

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

H
Haojun Liao 已提交
3287
  int16_t offset = 0;
3288
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3289
    pCtx[i].pOutput = getPosInResultPage(pRuntimeEnv->pQueryAttr, page, pResult->offset, offset);
H
Haojun Liao 已提交
3290
    offset += pCtx[i].outputBytes;
3291

3292 3293 3294
    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;
3295 3296
    }

3297 3298 3299 3300
    /*
     * set the output buffer information and intermediate buffer,
     * not all queries require the interResultBuf, such as COUNT
     */
H
Haojun Liao 已提交
3301
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);
3302 3303 3304
  }
}

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

H
Haojun Liao 已提交
3308
  SSqlExpr* pExpr = &pExprInfo->base;
H
Haojun Liao 已提交
3309
  if (pQueryAttr->stableQuery && (pRuntimeEnv->pTsBuf != NULL) &&
H
Haojun Liao 已提交
3310 3311 3312
      (pExpr->functionId == TSDB_FUNC_TS || pExpr->functionId == TSDB_FUNC_PRJ) &&
      (pExpr->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
    assert(pExpr->numOfParams == 1);
H
Haojun Liao 已提交
3313

H
Haojun Liao 已提交
3314
    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i64;
H
Haojun Liao 已提交
3315
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);
H
Haojun Liao 已提交
3316 3317 3318 3319 3320

    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 已提交
3321
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%s", GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3322
             pExprInfo->base.param[0].i64, pCtx[0].tag.pz);
H
Haojun Liao 已提交
3323
    } else {
H
Haojun Liao 已提交
3324
      qDebug("QInfo:0x%"PRIx64" set tag value for join comparison, colId:%" PRId64 ", val:%" PRId64, GET_QID(pRuntimeEnv),
H
Haojun Liao 已提交
3325
             pExprInfo->base.param[0].i64, pCtx[0].tag.i64);
H
Haojun Liao 已提交
3326 3327 3328 3329 3330
    }
  }
}

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

H
Haojun Liao 已提交
3333 3334 3335 3336 3337 3338
  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 已提交
3339
    STSElem elem = tsBufGetElemStartPos(pRuntimeEnv->pTsBuf, pQueryAttr->vgId, &pTableQueryInfo->tag);
H
Haojun Liao 已提交
3340 3341 3342 3343

    // 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 已提交
3344
        qError("QInfo:0x%"PRIx64" failed to find tag:%s in ts_comp", GET_QID(pRuntimeEnv), pTag->pz);
H
Haojun Liao 已提交
3345
      } else {
H
Haojun Liao 已提交
3346
        qError("QInfo:0x%"PRIx64" failed to find tag:%" PRId64 " in ts_comp", GET_QID(pRuntimeEnv), pTag->i64);
H
Haojun Liao 已提交
3347 3348 3349 3350 3351 3352 3353 3354
      }

      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 已提交
3355
      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 已提交
3356
    } else {
H
Haojun Liao 已提交
3357
      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 已提交
3358 3359 3360 3361 3362
    }

  } else {
    tsBufSetCursor(pRuntimeEnv->pTsBuf, &pTableQueryInfo->cur);
    if (pTag->nType == TSDB_DATA_TYPE_BINARY || pTag->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
3363
      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 已提交
3364
    } else {
H
Haojun Liao 已提交
3365
      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 已提交
3366
    }
H
Haojun Liao 已提交
3367 3368
  }

H
Haojun Liao 已提交
3369 3370 3371
  return 0;
}

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

H
Haojun Liao 已提交
3375
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3376
  for(int32_t i = 0; i < numOfExprs; ++i) {
H
Haojun Liao 已提交
3377
    SExprInfo* pExprInfo1 = &(pExprInfo[i]);
H
Haojun Liao 已提交
3378
    if (pExprInfo1->base.functionId != TSDB_FUNC_STDDEV_DST) {
H
Haojun Liao 已提交
3379 3380 3381
      continue;
    }

H
Haojun Liao 已提交
3382
    SSqlExpr* pExpr = &pExprInfo1->base;
H
Haojun Liao 已提交
3383 3384

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

    // TODO use hash to speedup this loop
H
Haojun Liao 已提交
3388 3389 3390
    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 已提交
3391
      if (pQueryAttr->tagLen == 0 || memcmp(p->tags, pRuntimeEnv->tagVal, pQueryAttr->tagLen) == 0) {
H
Haojun Liao 已提交
3392 3393
        int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult);
        for (int32_t k = 0; k < numOfCols; ++k) {
H
Haojun Liao 已提交
3394
          SStddevInterResult* pres = taosArrayGet(p->pResult, k);
H
Haojun Liao 已提交
3395
          if (pres->colId == pExpr->colInfo.colId) {
H
Haojun Liao 已提交
3396 3397 3398 3399 3400 3401 3402 3403 3404
            pCtx[i].param[0].arr = pres->pResult;
            break;
          }
        }
      }
    }
  }

}
3405

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

H
Haojun Liao 已提交
3409
  int32_t numOfExprs = pQueryAttr->numOfOutput;
H
Haojun Liao 已提交
3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435
  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 已提交
3436

3437 3438 3439
/*
 * There are two cases to handle:
 *
H
Haojun Liao 已提交
3440 3441
 * 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.
3442 3443 3444 3445
 * 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 已提交
3446
void setIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key) {
H
Haojun Liao 已提交
3447
  SQueryAttr           *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3448
  STableQueryInfo  *pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
3449
  SResultRowInfo   *pWindowResInfo = &pTableQueryInfo->resInfo;
3450

H
Haojun Liao 已提交
3451 3452 3453
  if (pWindowResInfo->prevSKey != TSKEY_INITIAL_VAL) {
    return;
  }
3454

H
Haojun Liao 已提交
3455
  pTableQueryInfo->win.skey = key;
H
Haojun Liao 已提交
3456
  STimeWindow win = {.skey = key, .ekey = pQueryAttr->window.ekey};
3457

H
Haojun Liao 已提交
3458 3459 3460 3461 3462 3463
  /**
   * 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 已提交
3464
  STimeWindow w = TSWINDOW_INITIALIZER;
3465

H
Haojun Liao 已提交
3466 3467
  TSKEY sk = MIN(win.skey, win.ekey);
  TSKEY ek = MAX(win.skey, win.ekey);
H
Haojun Liao 已提交
3468
  getAlignQueryTimeWindow(pQueryAttr, win.skey, sk, ek, &w);
3469

H
Haojun Liao 已提交
3470
  if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3471 3472
    if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
      assert(win.ekey == pQueryAttr->window.ekey);
3473
    }
H
Haojun Liao 已提交
3474

H
Haojun Liao 已提交
3475
    pWindowResInfo->prevSKey = w.skey;
3476
  }
H
Haojun Liao 已提交
3477 3478

  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
3479 3480 3481
}

/**
H
Haojun Liao 已提交
3482
 * copyToOutputBuf support copy data in ascending/descending order
3483 3484 3485 3486 3487 3488 3489
 * 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 已提交
3490

H
Haojun Liao 已提交
3491
static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
3492
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3493 3494

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
H
Haojun Liao 已提交
3495
  int32_t numOfResult = pBlock->info.rows; // there are already exists result rows
H
Haojun Liao 已提交
3496 3497 3498 3499

  int32_t start = 0;
  int32_t step = -1;

H
Haojun Liao 已提交
3500
  qDebug("QInfo:0x%"PRIx64" start to copy data from windowResInfo to output buf", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
  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 已提交
3521 3522

    int16_t offset = 0;
H
Haojun Liao 已提交
3523 3524 3525 3526 3527
    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 已提交
3528
      char *in  = getPosInResultPage(pQueryAttr, page, pRow->offset, offset);
H
Haojun Liao 已提交
3529
      memcpy(out, in, bytes * numOfRowsToCopy);
H
Haojun Liao 已提交
3530 3531

      offset += bytes;
H
Haojun Liao 已提交
3532 3533 3534
    }

    numOfResult += numOfRowsToCopy;
H
Haojun Liao 已提交
3535
    if (numOfResult == pRuntimeEnv->resultInfo.capacity) {  // output buffer is full
H
Haojun Liao 已提交
3536 3537 3538 3539
      break;
    }
  }

H
Haojun Liao 已提交
3540
  qDebug("QInfo:0x%"PRIx64" copy data to query buf completed", GET_QID(pRuntimeEnv));
H
Haojun Liao 已提交
3541 3542 3543 3544 3545 3546
  pBlock->info.rows = numOfResult;
  return 0;
}

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

H
Haojun Liao 已提交
3548
  pBlock->info.rows = 0;
H
Haojun Liao 已提交
3549
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
H
Haojun Liao 已提交
3550 3551 3552
    return;
  }

H
Haojun Liao 已提交
3553 3554
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t orderType = (pQueryAttr->pGroupbyExpr != NULL) ? pQueryAttr->pGroupbyExpr->orderType : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3555
  doCopyToSDataBlock(pRuntimeEnv, pGroupResInfo, orderType, pBlock);
H
Haojun Liao 已提交
3556

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

H
Haojun Liao 已提交
3560 3561 3562
  if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    STimeWindow* w = &pBlock->info.window;
    w->skey = *(int64_t*)pInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3563
    w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
H
Haojun Liao 已提交
3564
  }
3565 3566
}

H
Haojun Liao 已提交
3567 3568 3569
static void updateNumOfRowsInResultRows(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx, int32_t numOfOutput,
                                        SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
3570

3571
  // update the number of result for each, only update the number of rows for the corresponding window result.
H
Haojun Liao 已提交
3572
  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3573 3574
    return;
  }
3575

3576 3577
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRow *pResult = pResultRowInfo->pResult[i];
3578

3579 3580
    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
H
Haojun Liao 已提交
3581 3582
      if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
        continue;
3583
      }
H
Haojun Liao 已提交
3584

H
Haojun Liao 已提交
3585
      SResultRowCellInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
3586
      pResult->numOfRows = (uint16_t)(MAX(pResult->numOfRows, pCell->numOfRes));
3587 3588 3589 3590 3591
    }
  }
}

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

H
Haojun Liao 已提交
3595
  SSDataBlock* pRes = pRuntimeEnv->outputBuf;
3596

H
Haojun Liao 已提交
3597 3598
  if (pQueryAttr->pExpr2 == NULL) {
    for (int32_t col = 0; col < pQueryAttr->numOfOutput; ++col) {
H
Haojun Liao 已提交
3599 3600 3601
      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 已提交
3602 3603
    }
  } else {
H
Haojun Liao 已提交
3604
    for (int32_t col = 0; col < pQueryAttr->numOfExpr2; ++col) {
H
Haojun Liao 已提交
3605 3606 3607
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, col);
      memmove(data, pColRes->pData, pColRes->info.bytes * numOfRows);
      data += pColRes->info.bytes * numOfRows;
H
Haojun Liao 已提交
3608
    }
3609
  }
3610

H
Haojun Liao 已提交
3611
  int32_t numOfTables = (int32_t) taosHashGetSize(pRuntimeEnv->pTableRetrieveTsMap);
weixin_48148422's avatar
weixin_48148422 已提交
3612 3613
  *(int32_t*)data = htonl(numOfTables);
  data += sizeof(int32_t);
3614

3615
  int32_t total = 0;
H
Haojun Liao 已提交
3616
  STableIdInfo* item = taosHashIterate(pRuntimeEnv->pTableRetrieveTsMap, NULL);
3617

3618
  while(item) {
weixin_48148422's avatar
weixin_48148422 已提交
3619
    STableIdInfo* pDst = (STableIdInfo*)data;
3620 3621 3622 3623
    pDst->uid = htobe64(item->uid);
    pDst->tid = htonl(item->tid);
    pDst->key = htobe64(item->key);

weixin_48148422's avatar
weixin_48148422 已提交
3624
    data += sizeof(STableIdInfo);
3625 3626
    total++;

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

H
Haojun Liao 已提交
3631
  qDebug("QInfo:0x%"PRIx64" set %d subscribe info", pQInfo->qId, total);
H
Haojun Liao 已提交
3632
  // Check if query is completed or not for stable query or normal table query respectively.
H
Haojun Liao 已提交
3633 3634
  if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) {
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
3635
  }
3636 3637
}

H
Haojun Liao 已提交
3638
int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) {
H
Haojun Liao 已提交
3639 3640 3641 3642 3643 3644
  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 已提交
3645
  pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity);
H
Haojun Liao 已提交
3646
  tfree(p);
H
Haojun Liao 已提交
3647 3648
  return pOutput->info.rows;
}
3649

H
Haojun Liao 已提交
3650
void queryCostStatis(SQInfo *pQInfo) {
3651
  SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
3652
  SQueryCostInfo *pSummary = &pQInfo->summary;
H
Haojun Liao 已提交
3653

H
Haojun Liao 已提交
3654
  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
H
Haojun Liao 已提交
3655
  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
H
Haojun Liao 已提交
3656 3657
  pSummary->hashSize = hashSize;

H
Haojun Liao 已提交
3658 3659 3660
  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

H
Haojun Liao 已提交
3661
  SResultRowPool* p = pQInfo->runtimeEnv.pool;
3662 3663 3664 3665 3666 3667 3668
  if (p != NULL) {
    pSummary->winInfoSize = getResultRowPoolMemSize(p);
    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  } else {
    pSummary->winInfoSize = 0;
    pSummary->numOfTimeWindows = 0;
  }
3669

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

H
Haojun Liao 已提交
3675
  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 已提交
3676
      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
3677 3678
}

3679
//static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
H
Haojun Liao 已提交
3680
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
3681
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3682
//
H
Haojun Liao 已提交
3683
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3684
//
H
Haojun Liao 已提交
3685 3686 3687
//  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;
3688 3689 3690
//    return;
//  }
//
H
Haojun Liao 已提交
3691 3692
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//    pQueryAttr->pos = (int32_t)pQueryAttr->limit.offset;
3693
//  } else {
H
Haojun Liao 已提交
3694
//    pQueryAttr->pos = pBlockInfo->rows - (int32_t)pQueryAttr->limit.offset - 1;
3695 3696
//  }
//
H
Haojun Liao 已提交
3697
//  assert(pQueryAttr->pos >= 0 && pQueryAttr->pos <= pBlockInfo->rows - 1);
3698 3699 3700 3701
//
//  SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
//  SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
//
H
Haojun Liao 已提交
3702
//  // update the pQueryAttr->limit.offset value, and pQueryAttr->pos value
3703 3704 3705
//  TSKEY *keys = (TSKEY *) pColInfoData->pData;
//
//  // update the offset value
H
Haojun Liao 已提交
3706 3707
//  pTableQueryInfo->lastKey = keys[pQueryAttr->pos];
//  pQueryAttr->limit.offset = 0;
3708 3709 3710
//
//  int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//
H
Haojun Liao 已提交
3711
//  qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%"PRId64, GET_QID(pRuntimeEnv),
3712 3713
//         pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
//}
H
Haojun Liao 已提交
3714

3715
//void skipBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
H
Haojun Liao 已提交
3716
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3717
//
H
Haojun Liao 已提交
3718
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0) {
3719 3720 3721
//    return;
//  }
//
H
Haojun Liao 已提交
3722 3723
//  pQueryAttr->pos = 0;
//  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
3724
//
H
Haojun Liao 已提交
3725
//  STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
3726 3727 3728 3729
//  TsdbQueryHandleT pQueryHandle = pRuntimeEnv->pQueryHandle;
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pQueryHandle)) {
H
Haojun Liao 已提交
3730
//    if (isQueryKilled(pRuntimeEnv->qinfo)) {
3731 3732 3733 3734 3735
//      longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//    }
//
//    tsdbRetrieveDataBlockInfo(pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3736 3737 3738
//    if (pQueryAttr->limit.offset > blockInfo.rows) {
//      pQueryAttr->limit.offset -= blockInfo.rows;
//      pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? blockInfo.window.ekey : blockInfo.window.skey;
3739 3740
//      pTableQueryInfo->lastKey += step;
//
H
Haojun Liao 已提交
3741
//      qDebug("QInfo:0x%"PRIx64" skip rows:%d, offset:%" PRId64, GET_QID(pRuntimeEnv), blockInfo.rows,
3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752
//             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 已提交
3753

3754
//static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, STableQueryInfo* pTableQueryInfo) {
H
Haojun Liao 已提交
3755
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
3756 3757
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//
H
Haojun Liao 已提交
3758
//  assert(pQueryAttr->limit.offset == 0);
3759
//  STimeWindow tw = *win;
H
Haojun Liao 已提交
3760
//  getNextTimeWindow(pQueryAttr, &tw);
3761
//
H
Haojun Liao 已提交
3762 3763
//  if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//      (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
3764 3765 3766 3767 3768 3769 3770 3771
//
//    // 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 已提交
3772
//        getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
3773 3774 3775
//    assert(startPos >= 0);
//
//    // set the abort info
H
Haojun Liao 已提交
3776
//    pQueryAttr->pos = startPos;
3777 3778 3779
//
//    // reset the query start timestamp
//    pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
H
Haojun Liao 已提交
3780
//    pQueryAttr->window.skey = pTableQueryInfo->win.skey;
3781 3782 3783 3784 3785 3786 3787 3788
//    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 已提交
3789
//    qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, lastKey:%" PRId64,
H
Haojun Liao 已提交
3790
//           GET_QID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
H
Haojun Liao 已提交
3791
//           pQueryAttr->current->lastKey);
3792 3793 3794
//
//    return key;
//  } else {  // do nothing
H
Haojun Liao 已提交
3795
//    pQueryAttr->window.skey      = tw.skey;
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805
//    pWindowResInfo->prevSKey = tw.skey;
//    pTableQueryInfo->lastKey = tw.skey;
//
//    return tw.skey;
//  }
//
//  return true;
//}

//static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
H
Haojun Liao 已提交
3806 3807
//  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
3808
//    assert(*start <= pRuntimeEnv->current->lastKey);
3809
//  } else {
H
Haojun Liao 已提交
3810
//    assert(*start >= pRuntimeEnv->current->lastKey);
3811 3812 3813
//  }
//
//  // if queried with value filter, do NOT forward query start position
H
Haojun Liao 已提交
3814
//  if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || pRuntimeEnv->pFillInfo != NULL) {
3815 3816 3817 3818
//    return true;
//  }
//
//  /*
H
Haojun Liao 已提交
3819 3820 3821
//   * 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
3822 3823 3824 3825
//   */
//  assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
//
//  STimeWindow w = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3826
//  bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
3827 3828
//
//  SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
H
Haojun Liao 已提交
3829
//  STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
3830 3831 3832 3833 3834
//
//  SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//  while (tsdbNextDataBlock(pRuntimeEnv->pQueryHandle)) {
//    tsdbRetrieveDataBlockInfo(pRuntimeEnv->pQueryHandle, &blockInfo);
//
H
Haojun Liao 已提交
3835
//    if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
3836
//      if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
H
Haojun Liao 已提交
3837
//        getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey, &w);
3838 3839 3840
//        pWindowResInfo->prevSKey = w.skey;
//      }
//    } else {
H
Haojun Liao 已提交
3841
//      getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w);
3842 3843 3844 3845
//      pWindowResInfo->prevSKey = w.skey;
//    }
//
//    // the first time window
H
Haojun Liao 已提交
3846
//    STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
3847
//
H
Haojun Liao 已提交
3848
//    while (pQueryAttr->limit.offset > 0) {
3849 3850 3851
//      STimeWindow tw = win;
//
//      if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
H
Haojun Liao 已提交
3852
//        pQueryAttr->limit.offset -= 1;
3853 3854 3855 3856 3857 3858 3859 3860 3861
//        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 已提交
3862
//      if (pQueryAttr->limit.offset == 0) {
3863 3864 3865 3866 3867
//        *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//        return true;
//      }
//
//      // current window does not ended in current data block, try next data block
H
Haojun Liao 已提交
3868
//      getNextTimeWindow(pQueryAttr, &tw);
3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882
//
//      /*
//       * 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 已提交
3883
//          pQueryAttr->limit.offset -= 1;
3884 3885
//        }
//
H
Haojun Liao 已提交
3886
//        if (pQueryAttr->limit.offset == 0) {
3887 3888 3889 3890 3891
//          *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//          return true;
//        } else {
//          tw = win;
//          int32_t startPos =
H
Haojun Liao 已提交
3892
//              getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
3893 3894 3895
//          assert(startPos >= 0);
//
//          // set the abort info
H
Haojun Liao 已提交
3896
//          pQueryAttr->pos = startPos;
3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913
//          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;
//}
3914

H
Haojun Liao 已提交
3915 3916
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

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

H
Haojun Liao 已提交
3920
  // TODO set the tags scan handle
H
Haojun Liao 已提交
3921
  if (onlyQueryTags(pQueryAttr)) {
B
Bomin Zhang 已提交
3922
    return TSDB_CODE_SUCCESS;
B
Bomin Zhang 已提交
3923 3924
  }

H
Haojun Liao 已提交
3925 3926
  STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
  if (pQueryAttr->tsCompQuery || pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
3927 3928
    cond.type = BLOCK_LOAD_TABLE_SEQ_ORDER;
  }
S
TD-1057  
Shengliang Guan 已提交
3929

B
Bomin Zhang 已提交
3930
  if (!isSTableQuery
H
Haojun Liao 已提交
3931
    && (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 1)
3932
    && (cond.order == TSDB_ORDER_ASC)
H
Haojun Liao 已提交
3933 3934 3935
    && (!QUERY_IS_INTERVAL_QUERY(pQueryAttr))
    && (!pQueryAttr->groupbyColumn)
    && (!pQueryAttr->simpleAgg)
B
Bomin Zhang 已提交
3936
  ) {
H
Haojun Liao 已提交
3937
    SArray* pa = GET_TABLEGROUP(pRuntimeEnv, 0);
3938 3939
    STableQueryInfo* pCheckInfo = taosArrayGetP(pa, 0);
    cond.twindow = pCheckInfo->win;
3940
  }
B
Bomin Zhang 已提交
3941

B
Bomin Zhang 已提交
3942
  terrno = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
3943
  if (isFirstLastRowQuery(pQueryAttr)) {
H
Haojun Liao 已提交
3944
    pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3945

H
Haojun Liao 已提交
3946
    // update the query time window
H
Haojun Liao 已提交
3947 3948
    pQueryAttr->window = cond.twindow;
    if (pQueryAttr->tableGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
3949
      pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
H
Haojun Liao 已提交
3950
    } else {
H
Haojun Liao 已提交
3951
      size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
H
Haojun Liao 已提交
3952
      for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
3953
        SArray *group = GET_TABLEGROUP(pRuntimeEnv, i);
H
Haojun Liao 已提交
3954

H
Haojun Liao 已提交
3955 3956 3957
        size_t t = taosArrayGetSize(group);
        for (int32_t j = 0; j < t; ++j) {
          STableQueryInfo *pCheckInfo = taosArrayGetP(group, j);
H
Haojun Liao 已提交
3958

H
Haojun Liao 已提交
3959
          pCheckInfo->win = pQueryAttr->window;
H
Haojun Liao 已提交
3960 3961
          pCheckInfo->lastKey = pCheckInfo->win.skey;
        }
H
Haojun Liao 已提交
3962 3963
      }
    }
H
Haojun Liao 已提交
3964
  } else if (pQueryAttr->pointInterpQuery) {
H
Haojun Liao 已提交
3965
    pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3966
  } else {
H
Haojun Liao 已提交
3967
    pRuntimeEnv->pQueryHandle = tsdbQueryTables(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef);
H
Haojun Liao 已提交
3968
  }
3969

B
Bomin Zhang 已提交
3970
  return terrno;
B
Bomin Zhang 已提交
3971 3972
}

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

H
Haojun Liao 已提交
3976
  SFillColInfo* pFillCol = calloc(numOfOutput, sizeof(SFillColInfo));
H
Haojun Liao 已提交
3977 3978 3979 3980
  if (pFillCol == NULL) {
    return NULL;
  }

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

H
Haojun Liao 已提交
3984
    pFillCol[i].col.bytes  = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
3985
    pFillCol[i].col.type   = (int8_t)pExprInfo->base.resType;
3986
    pFillCol[i].col.offset = offset;
H
Haojun Liao 已提交
3987
    pFillCol[i].col.colId  = pExprInfo->base.resColId;
H
Haojun Liao 已提交
3988
    pFillCol[i].tagIndex   = -2;
H
Haojun Liao 已提交
3989
    pFillCol[i].flag       = pExprInfo->base.colInfo.flag;    // always be the normal column for table query
3990
    pFillCol[i].functionId = pExprInfo->base.functionId;
H
Haojun Liao 已提交
3991
    pFillCol[i].fillVal.i  = fillVal[i];
3992

H
Haojun Liao 已提交
3993
    offset += pExprInfo->base.resBytes;
3994
  }
3995

3996 3997 3998
  return pFillCol;
}

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

H
Haojun Liao 已提交
4003
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
4004
  pQueryAttr->tsdb = tsdb;
H
Haojun Liao 已提交
4005

4006 4007
  pRuntimeEnv->prevResult = prevResult;

H
Haojun Liao 已提交
4008
  if (tsdb != NULL) {
H
Haojun Liao 已提交
4009
    int32_t code = setupQueryHandle(tsdb, pRuntimeEnv, pQInfo->qId, pQueryAttr->stableQuery);
H
Haojun Liao 已提交
4010 4011 4012
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
B
Bomin Zhang 已提交
4013
  }
4014

H
Haojun Liao 已提交
4015
  pQueryAttr->interBufSize = getOutputInterResultBufSize(pQueryAttr);
H
Haojun Liao 已提交
4016

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

H
Haojun Liao 已提交
4019
  pRuntimeEnv->pQueryAttr = pQueryAttr;
H
Haojun Liao 已提交
4020
  pRuntimeEnv->pTsBuf = pTsBuf;
4021
  pRuntimeEnv->cur.vgroupIndex = -1;
H
Haojun Liao 已提交
4022
  setResultBufSize(pQueryAttr, &pRuntimeEnv->resultInfo);
H
Haojun Liao 已提交
4023

H
Haojun Liao 已提交
4024 4025
  switch(tbScanner) {
    case OP_TableBlockInfoScan: {
H
Haojun Liao 已提交
4026
      pRuntimeEnv->proot = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4027 4028 4029
      break;
    }
    case OP_TableSeqScan: {
H
Haojun Liao 已提交
4030
      pRuntimeEnv->proot = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv);
H
Haojun Liao 已提交
4031 4032 4033
      break;
    }
    case OP_DataBlocksOptScan: {
H
Haojun Liao 已提交
4034
      pRuntimeEnv->proot = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), 1);
H
Haojun Liao 已提交
4035 4036 4037
      break;
    }
    case OP_TableScan: {
H
Haojun Liao 已提交
4038
      pRuntimeEnv->proot = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr));
H
Haojun Liao 已提交
4039 4040
      break;
    }
H
Haojun Liao 已提交
4041
    default: { // do nothing
H
Haojun Liao 已提交
4042 4043 4044
      break;
    }
  }
H
Haojun Liao 已提交
4045 4046

  if (sourceOptr != NULL) {
H
Haojun Liao 已提交
4047 4048
    assert(pRuntimeEnv->proot == NULL);
    pRuntimeEnv->proot = sourceOptr;
H
Haojun Liao 已提交
4049 4050
  }

H
Haojun Liao 已提交
4051
  if (pTsBuf != NULL) {
H
Haojun Liao 已提交
4052
    int16_t order = (pQueryAttr->order.order == pRuntimeEnv->pTsBuf->tsOrder) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
H
Haojun Liao 已提交
4053
    tsBufSetTraverseOrder(pRuntimeEnv->pTsBuf, order);
4054 4055
  }

4056
  int32_t ps = DEFAULT_PAGE_SIZE;
H
Haojun Liao 已提交
4057
  getIntermediateBufInfo(pRuntimeEnv, &ps, &pQueryAttr->intermediateResultRowSize);
4058

H
Haojun Liao 已提交
4059
  int32_t TENMB = 1024*1024*10;
H
Haojun Liao 已提交
4060
  int32_t code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, ps, TENMB, pQInfo->qId);
H
Haojun Liao 已提交
4061 4062
  if (code != TSDB_CODE_SUCCESS) {
    return code;
4063 4064
  }

H
Haojun Liao 已提交
4065
  // create runtime environment
H
Haojun Liao 已提交
4066
  int32_t numOfTables = (int32_t)pQueryAttr->tableGroupInfo.numOfTables;
H
Haojun Liao 已提交
4067
  pQInfo->summary.tableInfoSize += (numOfTables * sizeof(STableQueryInfo));
4068

H
Haojun Liao 已提交
4069
  code = setupQueryRuntimeEnv(pRuntimeEnv, (int32_t) pQueryAttr->tableGroupInfo.numOfTables, pOperator, param);
H
Haojun Liao 已提交
4070 4071 4072 4073
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

H
Haojun Liao 已提交
4074
  setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
4075
  return TSDB_CODE_SUCCESS;
4076 4077
}

H
Haojun Liao 已提交
4078 4079
static void doTableQueryInfoTimeWindowCheck(SQueryAttr* pQueryAttr, STableQueryInfo* pTableQueryInfo) {
  if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
H
Haojun Liao 已提交
4080 4081 4082
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey >= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4083
        (pTableQueryInfo->win.skey >= pQueryAttr->window.skey && pTableQueryInfo->win.ekey <= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4084 4085 4086 4087
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
        (pTableQueryInfo->lastKey <= pTableQueryInfo->win.skey) &&
H
Haojun Liao 已提交
4088
        (pTableQueryInfo->win.skey <= pQueryAttr->window.skey && pTableQueryInfo->win.ekey >= pQueryAttr->window.ekey));
H
Haojun Liao 已提交
4089 4090 4091
  }
}

H
Haojun Liao 已提交
4092
STsdbQueryCond createTsdbQueryCond(SQueryAttr* pQueryAttr, STimeWindow* win) {
4093
  STsdbQueryCond cond = {
H
Haojun Liao 已提交
4094
      .colList   = pQueryAttr->tableCols,
H
Haojun Liao 已提交
4095 4096
      .order     = pQueryAttr->order.order,
      .numOfCols = pQueryAttr->numOfCols,
H
Haojun Liao 已提交
4097
      .type      = BLOCK_LOAD_OFFSET_SEQ_ORDER,
4098
      .loadExternalRows = false,
4099 4100
  };

H
Haojun Liao 已提交
4101
  TIME_WINDOW_COPY(cond.twindow, *win);
4102 4103 4104
  return cond;
}

H
Haojun Liao 已提交
4105
static STableIdInfo createTableIdInfo(STableQueryInfo* pTableQueryInfo) {
4106
  STableIdInfo tidInfo;
H
Haojun Liao 已提交
4107
  STableId* id = TSDB_TABLEID(pTableQueryInfo->pTable);
4108 4109 4110

  tidInfo.uid = id->uid;
  tidInfo.tid = id->tid;
H
Haojun Liao 已提交
4111
  tidInfo.key = pTableQueryInfo->lastKey;
4112 4113 4114 4115

  return tidInfo;
}

H
Haojun Liao 已提交
4116 4117 4118 4119
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 已提交
4120 4121
  STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
  STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
4122 4123 4124 4125 4126 4127 4128 4129
  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 已提交
4130 4131 4132 4133
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);
4134

H
Haojun Liao 已提交
4135 4136 4137 4138
    size_t num = taosArrayGetSize(group);
    for (int32_t j = 0; j < num; ++j) {
      STableQueryInfo* item = taosArrayGetP(group, j);
      closeAllResultRows(&item->resInfo);
4139 4140
    }
  }
4141 4142
}

H
Haojun Liao 已提交
4143
static SSDataBlock* doTableScanImpl(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4144 4145 4146
  SOperatorInfo*   pOperator = (SOperatorInfo*) param;

  STableScanInfo*  pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4147 4148
  SSDataBlock*      pBlock = &pTableScanInfo->block;
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4149 4150
  SQueryAttr*       pQueryAttr = pRuntimeEnv->pQueryAttr;
  STableGroupInfo  *pTableGroupInfo = &pOperator->pRuntimeEnv->tableqinfoGroupInfo;
H
Haojun Liao 已提交
4151

H
Haojun Liao 已提交
4152 4153
  *newgroup = false;

H
Haojun Liao 已提交
4154
  while (tsdbNextDataBlock(pTableScanInfo->pQueryHandle)) {
4155 4156 4157
    if (isQueryKilled(pOperator->pRuntimeEnv->qinfo)) {
      longjmp(pOperator->pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
    }
H
Haojun Liao 已提交
4158

4159
    pTableScanInfo->numOfBlocks += 1;
H
Haojun Liao 已提交
4160
    tsdbRetrieveDataBlockInfo(pTableScanInfo->pQueryHandle, &pBlock->info);
H
Haojun Liao 已提交
4161

4162
    // todo opt
H
Haojun Liao 已提交
4163
    if (pTableGroupInfo->numOfTables > 1 || (pRuntimeEnv->current == NULL && pTableGroupInfo->numOfTables == 1)) {
H
Haojun Liao 已提交
4164 4165
      STableQueryInfo** pTableQueryInfo =
          (STableQueryInfo**)taosHashGet(pTableGroupInfo->map, &pBlock->info.tid, sizeof(pBlock->info.tid));
H
Haojun Liao 已提交
4166 4167 4168 4169
      if (pTableQueryInfo == NULL) {
        break;
      }

H
Haojun Liao 已提交
4170
      pRuntimeEnv->current = *pTableQueryInfo;
H
Haojun Liao 已提交
4171
      doTableQueryInfoTimeWindowCheck(pQueryAttr, *pTableQueryInfo);
H
Haojun Liao 已提交
4172 4173
    }

H
Haojun Liao 已提交
4174
    // this function never returns error?
H
Haojun Liao 已提交
4175
    uint32_t status;
H
Haojun Liao 已提交
4176
    int32_t  code = loadDataBlockOnDemand(pOperator->pRuntimeEnv, pTableScanInfo, pBlock, &status);
H
Haojun Liao 已提交
4177
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4178
      longjmp(pOperator->pRuntimeEnv->env, code);
H
Haojun Liao 已提交
4179
    }
H
Haojun Liao 已提交
4180

H
Haojun Liao 已提交
4181
    // current block is ignored according to filter result by block statistics data, continue load the next block
H
Haojun Liao 已提交
4182
    if (status == BLK_DATA_DISCARD || pBlock->info.rows == 0) {
H
Haojun Liao 已提交
4183
      continue;
H
Haojun Liao 已提交
4184 4185 4186 4187
    }

    return pBlock;
  }
H
Haojun Liao 已提交
4188 4189

  return NULL;
H
Haojun Liao 已提交
4190 4191
}

H
Haojun Liao 已提交
4192
static SSDataBlock* doTableScan(void* param, bool *newgroup) {
H
Haojun Liao 已提交
4193 4194
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4195
  STableScanInfo   *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4196
  SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4197
  SQueryAttr       *pQueryAttr = pRuntimeEnv->pQueryAttr;
H
Haojun Liao 已提交
4198

H
Haojun Liao 已提交
4199
  SResultRowInfo* pResultRowInfo = pTableScanInfo->pResultRowInfo;
H
Haojun Liao 已提交
4200
  *newgroup = false;
H
Haojun Liao 已提交
4201

H
Haojun Liao 已提交
4202
  while (pTableScanInfo->current < pTableScanInfo->times) {
H
Haojun Liao 已提交
4203
    SSDataBlock* p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4204 4205
    if (p != NULL) {
      return p;
H
Haojun Liao 已提交
4206 4207
    }

H
Haojun Liao 已提交
4208
    if (++pTableScanInfo->current >= pTableScanInfo->times) {
H
Haojun Liao 已提交
4209 4210 4211 4212 4213
      if (pTableScanInfo->reverseTimes <= 0) {
        return NULL;
      } else {
        break;
      }
H
Haojun Liao 已提交
4214
    }
H
Haojun Liao 已提交
4215

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

H
Haojun Liao 已提交
4220
    setQueryStatus(pRuntimeEnv, QUERY_NOT_COMPLETED);
H
Haojun Liao 已提交
4221
    pRuntimeEnv->scanFlag = REPEAT_SCAN;
H
Haojun Liao 已提交
4222

H
Haojun Liao 已提交
4223 4224 4225 4226 4227
    if (pRuntimeEnv->pTsBuf) {
      bool ret = tsBufNextPos(pRuntimeEnv->pTsBuf);
      assert(ret);
    }

4228 4229 4230 4231
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = 0;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[0]->win.skey;
    }
H
Haojun Liao 已提交
4232

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

H
Haojun Liao 已提交
4237
  SSDataBlock *p = NULL;
H
Haojun Liao 已提交
4238
  if (pTableScanInfo->reverseTimes > 0) {
H
Haojun Liao 已提交
4239
    setupEnvForReverseScan(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, pTableScanInfo->numOfOutput);
H
Haojun Liao 已提交
4240

H
Haojun Liao 已提交
4241
    STsdbQueryCond cond = createTsdbQueryCond(pQueryAttr, &pQueryAttr->window);
H
Haojun Liao 已提交
4242
    tsdbResetQueryHandle(pTableScanInfo->pQueryHandle, &cond);
H
Haojun Liao 已提交
4243

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

H
Haojun Liao 已提交
4247 4248
    pRuntimeEnv->scanFlag = REVERSE_SCAN;

H
Haojun Liao 已提交
4249 4250
    pTableScanInfo->times = 1;
    pTableScanInfo->current = 0;
H
Haojun Liao 已提交
4251 4252
    pTableScanInfo->reverseTimes = 0;
    pTableScanInfo->order = cond.order;
H
Haojun Liao 已提交
4253

H
Haojun Liao 已提交
4254 4255 4256 4257
    if (pResultRowInfo->size > 0) {
      pResultRowInfo->curIndex = pResultRowInfo->size-1;
      pResultRowInfo->prevSKey = pResultRowInfo->pResult[pResultRowInfo->size-1]->win.skey;
    }
H
Haojun Liao 已提交
4258

H
Haojun Liao 已提交
4259
    p = doTableScanImpl(pOperator, newgroup);
H
Haojun Liao 已提交
4260
  }
H
Haojun Liao 已提交
4261

H
Haojun Liao 已提交
4262
  return p;
H
Haojun Liao 已提交
4263 4264
}

H
Haojun Liao 已提交
4265
static SSDataBlock* doBlockInfoScan(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4266
  SOperatorInfo *pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4267 4268 4269
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
H
Haojun Liao 已提交
4270 4271

  STableScanInfo *pTableScanInfo = pOperator->info;
H
Haojun Liao 已提交
4272
  *newgroup = false;
H
Haojun Liao 已提交
4273 4274

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

H
Haojun Liao 已提交
4278
  tsdbGetFileBlocksDistInfo(pTableScanInfo->pQueryHandle, &tableBlockDist);
sangshuduo's avatar
sangshuduo 已提交
4279
  tableBlockDist.numOfRowsInMemTable = (int32_t) tsdbGetNumOfRowsInMemTable(pTableScanInfo->pQueryHandle);
H
Haojun Liao 已提交
4280 4281 4282 4283 4284

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

H
Haojun Liao 已提交
4285 4286 4287 4288 4289 4290
  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 已提交
4291

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

H
Haojun Liao 已提交
4295
  tbufCloseWriter(&bw);
H
Haojun Liao 已提交
4296

H
Haojun Liao 已提交
4297
  SArray* g = GET_TABLEGROUP(pOperator->pRuntimeEnv, 0);
H
Haojun Liao 已提交
4298
  pOperator->pRuntimeEnv->current = taosArrayGetP(g, 0);
H
Haojun Liao 已提交
4299 4300 4301

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

H
Haojun Liao 已提交
4304
SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime) {
H
Haojun Liao 已提交
4305 4306
  assert(repeatTime > 0);

H
Haojun Liao 已提交
4307 4308
  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4309
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4310
  pInfo->reverseTimes = 0;
H
Haojun Liao 已提交
4311
  pInfo->order        = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4312
  pInfo->current      = 0;
H
Haojun Liao 已提交
4313

H
Haojun Liao 已提交
4314
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4315
  pOperator->name         = "TableScanOperator";
H
Haojun Liao 已提交
4316
  pOperator->operatorType = OP_TableScan;
H
Haojun Liao 已提交
4317
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
4318 4319
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4320
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4321
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
4322
  pOperator->exec         = doTableScan;
H
Haojun Liao 已提交
4323 4324 4325 4326

  return pOperator;
}

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

H
Haojun Liao 已提交
4330 4331 4332
  pInfo->pQueryHandle     = pTsdbQueryHandle;
  pInfo->times            = 1;
  pInfo->reverseTimes     = 0;
H
Haojun Liao 已提交
4333
  pInfo->order            = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4334
  pInfo->current          = 0;
H
Haojun Liao 已提交
4335 4336

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4337 4338
  pOperator->name         = "TableSeqScanOperator";
  pOperator->operatorType = OP_TableSeqScan;
H
Haojun Liao 已提交
4339 4340 4341
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
4342
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4343 4344
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->exec         = doTableScanImpl;
H
Haojun Liao 已提交
4345

H
Haojun Liao 已提交
4346 4347 4348
  return pOperator;
}

H
Haojun Liao 已提交
4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367
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 已提交
4368
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4369 4370 4371 4372 4373
  pOperator->exec         = doBlockInfoScan;

  return pOperator;
}

H
Haojun Liao 已提交
4374 4375 4376
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
  assert(pTableScanInfo != NULL && pDownstream != NULL);

H
Haojun Liao 已提交
4377 4378 4379
  pTableScanInfo->pExpr = pDownstream->pExpr;   // TODO refactor to use colId instead of pExpr
  pTableScanInfo->numOfOutput = pDownstream->numOfOutput;

H
Haojun Liao 已提交
4380
  if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) {
H
Haojun Liao 已提交
4381
    SAggOperatorInfo* pAggInfo = pDownstream->info;
H
Haojun Liao 已提交
4382

H
Haojun Liao 已提交
4383 4384 4385
    pTableScanInfo->pCtx = pAggInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
4386
  } else if (pDownstream->operatorType == OP_TimeWindow) {
H
Haojun Liao 已提交
4387
    STableIntervalOperatorInfo *pIntervalInfo = pDownstream->info;
H
Haojun Liao 已提交
4388 4389 4390

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

H
Haojun Liao 已提交
4393
  } else if (pDownstream->operatorType == OP_Groupby) {
H
Haojun Liao 已提交
4394
    SGroupbyOperatorInfo *pGroupbyInfo = pDownstream->info;
H
Haojun Liao 已提交
4395

H
Haojun Liao 已提交
4396 4397 4398
    pTableScanInfo->pCtx = pGroupbyInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pGroupbyInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pGroupbyInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4399

H
Haojun Liao 已提交
4400
  } else if (pDownstream->operatorType == OP_MultiTableTimeInterval) {
H
Haojun Liao 已提交
4401
    STableIntervalOperatorInfo *pInfo = pDownstream->info;
H
Haojun Liao 已提交
4402

4403 4404
    pTableScanInfo->pCtx = pInfo->pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
4405 4406
    pTableScanInfo->rowCellInfoOffset = pInfo->rowCellInfoOffset;

H
Haojun Liao 已提交
4407
  } else if (pDownstream->operatorType == OP_Arithmetic) {
H
Haojun Liao 已提交
4408
    SArithOperatorInfo *pInfo = pDownstream->info;
4409

4410 4411 4412 4413 4414 4415
    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 已提交
4416 4417 4418
    pTableScanInfo->pCtx = pInfo->binfo.pCtx;
    pTableScanInfo->pResultRowInfo = &pInfo->binfo.resultRowInfo;
    pTableScanInfo->rowCellInfoOffset = pInfo->binfo.rowCellInfoOffset;
H
Haojun Liao 已提交
4419 4420 4421
  } else {
    assert(0);
  }
H
Haojun Liao 已提交
4422 4423
}

H
Haojun Liao 已提交
4424
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) {
H
Haojun Liao 已提交
4425 4426 4427 4428
  assert(repeatTime > 0);

  STableScanInfo* pInfo = calloc(1, sizeof(STableScanInfo));
  pInfo->pQueryHandle = pTsdbQueryHandle;
H
Haojun Liao 已提交
4429
  pInfo->times        = repeatTime;
H
Haojun Liao 已提交
4430
  pInfo->reverseTimes = reverseTime;
H
Haojun Liao 已提交
4431
  pInfo->current      = 0;
H
Haojun Liao 已提交
4432
  pInfo->order        = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4433 4434

  SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4435 4436
  pOptr->name          = "DataBlocksOptimizedScanOperator";
  pOptr->operatorType  = OP_DataBlocksOptScan;
H
Haojun Liao 已提交
4437
  pOptr->pRuntimeEnv   = pRuntimeEnv;
H
Haojun Liao 已提交
4438 4439 4440
  pOptr->blockingOptr  = false;
  pOptr->info          = pInfo;
  pOptr->exec          = doTableScan;
H
Haojun Liao 已提交
4441 4442

  return pOptr;
H
Haojun Liao 已提交
4443 4444
}

H
Haojun Liao 已提交
4445 4446 4447 4448 4449 4450
SArray* getOrderCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4451 4452
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463
  }

  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 已提交
4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475
  {
    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) {
        if (index->colId == pQuery->pExpr1[j].base.colInfo.colId) {
          index->colIndex = j;
          index->colId = pQuery->pExpr1[j].base.resColId;
        }
      }
    }
  }
H
Haojun Liao 已提交
4476 4477 4478
  return pOrderColumns;
}

H
Haojun Liao 已提交
4479 4480 4481 4482 4483 4484
SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) {
  int32_t numOfCols = pQuery->pGroupbyExpr->numOfGroupCols;

  SArray* pOrderColumns = NULL;
  if (numOfCols > 0) {
    pOrderColumns = taosArrayDup(pQuery->pGroupbyExpr->columnInfo);
H
Haojun Liao 已提交
4485 4486
  } else {
    pOrderColumns = taosArrayInit(4, sizeof(SColIndex));
H
Haojun Liao 已提交
4487 4488 4489 4490
  }

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

    bool found = false;
H
Haojun Liao 已提交
4493
    for(int32_t j = 0; j < pQuery->numOfOutput; ++j) {
H
Haojun Liao 已提交
4494 4495 4496 4497 4498 4499
      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 已提交
4500
        index->colIndex = j;
H
Haojun Liao 已提交
4501 4502 4503
        index->colId = pExpr->resColId;
        found = true;
        break;
H
Haojun Liao 已提交
4504 4505
      }
    }
H
Haojun Liao 已提交
4506 4507

    assert(found && index->colIndex >= 0 && index->colIndex < pQuery->numOfOutput);
H
Haojun Liao 已提交
4508 4509 4510 4511
  }

  return pOrderColumns;
}
H
Haojun Liao 已提交
4512

4513 4514 4515
static void destroyGlobalAggOperatorInfo(void* param, int32_t numOfOutput) {
  SMultiwayMergeInfo *pInfo = (SMultiwayMergeInfo*) param;
  destroyBasicOperatorInfo(&pInfo->binfo, numOfOutput);
4516 4517 4518 4519 4520

  taosArrayDestroy(pInfo->orderColumnList);
  taosArrayDestroy(pInfo->groupColumnList);
  tfree(pInfo->prevRow);
  tfree(pInfo->currentGroupColData);
4521 4522
}

H
Haojun Liao 已提交
4523 4524 4525 4526 4527 4528
static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) {
  SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param;
  taosArrayDestroy(pInfo->orderColumnList);
  tfree(pInfo->prevRow);
}

H
Haojun Liao 已提交
4529
SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream,
H
Haojun Liao 已提交
4530
                                                 SExprInfo* pExpr, int32_t numOfOutput, void* param) {
H
Haojun Liao 已提交
4531 4532
  SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));

4533 4534 4535
  pInfo->resultRowFactor =
      (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery,
                                              false));
H
Haojun Liao 已提交
4536

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

H
Haojun Liao 已提交
4539
  pInfo->pMerge = param;
H
Haojun Liao 已提交
4540
  pInfo->bufCapacity = 4096;
4541 4542

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

H
Haojun Liao 已提交
4545
  pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4546
  pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr);
H
Haojun Liao 已提交
4547

H
Haojun Liao 已提交
4548 4549 4550
  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
4551
    len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4552 4553
  }

H
Haojun Liao 已提交
4554
  int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4555
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4556
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4557 4558

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

H
Haojun Liao 已提交
4561 4562
    SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
    offset += pExpr[index->colIndex].base.resBytes;
H
Haojun Liao 已提交
4563 4564
  }

H
Haojun Liao 已提交
4565
  numOfCols = (pInfo->groupColumnList != NULL)? (int32_t)taosArrayGetSize(pInfo->groupColumnList):0;
H
Haojun Liao 已提交
4566
  pInfo->currentGroupColData = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4567
  offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4568 4569

  for(int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4570
    pInfo->currentGroupColData[i] = (char*)pInfo->currentGroupColData + offset;
H
Haojun Liao 已提交
4571 4572 4573 4574 4575

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

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

  pInfo->seed = rand();
H
Haojun Liao 已提交
4579
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MERGE_STAGE);
H
Haojun Liao 已提交
4580 4581

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4582
  pOperator->name         = "GlobalAggregate";
H
Haojun Liao 已提交
4583 4584
  pOperator->operatorType = OP_GlobalAggregate;
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
4585 4586 4587 4588 4589 4590 4591 4592
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->upstream     = upstream;
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;

  pOperator->exec         = doGlobalAggregate;
4593
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4594 4595 4596
  return pOperator;
}

H
Haojun Liao 已提交
4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610
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) {
4611
      len += pExpr[i].base.colBytes;
H
Haojun Liao 已提交
4612 4613
    }

H
Haojun Liao 已提交
4614
    int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
4615
    pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
4616
    int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
4617 4618 4619 4620 4621

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

      SColIndex* index = taosArrayGet(pInfo->orderColumnList, i);
4622
      offset += pExpr[index->colIndex].base.colBytes;
H
Haojun Liao 已提交
4623 4624 4625 4626 4627
    }
  }

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
  pOperator->name         = "MultiwaySortOperator";
4628
  pOperator->operatorType = OP_MultiwayMergeSort;
H
Haojun Liao 已提交
4629 4630 4631 4632 4633
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
  pOperator->numOfOutput  = pRuntimeEnv->pQueryAttr->numOfCols;
H
Haojun Liao 已提交
4634
  pOperator->exec         = doMultiwayMergeSort;
4635
  pOperator->cleanup      = destroyGlobalAggOperatorInfo;
H
Haojun Liao 已提交
4636 4637 4638
  return pOperator;
}

H
Haojun Liao 已提交
4639
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
H
Haojun Liao 已提交
4640 4641 4642
  return pTableScanInfo->order;
}

H
Haojun Liao 已提交
4643
// this is a blocking operator
H
Haojun Liao 已提交
4644
static SSDataBlock* doAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4645
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4646
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4647 4648
    return NULL;
  }
H
Haojun Liao 已提交
4649

H
Haojun Liao 已提交
4650
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4651 4652
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4653
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4654

H
Haojun Liao 已提交
4655 4656
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
4657

H
Haojun Liao 已提交
4658
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4659

H
Haojun Liao 已提交
4660
  while(1) {
H
Haojun Liao 已提交
4661
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4662 4663 4664 4665
    if (pBlock == NULL) {
      break;
    }

H
Haojun Liao 已提交
4666 4667 4668
    if (pRuntimeEnv->current != NULL) {
      setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
4669

H
Haojun Liao 已提交
4670
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4671
      STableScanInfo* pScanInfo = upstream->info;
H
Haojun Liao 已提交
4672 4673 4674
      order = getTableScanOrder(pScanInfo);
    }

H
Haojun Liao 已提交
4675
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
4676
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
H
Haojun Liao 已提交
4677
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
H
Haojun Liao 已提交
4678 4679
  }

H
Haojun Liao 已提交
4680
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4681
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4682

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

H
Haojun Liao 已提交
4686
  return pInfo->pRes;
H
Haojun Liao 已提交
4687 4688
}

H
Haojun Liao 已提交
4689
static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4690
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4691
  if (pOperator->status == OP_EXEC_DONE) {
4692 4693
    return NULL;
  }
H
Haojun Liao 已提交
4694

H
Haojun Liao 已提交
4695
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
4696 4697
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;

H
Haojun Liao 已提交
4698
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
4699

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

H
Haojun Liao 已提交
4703 4704
    if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
      pOperator->status = OP_EXEC_DONE;
4705 4706
    }

H
Haojun Liao 已提交
4707
    return pInfo->pRes;
4708
  }
H
Haojun Liao 已提交
4709

H
Haojun Liao 已提交
4710 4711
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
4712 4713 4714 4715

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
4716
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
4717 4718 4719 4720
    if (pBlock == NULL) {
      break;
    }

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

H
Haojun Liao 已提交
4723
    if (upstream->operatorType == OP_DataBlocksOptScan) {
H
Haojun Liao 已提交
4724
      STableScanInfo* pScanInfo = upstream->info;
4725 4726 4727 4728
      order = getTableScanOrder(pScanInfo);
    }

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

H
Haojun Liao 已提交
4731
    TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
H
Haojun Liao 已提交
4732
    setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pRuntimeEnv->current->groupIndex, key);
H
Haojun Liao 已提交
4733
    doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
4734
  }
H
Haojun Liao 已提交
4735

H
Haojun Liao 已提交
4736 4737
  pOperator->status = OP_RES_TO_RETURN;
  closeAllResultRows(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4738

H
Haojun Liao 已提交
4739
  updateNumOfRowsInResultRows(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput, &pInfo->resultRowInfo,
H
Haojun Liao 已提交
4740
                             pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4741

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

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

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

H
Haojun Liao 已提交
4752
static SSDataBlock* doArithmeticOperation(void* param, bool* newgroup) {
4753 4754
  SOperatorInfo* pOperator = (SOperatorInfo*) param;

H
Haojun Liao 已提交
4755 4756
  SArithOperatorInfo* pArithInfo = pOperator->info;
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4757
  SOptrBasicInfo *pInfo = &pArithInfo->binfo;
4758

H
Haojun Liao 已提交
4759
  SSDataBlock* pRes = pInfo->pRes;
H
Haojun Liao 已提交
4760
  int32_t order = pRuntimeEnv->pQueryAttr->order.order;
H
Haojun Liao 已提交
4761 4762

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

H
Haojun Liao 已提交
4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792
  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 已提交
4793
  while(1) {
H
Haojun Liao 已提交
4794 4795 4796 4797
    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 已提交
4798
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4799 4800 4801
      assert(*newgroup == false);

      *newgroup = prevVal;
H
Haojun Liao 已提交
4802
      setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4803
      break;
H
Haojun Liao 已提交
4804 4805
    }

H
Haojun Liao 已提交
4806 4807 4808 4809 4810 4811 4812
    // Return result of the previous group in the firstly.
    if (newgroup && pRes->info.rows > 0) {
      pArithInfo->existDataBlock = pBlock;
      clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
      return pInfo->pRes;
    }

H
Haojun Liao 已提交
4813
    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
H
Haojun Liao 已提交
4814 4815

    // todo dynamic set tags
H
Haojun Liao 已提交
4816 4817 4818
    if (pTableQueryInfo != NULL) {
      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    }
H
Haojun Liao 已提交
4819

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

H
Haojun Liao 已提交
4824
    arithmeticApplyFunctions(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4825 4826 4827 4828

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

H
Haojun Liao 已提交
4830 4831
    pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput);
    if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) {
H
Haojun Liao 已提交
4832 4833 4834 4835
      break;
    }
  }

H
Haojun Liao 已提交
4836
  clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
4837
  return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
H
Haojun Liao 已提交
4838 4839
}

H
Haojun Liao 已提交
4840
static SSDataBlock* doLimit(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4841
  SOperatorInfo* pOperator = (SOperatorInfo*)param;
H
Haojun Liao 已提交
4842
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4843
    return NULL;
H
Haojun Liao 已提交
4844 4845
  }

H
Haojun Liao 已提交
4846
  SLimitOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
4847
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4848

H
Haojun Liao 已提交
4849
  SSDataBlock* pBlock = NULL;
H
Haojun Liao 已提交
4850
  while (1) {
H
Haojun Liao 已提交
4851
    pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
H
Haojun Liao 已提交
4852
    if (pBlock == NULL) {
H
Haojun Liao 已提交
4853
      setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4854
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4855 4856 4857
      return NULL;
    }

H
Haojun Liao 已提交
4858
    if (pRuntimeEnv->currentOffset == 0) {
H
Haojun Liao 已提交
4859
      break;
4860
    } else if (pRuntimeEnv->currentOffset >= pBlock->info.rows) {
H
Haojun Liao 已提交
4861
      pRuntimeEnv->currentOffset -= pBlock->info.rows;
H
Haojun Liao 已提交
4862
    } else {
sangshuduo's avatar
sangshuduo 已提交
4863
      int32_t remain = (int32_t)(pBlock->info.rows - pRuntimeEnv->currentOffset);
H
Haojun Liao 已提交
4864 4865 4866
      pBlock->info.rows = remain;

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

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

H
Haojun Liao 已提交
4873
      pRuntimeEnv->currentOffset = 0;
H
Haojun Liao 已提交
4874
      break;
H
Haojun Liao 已提交
4875 4876
    }
  }
H
Haojun Liao 已提交
4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888

  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 已提交
4889 4890
}

D
dapan1121 已提交
4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903

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

D
dapan1121 已提交
4905 4906 4907 4908 4909 4910 4911
  if (fp(filterElem, input, input, p->info.type)) {
    return true;
  }

  return false;
}

4912
static SSDataBlock* doFilter(void* param, bool* newgroup) {
D
dapan1121 已提交
4913 4914 4915 4916 4917
  SOperatorInfo *pOperator = (SOperatorInfo *)param;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

H
Haojun Liao 已提交
4918
  SFilterOperatorInfo* pCondInfo = pOperator->info;
D
dapan1121 已提交
4919 4920 4921
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;

  while (1) {
H
Haojun Liao 已提交
4922
    SSDataBlock *pBlock = pOperator->upstream->exec(pOperator->upstream, newgroup);
D
dapan1121 已提交
4923
    if (pBlock == NULL) {
4924
      break;
D
dapan1121 已提交
4925
    }
H
Haojun Liao 已提交
4926

4927 4928 4929
    doSetFilterColumnInfo(pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock);
    assert(pRuntimeEnv->pTsBuf == NULL);
    filterRowsInDataBlock(pRuntimeEnv, pCondInfo->pFilterInfo, pCondInfo->numOfFilterCols, pBlock, true);
D
dapan1121 已提交
4930

4931 4932 4933
    if (pBlock->info.rows > 0) {
      return pBlock;
    }
D
dapan1121 已提交
4934 4935
  }

4936 4937 4938 4939
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
  pOperator->status = OP_EXEC_DONE;
  return NULL;
}
D
dapan1121 已提交
4940

H
Haojun Liao 已提交
4941
static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4942
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4943
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4944 4945 4946
    return NULL;
  }

H
Haojun Liao 已提交
4947
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
4948

H
Haojun Liao 已提交
4949
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
4950
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
4951 4952
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);

H
Haojun Liao 已提交
4953
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4954
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4955 4956 4957 4958
    }

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

H
Haojun Liao 已提交
4960 4961 4962
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
H
Haojun Liao 已提交
4963

H
Haojun Liao 已提交
4964
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
4965 4966

  while(1) {
H
Haojun Liao 已提交
4967
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
4968 4969 4970 4971 4972
    if (pBlock == NULL) {
      break;
    }

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

4977
  // restore the value
H
Haojun Liao 已提交
4978 4979
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
4980

H
Haojun Liao 已提交
4981
  pOperator->status = OP_RES_TO_RETURN;
4982
  closeAllResultRows(&pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4983
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
4984
  finalizeQueryResult(pOperator, pIntervalInfo->pCtx, &pIntervalInfo->resultRowInfo, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4985

H
Haojun Liao 已提交
4986
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pIntervalInfo->resultRowInfo);
H
Haojun Liao 已提交
4987
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes);
H
Haojun Liao 已提交
4988

H
Haojun Liao 已提交
4989
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
4990
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
4991 4992
  }

H
Haojun Liao 已提交
4993
  return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes;
H
Haojun Liao 已提交
4994 4995
}

H
Haojun Liao 已提交
4996
static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) {
H
Haojun Liao 已提交
4997
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
4998
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
4999 5000 5001
    return NULL;
  }

H
Haojun Liao 已提交
5002
  STableIntervalOperatorInfo* pIntervalInfo = pOperator->info;
H
Haojun Liao 已提交
5003
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5004

H
Haojun Liao 已提交
5005
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5006
    copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5007
    if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5008
      pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5009 5010 5011 5012 5013
    }

    return pIntervalInfo->pRes;
  }

H
Haojun Liao 已提交
5014 5015
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
H
Haojun Liao 已提交
5016

H
Haojun Liao 已提交
5017
  SOperatorInfo* upstream = pOperator->upstream;
H
Haojun Liao 已提交
5018 5019

  while(1) {
H
Haojun Liao 已提交
5020
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5021
    if (pBlock == NULL) {
H
Haojun Liao 已提交
5022
      break;
H
Haojun Liao 已提交
5023 5024
    }

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

H
Haojun Liao 已提交
5028
    setTagValue(pOperator, pTableQueryInfo->pTable, pIntervalInfo->pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5029
    setInputDataBlock(pOperator, pIntervalInfo->pCtx, pBlock, pQueryAttr->order.order);
5030
    setIntervalQueryRange(pRuntimeEnv, pBlock->info.window.skey);
H
Haojun Liao 已提交
5031

H
Haojun Liao 已提交
5032
    hashIntervalAgg(pOperator, &pTableQueryInfo->resInfo, pBlock, pTableQueryInfo->groupIndex);
H
Haojun Liao 已提交
5033
  }
H
Haojun Liao 已提交
5034

H
Haojun Liao 已提交
5035
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5036
  pQueryAttr->order.order = order;   // TODO : restore the order
5037
  doCloseAllTimeWindow(pRuntimeEnv);
H
Haojun Liao 已提交
5038
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
5039

H
Haojun Liao 已提交
5040
  copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5041
  if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) {
H
Haojun Liao 已提交
5042
    pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
5043 5044 5045 5046
  }

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

H
Haojun Liao 已提交
5048
static SSDataBlock* doSessionWindowAgg(void* param, bool* newgroup) {
5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
  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 已提交
5068 5069 5070
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t order = pQueryAttr->order.order;
  STimeWindow win = pQueryAttr->window;
5071 5072 5073 5074

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5075
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
5076 5077 5078 5079 5080
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5081
    setInputDataBlock(pOperator, pBInfo->pCtx, pBlock, pQueryAttr->order.order);
5082 5083 5084 5085
    doSessionWindowAggImpl(pOperator, pWindowInfo, pBlock);
  }

  // restore the value
H
Haojun Liao 已提交
5086 5087
  pQueryAttr->order.order = order;
  pQueryAttr->window = win;
5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103

  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 已提交
5104
static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5105
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5106
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5107 5108 5109
    return NULL;
  }

H
Haojun Liao 已提交
5110
  SGroupbyOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5111

H
Haojun Liao 已提交
5112
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5113
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
5114
    toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5115 5116

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

H
Haojun Liao 已提交
5120
    return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5121 5122 5123 5124 5125
  }

  SOperatorInfo* upstream = pOperator->upstream;

  while(1) {
H
Haojun Liao 已提交
5126
    SSDataBlock* pBlock = upstream->exec(upstream, newgroup);
H
Haojun Liao 已提交
5127 5128 5129 5130 5131
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
5132
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pRuntimeEnv->pQueryAttr->order.order);
H
Haojun Liao 已提交
5133
    setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
5134
    if (pInfo->colIndex == -1) {
H
Haojun Liao 已提交
5135
      pInfo->colIndex = getGroupbyColumnIndex(pRuntimeEnv->pQueryAttr->pGroupbyExpr, pBlock);
H
Haojun Liao 已提交
5136 5137
    }

H
Haojun Liao 已提交
5138
    doHashGroupbyAgg(pOperator, pInfo, pBlock);
H
Haojun Liao 已提交
5139 5140
  }

H
Haojun Liao 已提交
5141
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
5142
  closeAllResultRows(&pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5143
  setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
5144

H
Haojun Liao 已提交
5145
  if (!pRuntimeEnv->pQueryAttr->stableQuery) { // finalize include the update of result rows
H
Haojun Liao 已提交
5146 5147 5148
    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);
5149 5150
  }

H
Haojun Liao 已提交
5151
  initGroupResInfo(&pRuntimeEnv->groupResInfo, &pInfo->binfo.resultRowInfo);
H
Haojun Liao 已提交
5152
  toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->binfo.pRes);
H
Haojun Liao 已提交
5153

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

H
Haojun Liao 已提交
5158
  return pInfo->binfo.pRes;
H
Haojun Liao 已提交
5159 5160
}

H
Haojun Liao 已提交
5161
static SSDataBlock* doFill(void* param, bool* newgroup) {
H
Haojun Liao 已提交
5162
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5163
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5164 5165 5166
    return NULL;
  }

H
Haojun Liao 已提交
5167
  SFillOperatorInfo *pInfo = pOperator->info;
H
Haojun Liao 已提交
5168
  SQueryRuntimeEnv  *pRuntimeEnv = pOperator->pRuntimeEnv;
H
Haojun Liao 已提交
5169

H
Haojun Liao 已提交
5170
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
H
Haojun Liao 已提交
5171
    *newgroup = false;
sangshuduo's avatar
sangshuduo 已提交
5172
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5173 5174 5175
    return pInfo->pRes;
  }

H
Haojun Liao 已提交
5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190
  // 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 已提交
5191
  while(1) {
H
Haojun Liao 已提交
5192 5193 5194 5195 5196 5197 5198 5199
    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 已提交
5200

H
Haojun Liao 已提交
5201 5202
      // fill the previous group data block
      // before handle a new data block, close the fill operation for previous group data block
H
Haojun Liao 已提交
5203
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey);
H
Haojun Liao 已提交
5204
    } else {
H
Haojun Liao 已提交
5205 5206 5207 5208 5209 5210 5211 5212 5213
      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 已提交
5214

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

H
Haojun Liao 已提交
5218 5219 5220
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
H
Haojun Liao 已提交
5221 5222
    }

H
Haojun Liao 已提交
5223
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243
    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 已提交
5244 5245
  }
}
H
Haojun Liao 已提交
5246

H
Haojun Liao 已提交
5247
// todo set the attribute of query scan count
H
Haojun Liao 已提交
5248 5249 5250
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 已提交
5251 5252 5253 5254 5255 5256 5257 5258
    if (functionId == TSDB_FUNC_STDDEV || functionId == TSDB_FUNC_PERCT) {
      return 2;
    }
  }

  return 1;
}

H
Haojun Liao 已提交
5259 5260 5261 5262 5263
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

H
Haojun Liao 已提交
5264
  if (pOperator->cleanup != NULL) {
H
Haojun Liao 已提交
5265
    pOperator->cleanup(pOperator->info, pOperator->numOfOutput);
H
Haojun Liao 已提交
5266 5267
  }

H
Haojun Liao 已提交
5268
  destroyOperatorInfo(pOperator->upstream);
H
Haojun Liao 已提交
5269
  tfree(pOperator->info);
H
Haojun Liao 已提交
5270 5271 5272
  tfree(pOperator);
}

H
Haojun Liao 已提交
5273
SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5274 5275
  SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));

H
Haojun Liao 已提交
5276 5277
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
  int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
H
Haojun Liao 已提交
5278 5279

  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
H
Haojun Liao 已提交
5280
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5281

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

H
Haojun Liao 已提交
5284
  pInfo->seed = rand();
H
Haojun Liao 已提交
5285
  setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5286

H
Haojun Liao 已提交
5287
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5288
  pOperator->name         = "TableAggregate";
H
Haojun Liao 已提交
5289
  pOperator->operatorType = OP_Aggregate;
H
Haojun Liao 已提交
5290
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5291
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5292
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5293
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5294 5295 5296
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5297

H
Haojun Liao 已提交
5298 5299
  pOperator->exec         = doAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;
5300 5301 5302
  return pOperator;
}

H
Haojun Liao 已提交
5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319
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 已提交
5320
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
5321 5322 5323 5324
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5325
  SGroupbyOperatorInfo* pInfo = (SGroupbyOperatorInfo*) param;
H
Haojun Liao 已提交
5326
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
5327
  tfree(pInfo->prevData);
H
Haojun Liao 已提交
5328 5329 5330 5331 5332 5333 5334
}

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

H
Haojun Liao 已提交
5335 5336 5337 5338 5339
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
  STagScanInfo* pInfo = (STagScanInfo*) param;
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

5340
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
H
Haojun Liao 已提交
5341
  SFilterOperatorInfo* pInfo = (SFilterOperatorInfo*) param;
5342
  doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
D
dapan1121 已提交
5343 5344
}

5345 5346 5347 5348 5349 5350
static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) {
  SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param;
  taosHashCleanup(pInfo->pSet);
  pInfo->pRes = destroyOutputBuf(pInfo->pRes);
}

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

H
Haojun Liao 已提交
5354
  size_t tableGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
5355

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

5360
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5361 5362
  pOperator->name         = "MultiTableAggregate";
  pOperator->operatorType = OP_MultiTableAggregate;
5363
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5364
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5365
  pOperator->info         = pInfo;
5366
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5367 5368 5369
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5370

H
Haojun Liao 已提交
5371 5372 5373
  pOperator->exec         = doSTableAggregate;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5374
  return pOperator;
H
Haojun Liao 已提交
5375 5376
}

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

H
Haojun Liao 已提交
5380
  pInfo->seed = rand();
H
Haojun Liao 已提交
5381
  pInfo->bufCapacity = pRuntimeEnv->resultInfo.capacity;
H
Haojun Liao 已提交
5382

H
Haojun Liao 已提交
5383
  SOptrBasicInfo* pBInfo = &pInfo->binfo;
H
Haojun Liao 已提交
5384
  pBInfo->pRes  = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity);
H
Haojun Liao 已提交
5385 5386 5387
  pBInfo->pCtx  = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pBInfo->rowCellInfoOffset);

  initResultRowInfo(&pBInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5388
  setDefaultOutputBuf(pRuntimeEnv, pBInfo, pInfo->seed, MASTER_SCAN);
H
Haojun Liao 已提交
5389 5390

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5391 5392
  pOperator->name         = "ArithmeticOperator";
  pOperator->operatorType = OP_Arithmetic;
H
Haojun Liao 已提交
5393
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5394
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5395
  pOperator->info         = pInfo;
H
Haojun Liao 已提交
5396
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5397 5398 5399
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5400

H
Haojun Liao 已提交
5401 5402 5403
  pOperator->exec         = doArithmeticOperation;
  pOperator->cleanup      = destroyArithOperatorInfo;

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

H
Haojun Liao 已提交
5407
SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5408
                                           int32_t numOfOutput) {
H
Haojun Liao 已提交
5409
  SFilterOperatorInfo* pInfo = calloc(1, sizeof(SFilterOperatorInfo));
D
dapan1121 已提交
5410

5411 5412
  {
    SColumnInfo* pCols = calloc(numOfOutput, sizeof(SColumnInfo));
D
dapan1121 已提交
5413

5414 5415 5416 5417 5418
    int32_t numOfFilter = 0;
    for(int32_t i = 0; i < numOfOutput; ++i) {
      if (pExpr[i].base.flist.numOfFilters > 0) {
        numOfFilter += 1;
      }
D
dapan1121 已提交
5419

5420 5421 5422
      pCols[i].type = pExpr[i].base.resType;
      pCols[i].bytes = pExpr[i].base.resBytes;
      pCols[i].colId = pExpr[i].base.resColId;
H
Haojun Liao 已提交
5423

5424 5425 5426
      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 已提交
5427 5428
    }

5429 5430 5431
    assert(numOfFilter > 0);
    doCreateFilterInfo(pCols, numOfOutput, numOfFilter, &pInfo->pFilterInfo, 0);
    pInfo->numOfFilterCols = numOfFilter;
D
dapan1121 已提交
5432

5433 5434
    for(int32_t i = 0; i < numOfOutput; ++i) {
      tfree(pCols[i].flist.filterInfo);
D
dapan1121 已提交
5435 5436
    }

5437
    tfree(pCols);
D
dapan1121 已提交
5438 5439 5440 5441
  }

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

5442
  pOperator->name         = "ConditionOperator";
H
Haojun Liao 已提交
5443
  pOperator->operatorType = OP_Filter;
D
dapan1121 已提交
5444 5445 5446 5447 5448
  pOperator->blockingOptr = false;
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->pExpr        = pExpr;
  pOperator->upstream     = upstream;
5449
  pOperator->exec         = doFilter;
D
dapan1121 已提交
5450 5451
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
5452
  pOperator->cleanup      = destroyConditionOperatorInfo;
D
dapan1121 已提交
5453 5454 5455 5456

  return pOperator;
}

H
Haojun Liao 已提交
5457
SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream) {
H
Haojun Liao 已提交
5458
  SLimitOperatorInfo* pInfo = calloc(1, sizeof(SLimitOperatorInfo));
H
Haojun Liao 已提交
5459
  pInfo->limit = pRuntimeEnv->pQueryAttr->limit.limit;
H
Haojun Liao 已提交
5460 5461 5462

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

H
Haojun Liao 已提交
5463 5464
  pOperator->name         = "LimitOperator";
  pOperator->operatorType = OP_Limit;
H
Haojun Liao 已提交
5465
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5466
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5467
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5468
  pOperator->exec         = doLimit;
H
Haojun Liao 已提交
5469 5470
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5471 5472 5473 5474

  return pOperator;
}

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

H
Haojun Liao 已提交
5478
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5479
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5480
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5481 5482 5483

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

H
Haojun Liao 已提交
5484
  pOperator->name         = "TimeIntervalAggOperator";
5485
  pOperator->operatorType = OP_TimeWindow;
H
Haojun Liao 已提交
5486
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5487
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5488
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5489 5490 5491 5492
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5493
  pOperator->exec         = doIntervalAgg;
H
Haojun Liao 已提交
5494 5495
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5496 5497 5498
  return pOperator;
}

5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523
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 已提交
5524
SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
H
Haojun Liao 已提交
5525
  STableIntervalOperatorInfo* pInfo = calloc(1, sizeof(STableIntervalOperatorInfo));
H
Haojun Liao 已提交
5526

H
Haojun Liao 已提交
5527
  pInfo->pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
5528
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5529
  initResultRowInfo(&pInfo->resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5530 5531

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5532 5533
  pOperator->name         = "MultiTableTimeIntervalOperator";
  pOperator->operatorType = OP_MultiTableTimeInterval;
H
Haojun Liao 已提交
5534
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5535
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5536
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5537 5538
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5539 5540
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5541

H
Haojun Liao 已提交
5542 5543 5544
  pOperator->exec         = doSTableIntervalAgg;
  pOperator->cleanup      = destroyBasicOperatorInfo;

H
Haojun Liao 已提交
5545 5546 5547
  return pOperator;
}

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

H
Haojun Liao 已提交
5552
  pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
5553
  pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
H
Haojun Liao 已提交
5554
  initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
H
Haojun Liao 已提交
5555 5556

  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5557
  pOperator->name         = "GroupbyAggOperator";
H
Haojun Liao 已提交
5558
  pOperator->blockingOptr = true;
H
Haojun Liao 已提交
5559 5560
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Groupby;
H
Haojun Liao 已提交
5561
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5562 5563 5564 5565
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5566
  pOperator->exec         = hashGroupbyAggregate;
H
Haojun Liao 已提交
5567 5568
  pOperator->cleanup      = destroyGroupbyOperatorInfo;

H
Haojun Liao 已提交
5569 5570
  return pOperator;
}
H
Haojun Liao 已提交
5571

H
Haojun Liao 已提交
5572
SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr,
5573
                                      int32_t numOfOutput) {
H
Haojun Liao 已提交
5574
  SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo));
H
Haojun Liao 已提交
5575 5576 5577
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);

  {
H
Haojun Liao 已提交
5578 5579
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfOutput, pQueryAttr->fillVal);
H
Haojun Liao 已提交
5580 5581
    STimeWindow w = TSWINDOW_INITIALIZER;

H
Haojun Liao 已提交
5582 5583 5584
    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 已提交
5585

H
Haojun Liao 已提交
5586 5587 5588 5589
    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 已提交
5590
  }
H
Haojun Liao 已提交
5591 5592 5593

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

H
Haojun Liao 已提交
5594
  pOperator->name         = "FillOperator";
H
Haojun Liao 已提交
5595
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5596 5597 5598
  pOperator->status       = OP_IN_EXECUTING;
  pOperator->operatorType = OP_Fill;

H
Haojun Liao 已提交
5599
  pOperator->upstream     = upstream;
H
Haojun Liao 已提交
5600 5601 5602 5603
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5604

H
Haojun Liao 已提交
5605 5606 5607
  pOperator->exec         = doFill;
  pOperator->cleanup      = destroySFillOperatorInfo;

H
Haojun Liao 已提交
5608 5609 5610
  return pOperator;
}

H
Haojun Liao 已提交
5611
SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) {
H
Haojun Liao 已提交
5612 5613
  SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo));

H
Haojun Liao 已提交
5614 5615 5616
  SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;

  pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr);
H
Haojun Liao 已提交
5617 5618
  pInfo->slimit          = pQueryAttr->slimit;
  pInfo->limit           = pQueryAttr->limit;
H
Haojun Liao 已提交
5619 5620 5621

  pInfo->currentGroupOffset = pQueryAttr->slimit.offset;
  pInfo->currentOffset = pQueryAttr->limit.offset;
H
Haojun Liao 已提交
5622 5623 5624 5625 5626 5627 5628

  // TODO refactor
  int32_t len = 0;
  for(int32_t i = 0; i < numOfOutput; ++i) {
    len += pExpr[i].base.resBytes;
  }

H
Haojun Liao 已提交
5629
  int32_t numOfCols = pInfo->orderColumnList != NULL? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0;
H
Haojun Liao 已提交
5630
  pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len));
H
Haojun Liao 已提交
5631
  int32_t offset = POINTER_BYTES * numOfCols;
H
Haojun Liao 已提交
5632 5633 5634 5635 5636 5637 5638

  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 已提交
5639 5640 5641 5642 5643 5644 5645 5646

  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 已提交
5647
  pOperator->exec         = doSLimit;
H
Haojun Liao 已提交
5648 5649
  pOperator->info         = pInfo;
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5650
  pOperator->cleanup      = destroySlimitOperatorInfo;
H
Haojun Liao 已提交
5651 5652 5653
  return pOperator;
}

H
Haojun Liao 已提交
5654
static SSDataBlock* doTagScan(void* param, bool* newgroup) {
5655
  SOperatorInfo* pOperator = (SOperatorInfo*) param;
H
Haojun Liao 已提交
5656
  if (pOperator->status == OP_EXEC_DONE) {
H
Haojun Liao 已提交
5657 5658
    return NULL;
  }
5659

H
Haojun Liao 已提交
5660
  SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
5661

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

H
Haojun Liao 已提交
5664 5665
  STagScanInfo *pInfo = pOperator->info;
  SSDataBlock  *pRes = pInfo->pRes;
H
Haojun Liao 已提交
5666
  *newgroup = false;
5667 5668

  int32_t count = 0;
H
Haojun Liao 已提交
5669 5670 5671 5672
  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 已提交
5673 5674
    SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
    assert(pQueryAttr->numOfOutput == 1);
5675 5676

    SExprInfo* pExprInfo = &pOperator->pExpr[0];
H
Haojun Liao 已提交
5677
    int32_t rsize = pExprInfo->base.resBytes;
H
Haojun Liao 已提交
5678

5679 5680
    count = 0;

H
Haojun Liao 已提交
5681 5682
    int16_t bytes = pExprInfo->base.resBytes;
    int16_t type  = pExprInfo->base.resType;
5683

H
Haojun Liao 已提交
5684 5685 5686 5687
    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;
5688 5689 5690 5691
        break;
      }
    }

H
Haojun Liao 已提交
5692 5693 5694 5695
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);

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

H
Haojun Liao 已提交
5698
      char *output = pColInfo->pData + count * rsize;
5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712
      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 已提交
5713 5714
      *(int32_t *)output = pQueryAttr->vgId;
      output += sizeof(pQueryAttr->vgId);
5715

H
Haojun Liao 已提交
5716
      char* data = NULL;
5717
      if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
H
Haojun Liao 已提交
5718
        data = tsdbGetTableName(item->pTable);
5719
      } else {
H
Haojun Liao 已提交
5720
        data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes);
5721 5722
      }

H
Haojun Liao 已提交
5723
      doSetTagValueToResultBuf(output, data, type, bytes);
5724 5725 5726
      count += 1;
    }

H
Haojun Liao 已提交
5727
    qDebug("QInfo:0x%"PRIx64" create (tableId, tag) info completed, rows:%d", GET_QID(pRuntimeEnv), count);
H
Haojun Liao 已提交
5728 5729 5730
  } else if (functionId == TSDB_FUNC_COUNT) {// handle the "count(tbname)" query
    SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, 0);
    *(int64_t*)pColInfo->pData = pInfo->totalTables;
5731
    count = 1;
H
Haojun Liao 已提交
5732 5733

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

H
Haojun Liao 已提交
5738 5739 5740
    count = 0;
    while(pInfo->currentIndex < pInfo->totalTables && count < maxNumOfTables) {
      int32_t i = pInfo->currentIndex++;
5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751

      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 已提交
5752
        SColumnInfoData* pColInfo = taosArrayGet(pRes->pDataBlock, j);
H
Haojun Liao 已提交
5753 5754
        type  = pExprInfo[j].base.resType;
        bytes = pExprInfo[j].base.resBytes;
5755 5756 5757 5758 5759 5760 5761

        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 已提交
5762
        dst  = pColInfo->pData + count * pExprInfo[j].base.resBytes;
5763 5764
        doSetTagValueToResultBuf(dst, data, type, bytes);
      }
H
Haojun Liao 已提交
5765

5766 5767 5768
      count += 1;
    }

H
Haojun Liao 已提交
5769 5770 5771 5772
    if (pInfo->currentIndex >= pInfo->totalTables) {
      pOperator->status = OP_EXEC_DONE;
    }

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

H
Haojun Liao 已提交
5776
  pRes->info.rows = count;
H
Haojun Liao 已提交
5777
  return (pRes->info.rows == 0)? NULL:pInfo->pRes;
5778 5779
}

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

H
Haojun Liao 已提交
5784 5785 5786 5787 5788 5789
  size_t numOfGroup = GET_NUM_OF_TABLEGROUP(pRuntimeEnv);
  assert(numOfGroup == 0 || numOfGroup == 1);

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

5790
  SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
5791
  pOperator->name         = "SeqTableTagScan";
H
Haojun Liao 已提交
5792
  pOperator->operatorType = OP_TagScan;
5793
  pOperator->blockingOptr = false;
H
Haojun Liao 已提交
5794
  pOperator->status       = OP_IN_EXECUTING;
H
Haojun Liao 已提交
5795 5796
  pOperator->info         = pInfo;
  pOperator->exec         = doTagScan;
H
Haojun Liao 已提交
5797 5798
  pOperator->pExpr        = pExpr;
  pOperator->numOfOutput  = numOfOutput;
H
Haojun Liao 已提交
5799
  pOperator->pRuntimeEnv  = pRuntimeEnv;
H
Haojun Liao 已提交
5800
  pOperator->cleanup      = destroyTagScanOperatorInfo;
H
Haojun Liao 已提交
5801

5802 5803
  return pOperator;
}
H
Haojun Liao 已提交
5804

5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 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
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);
  pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pInfo->outputCapacity);

  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 已提交
5887
static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
5888
  int32_t j = 0;
5889

H
Haojun Liao 已提交
5890 5891
  if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
    if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
5892
      return TSDB_TBNAME_COLUMN_INDEX;
H
Haojun Liao 已提交
5893
    } else if (pExpr->colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
Y
yihaoDeng 已提交
5894
      return TSDB_BLOCK_DIST_COLUMN_INDEX;     
H
Haojun Liao 已提交
5895
    }
Y
yihaoDeng 已提交
5896
    
H
Haojun Liao 已提交
5897

H
Haojun Liao 已提交
5898 5899
    while(j < pTableInfo->numOfTags) {
      if (pExpr->colInfo.colId == pTagCols[j].colId) {
5900 5901
        return j;
      }
5902

5903 5904
      j += 1;
    }
5905

H
Haojun Liao 已提交
5906
  } else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {  // user specified column data
H
Haojun Liao 已提交
5907
    return TSDB_UD_COLUMN_INDEX;
5908
  } else {
H
Haojun Liao 已提交
5909 5910
    while (j < pTableInfo->numOfCols) {
      if (pExpr->colInfo.colId == pTableInfo->colList[j].colId) {
5911 5912
        return j;
      }
5913

5914
      j += 1;
5915 5916
    }
  }
5917 5918

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
5919 5920
}

H
Haojun Liao 已提交
5921 5922
bool validateExprColumnInfo(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) {
  int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols);
5923
  return j != INT32_MIN;
5924 5925
}

5926
static bool validateQueryMsg(SQueryTableMsg *pQueryMsg) {
5927 5928
  if (pQueryMsg->interval.interval < 0) {
    qError("qmsg:%p illegal value of interval time %" PRId64, pQueryMsg, pQueryMsg->interval.interval);
5929
    return false;
5930 5931
  }

5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942
  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 已提交
5943
  if (pQueryMsg->numOfTables <= 0) {
S
slguan 已提交
5944
    qError("qmsg:%p illegal value of numOfTables %d", pQueryMsg, pQueryMsg->numOfTables);
5945
    return false;
5946 5947
  }

H
hjxilinx 已提交
5948
  if (pQueryMsg->numOfGroupCols < 0) {
S
slguan 已提交
5949
    qError("qmsg:%p illegal value of numOfGroupbyCols %d", pQueryMsg, pQueryMsg->numOfGroupCols);
5950
    return false;
5951 5952
  }

5953 5954
  if (pQueryMsg->numOfOutput > TSDB_MAX_COLUMNS || pQueryMsg->numOfOutput <= 0) {
    qError("qmsg:%p illegal value of output columns %d", pQueryMsg, pQueryMsg->numOfOutput);
5955
    return false;
5956 5957
  }

5958 5959 5960
  return true;
}

H
Haojun Liao 已提交
5961 5962 5963 5964 5965
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);
5966
    return false;
5967 5968
  }

H
Haojun Liao 已提交
5969 5970 5971 5972 5973 5974 5975
  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)) {
5976
        continue;
5977
      }
5978

5979
      return false;
5980 5981
    }
  }
5982

H
Haojun Liao 已提交
5983 5984
  for(int32_t i = 0; i < numOfOutput; ++i) {
    if (!validateExprColumnInfo(pTableInfo, pExpr[i], pTagCols)) {
5985 5986 5987 5988
      return TSDB_CODE_QRY_INVALID_MSG;
    }
  }

5989
  return true;
5990 5991
}

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

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

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

6000
    pTableIdInfo->tid = htonl(pTableIdInfo->tid);
H
hjxilinx 已提交
6001 6002
    pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
    pTableIdInfo->key = htobe64(pTableIdInfo->key);
6003

H
hjxilinx 已提交
6004 6005 6006
    taosArrayPush(*pTableIdList, pTableIdInfo);
    pMsg += sizeof(STableIdInfo);
  }
6007

H
hjxilinx 已提交
6008 6009
  return pMsg;
}
6010

6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041
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;
}

6042
/**
H
hjxilinx 已提交
6043
 * pQueryMsg->head has been converted before this function is called.
6044
 *
H
hjxilinx 已提交
6045
 * @param pQueryMsg
6046 6047 6048 6049
 * @param pTableIdList
 * @param pExpr
 * @return
 */
H
Haojun Liao 已提交
6050
int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) {
6051 6052
  int32_t code = TSDB_CODE_SUCCESS;

6053 6054 6055 6056
  if (taosCheckVersion(pQueryMsg->version, version, 3) != 0) {
    return TSDB_CODE_QRY_INVALID_MSG;
  }

6057 6058 6059
  pQueryMsg->numOfTables = htonl(pQueryMsg->numOfTables);
  pQueryMsg->window.skey = htobe64(pQueryMsg->window.skey);
  pQueryMsg->window.ekey = htobe64(pQueryMsg->window.ekey);
6060 6061 6062
  pQueryMsg->interval.interval = htobe64(pQueryMsg->interval.interval);
  pQueryMsg->interval.sliding = htobe64(pQueryMsg->interval.sliding);
  pQueryMsg->interval.offset = htobe64(pQueryMsg->interval.offset);
6063 6064
  pQueryMsg->limit = htobe64(pQueryMsg->limit);
  pQueryMsg->offset = htobe64(pQueryMsg->offset);
H
Haojun Liao 已提交
6065
  pQueryMsg->vgroupLimit = htobe64(pQueryMsg->vgroupLimit);
H
hjxilinx 已提交
6066

6067 6068
  pQueryMsg->order = htons(pQueryMsg->order);
  pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
H
Haojun Liao 已提交
6069
  pQueryMsg->queryType = htonl(pQueryMsg->queryType);
weixin_48148422's avatar
weixin_48148422 已提交
6070
  pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
6071 6072

  pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
6073
  pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput);
H
hjxilinx 已提交
6074
  pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols);
6075
  pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen);
H
Haojun Liao 已提交
6076 6077 6078 6079
  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);
6080
  pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags);
H
Haojun Liao 已提交
6081
  pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6082
  pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput);
6083
  pQueryMsg->sqlstrLen = htonl(pQueryMsg->sqlstrLen);
6084
  pQueryMsg->prevResultLen = htonl(pQueryMsg->prevResultLen);
6085 6086
  pQueryMsg->sw.gap = htobe64(pQueryMsg->sw.gap);
  pQueryMsg->sw.primaryColId = htonl(pQueryMsg->sw.primaryColId);
H
Haojun Liao 已提交
6087 6088
  pQueryMsg->tableScanOperator = htonl(pQueryMsg->tableScanOperator);
  pQueryMsg->numOfOperator = htonl(pQueryMsg->numOfOperator);
6089

6090
  // query msg safety check
6091
  if (!validateQueryMsg(pQueryMsg)) {
6092 6093
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
6094 6095
  }

H
Haojun Liao 已提交
6096
  char *pMsg = (char *)(pQueryMsg->tableCols) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
H
hjxilinx 已提交
6097
  for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
H
Haojun Liao 已提交
6098
    SColumnInfo *pColInfo = &pQueryMsg->tableCols[col];
6099

H
hjxilinx 已提交
6100
    pColInfo->colId = htons(pColInfo->colId);
6101
    pColInfo->type = htons(pColInfo->type);
H
hjxilinx 已提交
6102
    pColInfo->bytes = htons(pColInfo->bytes);
6103
    pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters);
6104

6105 6106 6107 6108 6109
    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;
    }
6110

6111
    int32_t numOfFilters = pColInfo->flist.numOfFilters;
6112
    if (numOfFilters > 0) {
6113 6114
      pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo));
      if (pColInfo->flist.filterInfo == NULL) {
H
Haojun Liao 已提交
6115 6116 6117
        code = TSDB_CODE_QRY_OUT_OF_MEMORY;
        goto _cleanup;
      }
6118 6119
    }

6120 6121 6122
    code = deserializeColFilterInfo(pColInfo->flist.filterInfo, numOfFilters, &pMsg);
    if (code != TSDB_CODE_SUCCESS) {
      goto _cleanup;
6123 6124 6125
    }
  }

H
Haojun Liao 已提交
6126
  param->tableScanOperator = pQueryMsg->tableScanOperator;
H
Haojun Liao 已提交
6127 6128
  param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES);
  if (param->pExpr == NULL) {
H
Haojun Liao 已提交
6129 6130 6131 6132
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _cleanup;
  }

H
Haojun Liao 已提交
6133
  SSqlExpr *pExprMsg = (SSqlExpr *)pMsg;
6134

6135
  for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
H
Haojun Liao 已提交
6136
    param->pExpr[i] = pExprMsg;
6137

6138
    pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
6139
    pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6140
    pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6141
    pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6142 6143 6144 6145
    pExprMsg->colType       = htons(pExprMsg->colType);

    pExprMsg->resType       = htons(pExprMsg->resType);
    pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6146

H
Haojun Liao 已提交
6147 6148 6149
    pExprMsg->functionId    = htons(pExprMsg->functionId);
    pExprMsg->numOfParams   = htons(pExprMsg->numOfParams);
    pExprMsg->resColId      = htons(pExprMsg->resColId);
6150
    pExprMsg->flist.numOfFilters  = htons(pExprMsg->flist.numOfFilters);
H
Haojun Liao 已提交
6151
    pMsg += sizeof(SSqlExpr);
6152 6153

    for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6154 6155
      pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
      pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
6156

H
Haojun Liao 已提交
6157 6158 6159
      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.
6160
      } else {
H
Haojun Liao 已提交
6161
        pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
6162 6163 6164
      }
    }

H
Haojun Liao 已提交
6165 6166
    int16_t functionId = pExprMsg->functionId;
    if (functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG_DUMMY) {
Y
TD-1230  
yihaoDeng 已提交
6167
      if (!TSDB_COL_IS_TAG(pExprMsg->colInfo.flag)) {  // ignore the column  index check for arithmetic expression.
6168 6169
        code = TSDB_CODE_QRY_INVALID_MSG;
        goto _cleanup;
6170 6171 6172
      }
    }

6173 6174 6175 6176 6177
    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 已提交
6178
    pExprMsg = (SSqlExpr *)pMsg;
6179
  }
6180

H
Haojun Liao 已提交
6181
  if (pQueryMsg->secondStageOutput) {
H
Haojun Liao 已提交
6182 6183
    pExprMsg = (SSqlExpr *)pMsg;
    param->pSecExpr = calloc(pQueryMsg->secondStageOutput, POINTER_BYTES);
6184

H
Haojun Liao 已提交
6185
    for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) {
H
Haojun Liao 已提交
6186
      param->pSecExpr[i] = pExprMsg;
H
Haojun Liao 已提交
6187 6188 6189

      pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex);
      pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId);
H
Haojun Liao 已提交
6190
      pExprMsg->colInfo.flag  = htons(pExprMsg->colInfo.flag);
H
Haojun Liao 已提交
6191 6192
      pExprMsg->resType       = htons(pExprMsg->resType);
      pExprMsg->resBytes      = htons(pExprMsg->resBytes);
H
Haojun Liao 已提交
6193
      pExprMsg->colBytes      = htons(pExprMsg->colBytes);
H
Haojun Liao 已提交
6194
      pExprMsg->colType       = htons(pExprMsg->colType);
H
Haojun Liao 已提交
6195

H
Haojun Liao 已提交
6196 6197 6198
      pExprMsg->functionId = htons(pExprMsg->functionId);
      pExprMsg->numOfParams = htons(pExprMsg->numOfParams);

H
Haojun Liao 已提交
6199
      pMsg += sizeof(SSqlExpr);
H
Haojun Liao 已提交
6200 6201

      for (int32_t j = 0; j < pExprMsg->numOfParams; ++j) {
H
Haojun Liao 已提交
6202 6203
        pExprMsg->param[j].nType = htons(pExprMsg->param[j].nType);
        pExprMsg->param[j].nLen = htons(pExprMsg->param[j].nLen);
H
Haojun Liao 已提交
6204

H
Haojun Liao 已提交
6205 6206 6207
        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 已提交
6208
        } else {
H
Haojun Liao 已提交
6209
          pExprMsg->param[j].i64 = htobe64(pExprMsg->param[j].i64);
H
Haojun Liao 已提交
6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220
        }
      }

      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 已提交
6221
      pExprMsg = (SSqlExpr *)pMsg;
H
Haojun Liao 已提交
6222 6223 6224
    }
  }

6225
  pMsg = createTableIdList(pQueryMsg, pMsg, &(param->pTableIdList));
6226

H
hjxilinx 已提交
6227
  if (pQueryMsg->numOfGroupCols > 0) {  // group by tag columns
6228 6229
    param->pGroupColIndex = malloc(pQueryMsg->numOfGroupCols * sizeof(SColIndex));
    if (param->pGroupColIndex == NULL) {
6230 6231 6232
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6233 6234

    for (int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
6235 6236
      param->pGroupColIndex[i].colId = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colId);
6237

6238 6239
      param->pGroupColIndex[i].colIndex = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].colIndex);
6240

6241 6242
      param->pGroupColIndex[i].flag = htons(*(int16_t *)pMsg);
      pMsg += sizeof(param->pGroupColIndex[i].flag);
6243

6244 6245
      memcpy(param->pGroupColIndex[i].name, pMsg, tListLen(param->pGroupColIndex[i].name));
      pMsg += tListLen(param->pGroupColIndex[i].name);
6246
    }
6247

H
hjxilinx 已提交
6248 6249
    pQueryMsg->orderByIdx = htons(pQueryMsg->orderByIdx);
    pQueryMsg->orderType = htons(pQueryMsg->orderType);
6250 6251
  }

6252 6253
  pQueryMsg->fillType = htons(pQueryMsg->fillType);
  if (pQueryMsg->fillType != TSDB_FILL_NONE) {
6254
    pQueryMsg->fillVal = (uint64_t)(pMsg);
6255 6256

    int64_t *v = (int64_t *)pMsg;
6257
    for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) {
6258 6259
      v[i] = htobe64(v[i]);
    }
6260

6261
    pMsg += sizeof(int64_t) * pQueryMsg->numOfOutput;
6262
  }
6263

6264
  if (pQueryMsg->numOfTags > 0) {
6265 6266
    param->pTagColumnInfo = calloc(1, sizeof(SColumnInfo) * pQueryMsg->numOfTags);
    if (param->pTagColumnInfo == NULL) {
H
Haojun Liao 已提交
6267 6268 6269 6270
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6271 6272
    for (int32_t i = 0; i < pQueryMsg->numOfTags; ++i) {
      SColumnInfo* pTagCol = (SColumnInfo*) pMsg;
6273

6274 6275 6276
      pTagCol->colId = htons(pTagCol->colId);
      pTagCol->bytes = htons(pTagCol->bytes);
      pTagCol->type  = htons(pTagCol->type);
6277
      pTagCol->flist.numOfFilters = 0;
6278

6279
      param->pTagColumnInfo[i] = *pTagCol;
6280
      pMsg += sizeof(SColumnInfo);
6281
    }
H
hjxilinx 已提交
6282
  }
6283

6284 6285
  // the tag query condition expression string is located at the end of query msg
  if (pQueryMsg->tagCondLen > 0) {
6286 6287
    param->tagCond = calloc(1, pQueryMsg->tagCondLen);
    if (param->tagCond == NULL) {
H
Haojun Liao 已提交
6288 6289 6290
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }
6291 6292

    memcpy(param->tagCond, pMsg, pQueryMsg->tagCondLen);
6293 6294
    pMsg += pQueryMsg->tagCondLen;
  }
6295

6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306
  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 已提交
6307
  if (pQueryMsg->tbnameCondLen > 0) {
6308 6309
    param->tbnameCond = calloc(1, pQueryMsg->tbnameCondLen + 1);
    if (param->tbnameCond == NULL) {
6310 6311 6312 6313
      code = TSDB_CODE_QRY_OUT_OF_MEMORY;
      goto _cleanup;
    }

6314
    strncpy(param->tbnameCond, pMsg, pQueryMsg->tbnameCondLen);
H
Haojun Liao 已提交
6315
    pMsg += pQueryMsg->tbnameCondLen;
6316 6317
  }

D
dapan1121 已提交
6318
  //skip ts buf
H
Haojun Liao 已提交
6319 6320
  if ((pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen) > 0) {
    pMsg = (char *)pQueryMsg + pQueryMsg->tsBuf.tsOffset + pQueryMsg->tsBuf.tsLen;
D
dapan1121 已提交
6321 6322
  }

H
Haojun Liao 已提交
6323 6324 6325 6326 6327 6328 6329 6330
  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);
  }

6331
  param->sql = strndup(pMsg, pQueryMsg->sqlstrLen);
6332

H
Haojun Liao 已提交
6333
  SQueriedTableInfo info = { .numOfTags = pQueryMsg->numOfTags, .numOfCols = pQueryMsg->numOfCols, .colList = pQueryMsg->tableCols};
H
Haojun Liao 已提交
6334
  if (!validateQueryTableCols(&info, param->pExpr, pQueryMsg->numOfOutput, param->pTagColumnInfo, pQueryMsg)) {
6335 6336
    code = TSDB_CODE_QRY_INVALID_MSG;
    goto _cleanup;
weixin_48148422's avatar
weixin_48148422 已提交
6337
  }
6338

6339
  qDebug("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
H
Haojun Liao 已提交
6340 6341
         "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,
6342
         pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->interval.interval,
H
Haojun Liao 已提交
6343
         pQueryMsg->fillType, pQueryMsg->tsBuf.tsLen, pQueryMsg->tsBuf.tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
6344

6345
  qDebug("qmsg:%p, sql:%s", pQueryMsg, param->sql);
6346
  return TSDB_CODE_SUCCESS;
dengyihao's avatar
dengyihao 已提交
6347 6348

_cleanup:
6349
  freeParam(param);
6350
  return code;
6351 6352
}

H
Haojun Liao 已提交
6353 6354 6355 6356
  int32_t cloneExprFilterInfo(SColumnFilterInfo **dst, SColumnFilterInfo* src, int32_t filterNum) {
    if (filterNum <= 0) {
      return TSDB_CODE_SUCCESS;
    }
D
dapan1121 已提交
6357

H
Haojun Liao 已提交
6358 6359 6360 6361
    *dst = calloc(filterNum, sizeof(*src));
    if (*dst == NULL) {
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
D
dapan1121 已提交
6362

H
Haojun Liao 已提交
6363
    memcpy(*dst, src, sizeof(*src) * filterNum);
D
dapan1121 已提交
6364

H
Haojun Liao 已提交
6365 6366 6367
    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 已提交
6368

H
Haojun Liao 已提交
6369 6370 6371 6372 6373 6374
        if (pz == NULL) {
          if (i == 0) {
            free(*dst);
          } else {
            freeColumnFilterInfo(*dst, i);
          }
D
dapan1121 已提交
6375

H
Haojun Liao 已提交
6376 6377
          return TSDB_CODE_QRY_OUT_OF_MEMORY;
        }
D
dapan1121 已提交
6378

H
Haojun Liao 已提交
6379
        memcpy(pz, (void *)src->pz, (size_t)src->len + 1);
D
dapan1121 已提交
6380

H
Haojun Liao 已提交
6381 6382 6383
        (*dst)[i].pz = (int64_t)pz;
      }
    }
D
dapan1121 已提交
6384

H
Haojun Liao 已提交
6385 6386 6387
    return TSDB_CODE_SUCCESS;
  }

6388
int32_t buildArithmeticExprFromMsg(SExprInfo *pExprInfo, void *pQueryMsg) {
H
Haojun Liao 已提交
6389
  qDebug("qmsg:%p create arithmetic expr from binary", pQueryMsg);
weixin_48148422's avatar
weixin_48148422 已提交
6390 6391

  tExprNode* pExprNode = NULL;
dengyihao's avatar
dengyihao 已提交
6392
  TRY(TSDB_MAX_TAG_CONDITIONS) {
6393
    pExprNode = exprTreeFromBinary(pExprInfo->base.param[0].pz, pExprInfo->base.param[0].nLen);
weixin_48148422's avatar
weixin_48148422 已提交
6394 6395
  } CATCH( code ) {
    CLEANUP_EXECUTE();
6396
    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 已提交
6397 6398 6399
    return code;
  } END_TRY

H
hjxilinx 已提交
6400
  if (pExprNode == NULL) {
6401
    qError("qmsg:%p failed to create arithmetic expression string from:%s", pQueryMsg, pExprInfo->base.param[0].pz);
6402
    return TSDB_CODE_QRY_APP_ERROR;
6403
  }
6404

6405
  pExprInfo->pExpr = pExprNode;
6406 6407 6408
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6409 6410

static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs, int32_t numOfOutput, int32_t tagLen, bool superTable) {
H
Haojun Liao 已提交
6411 6412 6413 6414
  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 已提交
6415 6416
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
      if (j < 0 || j >= pTableInfo->numOfCols) {
H
Haojun Liao 已提交
6417 6418
        return TSDB_CODE_QRY_INVALID_MSG;
      } else {
H
Haojun Liao 已提交
6419 6420 6421
        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 已提交
6422 6423 6424 6425 6426 6427 6428 6429
        assert(ret == TSDB_CODE_SUCCESS);
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6430
// TODO tag length should be passed from client
H
Haojun Liao 已提交
6431 6432
int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExprInfo** pExprInfo,
                        SSqlExpr** pExprMsg, SColumnInfo* pTagCols, int32_t queryType, void* pMsg) {
6433
  *pExprInfo = NULL;
H
hjxilinx 已提交
6434
  int32_t code = TSDB_CODE_SUCCESS;
6435

6436
  SExprInfo *pExprs = (SExprInfo *)calloc(numOfOutput, sizeof(SExprInfo));
6437
  if (pExprs == NULL) {
6438
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
6439 6440
  }

H
Haojun Liao 已提交
6441
  bool    isSuperTable = QUERY_IS_STABLE_QUERY(queryType);
6442 6443
  int16_t tagLen = 0;

H
Haojun Liao 已提交
6444
  for (int32_t i = 0; i < numOfOutput; ++i) {
6445
    pExprs[i].base = *pExprMsg[i];
H
Haojun Liao 已提交
6446 6447 6448 6449 6450
    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]);
    }
6451 6452 6453 6454

    int16_t type = 0;
    int16_t bytes = 0;

6455
    // parse the arithmetic expression
6456
    if (pExprs[i].base.functionId == TSDB_FUNC_ARITHM) {
H
Haojun Liao 已提交
6457
      code = buildArithmeticExprFromMsg(&pExprs[i], pMsg);
6458

6459
      if (code != TSDB_CODE_SUCCESS) {
S
TD-1848  
Shengliang Guan 已提交
6460
        tfree(pExprs);
6461
        return code;
6462 6463
      }

6464
      type  = TSDB_DATA_TYPE_DOUBLE;
H
Haojun Liao 已提交
6465
      bytes = tDataTypes[type].bytes;
H
Haojun Liao 已提交
6466
    } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && pExprs[i].base.functionId == TSDB_FUNC_TAGPRJ) {  // parse the normal column
6467 6468 6469
      SSchema* s = tGetTbnameColumnSchema();
      type = s->type;
      bytes = s->bytes;
Y
yihaoDeng 已提交
6470 6471 6472 6473
    } else if (pExprs[i].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      SSchema s = tGetBlockDistColumnSchema(); 
      type = s.type;
      bytes = s.bytes;
H
Haojun Liao 已提交
6474
    } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) {
6475
      // it is a user-defined constant value column
H
Haojun Liao 已提交
6476 6477
      assert(pExprs[i].base.functionId == TSDB_FUNC_PRJ);

H
Haojun Liao 已提交
6478 6479
      type = pExprs[i].base.param[1].nType;
      bytes = pExprs[i].base.param[1].nLen;
H
Haojun Liao 已提交
6480 6481 6482 6483
      if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
        bytes += VARSTR_HEADER_SIZE;
      }
    } else {
H
Haojun Liao 已提交
6484
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
6485
      if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) {
H
Haojun Liao 已提交
6486
        if (j < TSDB_BLOCK_DIST_COLUMN_INDEX || j >= pTableInfo->numOfTags) {
6487 6488 6489
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      } else {
H
Haojun Liao 已提交
6490
        if (j < PRIMARYKEY_TIMESTAMP_COL_INDEX || j >= pTableInfo->numOfCols) {
6491 6492 6493
          return TSDB_CODE_QRY_INVALID_MSG;
        }
      }
H
Haojun Liao 已提交
6494

dengyihao's avatar
dengyihao 已提交
6495
      if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) {
H
Haojun Liao 已提交
6496
        SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j];
H
Haojun Liao 已提交
6497 6498 6499
        type = pCol->type;
        bytes = pCol->bytes;
      } else {
6500
        SSchema* s = tGetTbnameColumnSchema();
H
hjxilinx 已提交
6501

6502 6503
        type  = s->type;
        bytes = s->bytes;
H
Haojun Liao 已提交
6504
      }
D
dapan1121 已提交
6505

6506 6507 6508
      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 已提交
6509 6510 6511 6512
        if (ret) {
          return ret;
        }
      }
6513 6514
    }

H
Haojun Liao 已提交
6515
    int32_t param = (int32_t)pExprs[i].base.param[0].i64;
H
Haojun Liao 已提交
6516
    if (pExprs[i].base.functionId != TSDB_FUNC_ARITHM &&
H
Haojun Liao 已提交
6517
       (type != pExprs[i].base.colType || bytes != pExprs[i].base.colBytes)) {
H
Haojun Liao 已提交
6518 6519 6520 6521
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6522 6523
    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 已提交
6524
      tfree(pExprs);
6525
      return TSDB_CODE_QRY_INVALID_MSG;
6526 6527
    }

6528
    if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
H
Haojun Liao 已提交
6529
      tagLen += pExprs[i].base.resBytes;
6530
    }
6531

H
Haojun Liao 已提交
6532
    assert(isValidDataType(pExprs[i].base.resType));
6533 6534
  }

H
Haojun Liao 已提交
6535
  // the tag length is affected by other tag columns, so this should be update.
H
Haojun Liao 已提交
6536
  updateOutputBufForTopBotQuery(pTableInfo, pTagCols, pExprs, numOfOutput, tagLen, isSuperTable);
6537

6538
  *pExprInfo = pExprs;
6539 6540 6541
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6542
// todo refactor
H
Haojun Liao 已提交
6543 6544
int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo,
                                           SSqlExpr** pExpr, SExprInfo* prevExpr) {
H
Haojun Liao 已提交
6545 6546 6547 6548 6549 6550 6551 6552
  *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 已提交
6553
  bool isSuperTable = QUERY_IS_STABLE_QUERY(pQueryMsg->queryType);
H
Haojun Liao 已提交
6554 6555

  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
6556
    pExprs[i].base = *pExpr[i];
H
Haojun Liao 已提交
6557 6558 6559 6560 6561 6562
    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 已提交
6563
    pExprs[i].base.resType = 0;
H
Haojun Liao 已提交
6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582

    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 已提交
6583 6584
      type  = prevExpr[index].base.resType;
      bytes = prevExpr[index].base.resBytes;
H
Haojun Liao 已提交
6585 6586
    }

H
Haojun Liao 已提交
6587 6588 6589
    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 已提交
6590 6591 6592 6593
      tfree(pExprs);
      return TSDB_CODE_QRY_INVALID_MSG;
    }

H
Haojun Liao 已提交
6594
    assert(isValidDataType(pExprs[i].base.resType));
H
Haojun Liao 已提交
6595 6596 6597 6598 6599 6600
  }

  *pExprInfo = pExprs;
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
6601
SSqlGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code) {
6602 6603 6604 6605 6606
  if (pQueryMsg->numOfGroupCols == 0) {
    return NULL;
  }

  // using group by tag columns
6607
  SSqlGroupbyExpr *pGroupbyExpr = (SSqlGroupbyExpr *)calloc(1, sizeof(SSqlGroupbyExpr));
6608
  if (pGroupbyExpr == NULL) {
6609
    *code = TSDB_CODE_QRY_OUT_OF_MEMORY;
6610 6611 6612 6613 6614 6615 6616
    return NULL;
  }

  pGroupbyExpr->numOfGroupCols = pQueryMsg->numOfGroupCols;
  pGroupbyExpr->orderType = pQueryMsg->orderType;
  pGroupbyExpr->orderIndex = pQueryMsg->orderByIdx;

6617 6618 6619 6620
  pGroupbyExpr->columnInfo = taosArrayInit(pQueryMsg->numOfGroupCols, sizeof(SColIndex));
  for(int32_t i = 0; i < pQueryMsg->numOfGroupCols; ++i) {
    taosArrayPush(pGroupbyExpr->columnInfo, &pColIndex[i]);
  }
6621

6622 6623 6624
  return pGroupbyExpr;
}

6625 6626 6627 6628
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 已提交
6629 6630
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }
6631

6632 6633 6634
  for (int32_t i = 0, j = 0; i < numOfCols; ++i) {
    if (pCols[i].flist.numOfFilters > 0) {
      SSingleColumnFilterInfo* pFilter = &((*pFilterInfo)[j]);
6635

6636 6637
      memcpy(&pFilter->info, &pCols[i], sizeof(SColumnInfo));
      pFilter->info = pCols[i];
6638

6639 6640 6641
      pFilter->numOfFilters = pCols[i].flist.numOfFilters;
      pFilter->pFilters = calloc(pFilter->numOfFilters, sizeof(SColumnFilterElem));
      if (pFilter->pFilters == NULL) {
H
Haojun Liao 已提交
6642 6643
        return TSDB_CODE_QRY_OUT_OF_MEMORY;
      }
6644

6645 6646 6647
      for (int32_t f = 0; f < pFilter->numOfFilters; ++f) {
        SColumnFilterElem* pSingleColFilter = &pFilter->pFilters[f];
        pSingleColFilter->filterInfo = pCols[i].flist.filterInfo[f];
6648 6649 6650 6651

        int32_t lower = pSingleColFilter->filterInfo.lowerRelOptr;
        int32_t upper = pSingleColFilter->filterInfo.upperRelOptr;
        if (lower == TSDB_RELATION_INVALID && upper == TSDB_RELATION_INVALID) {
H
Haojun Liao 已提交
6652
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6653
          return TSDB_CODE_QRY_INVALID_MSG;
6654 6655
        }

6656 6657
        pSingleColFilter->fp = getFilterOperator(lower, upper);
        if (pSingleColFilter->fp == NULL) {
H
Haojun Liao 已提交
6658
          qError("QInfo:0x%"PRIx64" invalid filter info", qId);
6659
          return TSDB_CODE_QRY_INVALID_MSG;
6660 6661
        }

6662
        pSingleColFilter->bytes = pCols[i].bytes;
6663 6664 6665 6666 6667 6668 6669 6670 6671
      }

      j++;
    }
  }

  return TSDB_CODE_SUCCESS;
}

6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699
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 已提交
6700 6701
static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) {
  assert(pQueryAttr->pExpr1 != NULL && pQueryAttr != NULL);
6702

H
Haojun Liao 已提交
6703 6704
  for (int32_t k = 0; k < pQueryAttr->numOfOutput; ++k) {
    SSqlExpr *pSqlExprMsg = &pQueryAttr->pExpr1[k].base;
6705
    if (pSqlExprMsg->functionId == TSDB_FUNC_ARITHM) {
6706 6707
      continue;
    }
6708

6709
    // todo opt performance
H
Haojun Liao 已提交
6710
    SColIndex *pColIndex = &pSqlExprMsg->colInfo;
H
Haojun Liao 已提交
6711
    if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) {
6712
      int32_t f = 0;
H
Haojun Liao 已提交
6713
      for (f = 0; f < pQueryAttr->numOfCols; ++f) {
H
Haojun Liao 已提交
6714
        if (pColIndex->colId == pQueryAttr->tableCols[f].colId) {
H
Haojun Liao 已提交
6715
          pColIndex->colIndex = f;
6716 6717 6718
          break;
        }
      }
H
Haojun Liao 已提交
6719

H
Haojun Liao 已提交
6720
      assert(f < pQueryAttr->numOfCols);
6721 6722
    } else if (pColIndex->colId <= TSDB_UD_COLUMN_INDEX) {
      // do nothing for user-defined constant value result columns
H
Haojun Liao 已提交
6723 6724
    } else if (pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX) {
      pColIndex->colIndex = 0;// only one source column, so it must be 0;
H
Haojun Liao 已提交
6725
      assert(pQueryAttr->numOfOutput == 1);
6726
    } else {
6727
      int32_t f = 0;
H
Haojun Liao 已提交
6728 6729
      for (f = 0; f < pQueryAttr->numOfTags; ++f) {
        if (pColIndex->colId == pQueryAttr->tagColList[f].colId) {
H
Haojun Liao 已提交
6730
          pColIndex->colIndex = f;
6731 6732
          break;
        }
6733
      }
6734

H
Haojun Liao 已提交
6735
      assert(f < pQueryAttr->numOfTags || pColIndex->colId == TSDB_TBNAME_COLUMN_INDEX || pColIndex->colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6736 6737 6738 6739
    }
  }
}

H
Haojun Liao 已提交
6740
void setResultBufSize(SQueryAttr* pQueryAttr, SRspResultInfo* pResultInfo) {
H
Haojun Liao 已提交
6741 6742 6743 6744 6745 6746 6747
  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 已提交
6748

H
Haojun Liao 已提交
6749 6750
  if (isProjQuery(pQueryAttr)) {
    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQueryAttr->resultRowSize;
H
Haojun Liao 已提交
6751 6752
    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
6753
    }
H
Haojun Liao 已提交
6754

H
Haojun Liao 已提交
6755
    pResultInfo->capacity  = numOfRes;
6756
  } else {  // in case of non-prj query, a smaller output buffer will be used.
H
Haojun Liao 已提交
6757
    pResultInfo->capacity = DEFAULT_MIN_ROWS;
6758
  }
H
Haojun Liao 已提交
6759 6760 6761

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
  pResultInfo->total = 0;
H
Haojun Liao 已提交
6762 6763
}

D
fix bug  
dapan1121 已提交
6764 6765 6766 6767
FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) {
  return ((SQInfo *)qHandle)->qId == qId;
}

H
Haojun Liao 已提交
6768
SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SSqlGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs,
H
Haojun Liao 已提交
6769
                        SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId,
D
dapan1121 已提交
6770
                        char* sql, uint64_t *qId) {
B
Bomin Zhang 已提交
6771 6772 6773
  int16_t numOfCols = pQueryMsg->numOfCols;
  int16_t numOfOutput = pQueryMsg->numOfOutput;

6774 6775
  SQInfo *pQInfo = (SQInfo *)calloc(1, sizeof(SQInfo));
  if (pQInfo == NULL) {
B
Bomin Zhang 已提交
6776
    goto _cleanup_qinfo;
6777
  }
6778

D
dapan1121 已提交
6779 6780
  pQInfo->qId = *qId;

B
Bomin Zhang 已提交
6781 6782
  // to make sure third party won't overwrite this structure
  pQInfo->signature = pQInfo;
H
Haojun Liao 已提交
6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817
  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 已提交
6818 6819
  pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo));
  if (pQueryAttr->tableCols == NULL) {
6820
    goto _cleanup;
6821
  }
6822

H
Haojun Liao 已提交
6823 6824
  pQueryAttr->srcRowSize = 0;
  pQueryAttr->maxTableColumnWidth = 0;
H
hjxilinx 已提交
6825
  for (int16_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
6826
    pQueryAttr->tableCols[i] = pQueryMsg->tableCols[i];
6827
    pQueryAttr->tableCols[i].flist.filterInfo = tFilterInfoDup(pQueryMsg->tableCols[i].flist.filterInfo, pQueryAttr->tableCols[i].flist.numOfFilters);
6828

H
Haojun Liao 已提交
6829 6830 6831
    pQueryAttr->srcRowSize += pQueryAttr->tableCols[i].bytes;
    if (pQueryAttr->maxTableColumnWidth < pQueryAttr->tableCols[i].bytes) {
      pQueryAttr->maxTableColumnWidth = pQueryAttr->tableCols[i].bytes;
6832
    }
H
hjxilinx 已提交
6833
  }
6834

6835
  // calculate the result row size
6836
  for (int16_t col = 0; col < numOfOutput; ++col) {
H
Haojun Liao 已提交
6837
    assert(pExprs[col].base.resBytes > 0);
H
Haojun Liao 已提交
6838
    pQueryAttr->resultRowSize += pExprs[col].base.resBytes;
6839 6840 6841

    // keep the tag length
    if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) {
H
Haojun Liao 已提交
6842
      pQueryAttr->tagLen += pExprs[col].base.resBytes;
6843
    }
D
dapan1121 已提交
6844

6845
    if (pExprs[col].base.flist.filterInfo) {
H
Haojun Liao 已提交
6846
      ++pQueryAttr->havingNum;
D
dapan1121 已提交
6847
    }
6848
  }
6849

H
Haojun Liao 已提交
6850
  doUpdateExprColumnIndex(pQueryAttr);
H
Haojun Liao 已提交
6851
  int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId);
6852
  if (ret != TSDB_CODE_SUCCESS) {
6853
    goto _cleanup;
6854 6855
  }

H
Haojun Liao 已提交
6856 6857 6858
  if (pQueryAttr->fillType != TSDB_FILL_NONE) {
    pQueryAttr->fillVal = malloc(sizeof(int64_t) * pQueryAttr->numOfOutput);
    if (pQueryAttr->fillVal == NULL) {
6859
      goto _cleanup;
6860 6861 6862
    }

    // the first column is the timestamp
H
Haojun Liao 已提交
6863
    memcpy(pQueryAttr->fillVal, (char *)pQueryMsg->fillVal, pQueryAttr->numOfOutput * sizeof(int64_t));
6864 6865
  }

dengyihao's avatar
dengyihao 已提交
6866 6867 6868
  size_t numOfGroups = 0;
  if (pTableGroupInfo->pGroupList != NULL) {
    numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList);
H
Haojun Liao 已提交
6869
    STableGroupInfo* pTableqinfo = &pQInfo->runtimeEnv.tableqinfoGroupInfo;
dengyihao's avatar
dengyihao 已提交
6870

6871 6872 6873
    pTableqinfo->pGroupList = taosArrayInit(numOfGroups, POINTER_BYTES);
    pTableqinfo->numOfTables = pTableGroupInfo->numOfTables;
    pTableqinfo->map = taosHashInit(pTableGroupInfo->numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
6874
  }
H
Haojun Liao 已提交
6875

H
Haojun Liao 已提交
6876
  pQInfo->pBuf = calloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
6877 6878 6879 6880
  if (pQInfo->pBuf == NULL) {
    goto _cleanup;
  }

6881
  pQInfo->dataReady = QUERY_RESULT_NOT_READY;
H
Haojun Liao 已提交
6882
  pQInfo->rspContext = NULL;
6883
  pQInfo->sql = sql;
6884
  pthread_mutex_init(&pQInfo->lock, NULL);
H
Haojun Liao 已提交
6885
  tsem_init(&pQInfo->ready, 0, 0);
6886

H
Haojun Liao 已提交
6887 6888
  pQueryAttr->window = pQueryMsg->window;
  changeExecuteScanOrder(pQInfo, pQueryMsg, pQueryAttr->stableQuery);
6889

H
Haojun Liao 已提交
6890
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
6891
  STimeWindow window = pQueryAttr->window;
H
Haojun Liao 已提交
6892

H
Haojun Liao 已提交
6893
  int32_t index = 0;
H
hjxilinx 已提交
6894
  for(int32_t i = 0; i < numOfGroups; ++i) {
H
Haojun Liao 已提交
6895
    SArray* pa = taosArrayGetP(pQueryAttr->tableGroupInfo.pGroupList, i);
6896

H
Haojun Liao 已提交
6897
    size_t s = taosArrayGetSize(pa);
6898
    SArray* p1 = taosArrayInit(s, POINTER_BYTES);
B
Bomin Zhang 已提交
6899 6900 6901
    if (p1 == NULL) {
      goto _cleanup;
    }
H
Haojun Liao 已提交
6902

H
Haojun Liao 已提交
6903
    taosArrayPush(pRuntimeEnv->tableqinfoGroupInfo.pGroupList, &p1);
6904

H
hjxilinx 已提交
6905
    for(int32_t j = 0; j < s; ++j) {
H
Haojun Liao 已提交
6906
      STableKeyInfo* info = taosArrayGet(pa, j);
6907
      window.skey = info->lastKey;
6908 6909

      void* buf = (char*) pQInfo->pBuf + index * sizeof(STableQueryInfo);
H
Haojun Liao 已提交
6910
      STableQueryInfo* item = createTableQueryInfo(pQueryAttr, info->pTable, pQueryAttr->groupbyColumn, window, buf);
B
Bomin Zhang 已提交
6911 6912 6913
      if (item == NULL) {
        goto _cleanup;
      }
H
Haojun Liao 已提交
6914

6915
      item->groupIndex = i;
H
hjxilinx 已提交
6916
      taosArrayPush(p1, &item);
6917 6918

      STableId* id = TSDB_TABLEID(info->pTable);
H
Haojun Liao 已提交
6919
      taosHashPut(pRuntimeEnv->tableqinfoGroupInfo.map, &id->tid, sizeof(id->tid), &item, POINTER_BYTES);
H
Haojun Liao 已提交
6920
      index += 1;
H
hjxilinx 已提交
6921 6922
    }
  }
6923

H
Haojun Liao 已提交
6924
  colIdCheck(pQueryAttr, pQInfo->qId);
6925

6926
  // todo refactor
H
Haojun Liao 已提交
6927
  pQInfo->query.queryBlockDist = (numOfOutput == 1 && pExprs[0].base.colInfo.colId == TSDB_BLOCK_DIST_COLUMN_INDEX);
6928

H
Haojun Liao 已提交
6929
  qDebug("qmsg:%p QInfo:0x%" PRIx64 "-%p created", pQueryMsg, pQInfo->qId, pQInfo);
6930 6931
  return pQInfo;

B
Bomin Zhang 已提交
6932
_cleanup_qinfo:
H
Haojun Liao 已提交
6933
  tsdbDestroyTableGroup(pTableGroupInfo);
B
Bomin Zhang 已提交
6934

6935 6936 6937 6938
  if (pGroupbyExpr != NULL) {
    taosArrayDestroy(pGroupbyExpr->columnInfo);
    free(pGroupbyExpr);
  }
H
Haojun Liao 已提交
6939

S
TD-1848  
Shengliang Guan 已提交
6940
  tfree(pTagCols);
B
Bomin Zhang 已提交
6941 6942 6943
  for (int32_t i = 0; i < numOfOutput; ++i) {
    SExprInfo* pExprInfo = &pExprs[i];
    if (pExprInfo->pExpr != NULL) {
H
Haojun Liao 已提交
6944 6945
      tExprTreeDestroy(pExprInfo->pExpr, NULL);
      pExprInfo->pExpr = NULL;
B
Bomin Zhang 已提交
6946
    }
D
dapan1121 已提交
6947

6948 6949
    if (pExprInfo->base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo->base.flist.filterInfo, pExprInfo->base.flist.numOfFilters);
D
dapan1121 已提交
6950
    }
B
Bomin Zhang 已提交
6951
  }
H
Haojun Liao 已提交
6952

S
TD-1848  
Shengliang Guan 已提交
6953
  tfree(pExprs);
B
Bomin Zhang 已提交
6954

6955
_cleanup:
dengyihao's avatar
dengyihao 已提交
6956
  freeQInfo(pQInfo);
6957 6958 6959
  return NULL;
}

H
Haojun Liao 已提交
6960
bool isValidQInfo(void *param) {
H
hjxilinx 已提交
6961 6962 6963 6964
  SQInfo *pQInfo = (SQInfo *)param;
  if (pQInfo == NULL) {
    return false;
  }
6965

H
hjxilinx 已提交
6966 6967 6968 6969
  /*
   * pQInfo->signature may be changed by another thread, so we assign value of signature
   * into local variable, then compare by using local variable
   */
6970
  uint64_t sig = (uint64_t)pQInfo->signature;
H
hjxilinx 已提交
6971 6972 6973
  return (sig == (uint64_t)pQInfo);
}

H
Haojun Liao 已提交
6974
int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start,
H
Haojun Liao 已提交
6975
                  int32_t prevResultLen, void* merger) {
H
hjxilinx 已提交
6976
  int32_t code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
6977 6978

  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
6979 6980
  pRuntimeEnv->qinfo = pQInfo;

H
Haojun Liao 已提交
6981
  SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
6982

6983
  STSBuf *pTsBuf = NULL;
H
Haojun Liao 已提交
6984 6985
  if (pTsBufInfo->tsLen > 0) { // open new file to save the result
    char *tsBlock = start + pTsBufInfo->tsOffset;
H
Haojun Liao 已提交
6986
    pTsBuf = tsBufCreateFromCompBlocks(tsBlock, pTsBufInfo->tsNumOfBlocks, pTsBufInfo->tsLen, pTsBufInfo->tsOrder,
H
Haojun Liao 已提交
6987
        pQueryAttr->vgId);
6988

6989 6990
    tsBufResetPos(pTsBuf);
    bool ret = tsBufNextPos(pTsBuf);
dengyihao's avatar
dengyihao 已提交
6991
    UNUSED(ret);
H
hjxilinx 已提交
6992
  }
6993

6994
  SArray* prevResult = NULL;
H
Haojun Liao 已提交
6995 6996
  if (prevResultLen > 0) {
    prevResult = interResFromBinary(param->prevResult, prevResultLen);
6997 6998
  }

H
Haojun Liao 已提交
6999
  if (tsdb != NULL) {
H
Haojun Liao 已提交
7000
    pQueryAttr->precision = tsdbGetCfg(tsdb)->precision;
H
Haojun Liao 已提交
7001
  }
7002

H
Haojun Liao 已提交
7003 7004
  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 已提交
7005
    qDebug("QInfo:0x%"PRIx64" no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo->qId, pQueryAttr->window.skey,
H
Haojun Liao 已提交
7006
           pQueryAttr->window.ekey, pQueryAttr->order.order);
H
Haojun Liao 已提交
7007
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
H
Haojun Liao 已提交
7008
    pRuntimeEnv->tableqinfoGroupInfo.numOfTables = 0;
7009
    // todo free memory
7010 7011
    return TSDB_CODE_SUCCESS;
  }
7012

H
Haojun Liao 已提交
7013
  if (pRuntimeEnv->tableqinfoGroupInfo.numOfTables == 0) {
H
Haojun Liao 已提交
7014
    qDebug("QInfo:0x%"PRIx64" no table qualified for tag filter, abort query", pQInfo->qId);
H
Haojun Liao 已提交
7015
    setQueryStatus(pRuntimeEnv, QUERY_COMPLETED);
7016 7017
    return TSDB_CODE_SUCCESS;
  }
H
hjxilinx 已提交
7018 7019

  // filter the qualified
H
Haojun Liao 已提交
7020
  if ((code = doInitQInfo(pQInfo, pTsBuf, prevResult, tsdb, sourceOptr, param->tableScanOperator, param->pOperator, merger)) != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
7021 7022
    goto _error;
  }
7023

H
hjxilinx 已提交
7024 7025 7026 7027
  return code;

_error:
  // table query ref will be decrease during error handling
7028
  freeQInfo(pQInfo);
H
hjxilinx 已提交
7029 7030 7031
  return code;
}

7032
//TODO refactor
H
Haojun Liao 已提交
7033
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
H
Haojun Liao 已提交
7034
    if (pFilter == NULL || numOfFilters == 0) {
B
Bomin Zhang 已提交
7035 7036
      return;
    }
H
Haojun Liao 已提交
7037

B
Bomin Zhang 已提交
7038
    for (int32_t i = 0; i < numOfFilters; i++) {
D
dapan1121 已提交
7039
      if (pFilter[i].filterstr && pFilter[i].pz) {
B
Bomin Zhang 已提交
7040 7041 7042
        free((void*)(pFilter[i].pz));
      }
    }
H
Haojun Liao 已提交
7043

B
Bomin Zhang 已提交
7044 7045 7046
    free(pFilter);
}

H
Haojun Liao 已提交
7047 7048
static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
H
Haojun Liao 已提交
7049
    int32_t numOfGroups = (int32_t) taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
H
Haojun Liao 已提交
7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070
    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 已提交
7071 7072 7073 7074 7075 7076 7077 7078
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 已提交
7079
      tExprTreeDestroy(pExprInfo[i].pExpr, NULL);
H
Haojun Liao 已提交
7080
    }
D
dapan1121 已提交
7081

7082 7083
    if (pExprInfo[i].base.flist.filterInfo) {
      freeColumnFilterInfo(pExprInfo[i].base.flist.filterInfo, pExprInfo[i].base.flist.numOfFilters);
D
dapan1121 已提交
7084
    }
H
Haojun Liao 已提交
7085 7086 7087 7088

    for(int32_t j = 0; j < pExprInfo[i].base.numOfParams; ++j) {
      tVariantDestroy(&pExprInfo[i].base.param[j]);
    }
H
Haojun Liao 已提交
7089 7090 7091 7092 7093 7094
  }

  tfree(pExprInfo);
  return NULL;
}

H
Haojun Liao 已提交
7095
void freeQInfo(SQInfo *pQInfo) {
H
hjxilinx 已提交
7096 7097 7098
  if (!isValidQInfo(pQInfo)) {
    return;
  }
7099

H
Haojun Liao 已提交
7100
  qDebug("QInfo:0x%"PRIx64" start to free QInfo", pQInfo->qId);
7101

H
Haojun Liao 已提交
7102
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7103
  releaseQueryBuf(pRuntimeEnv->tableqinfoGroupInfo.numOfTables);
D
dapan1121 已提交
7104 7105

  doDestroyTableQueryInfo(&pRuntimeEnv->tableqinfoGroupInfo);
7106
  teardownQueryRuntimeEnv(&pQInfo->runtimeEnv);
7107

H
Haojun Liao 已提交
7108
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
7109
  freeQueryAttr(pQueryAttr);
7110

7111 7112
  tsdbDestroyTableGroup(&pQueryAttr->tableGroupInfo);

S
TD-1848  
Shengliang Guan 已提交
7113
  tfree(pQInfo->pBuf);
7114 7115
  tfree(pQInfo->sql);

H
Haojun Liao 已提交
7116
  taosArrayDestroy(pRuntimeEnv->groupResInfo.pRows);
7117
  pQInfo->signature = 0;
7118

H
Haojun Liao 已提交
7119
  qDebug("QInfo:0x%"PRIx64" QInfo is freed", pQInfo->qId);
7120

S
TD-1848  
Shengliang Guan 已提交
7121
  tfree(pQInfo);
H
hjxilinx 已提交
7122 7123
}

H
Haojun Liao 已提交
7124
int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) {
H
hjxilinx 已提交
7125
  // the remained number of retrieved rows, not the interpolated result
H
Haojun Liao 已提交
7126
  SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv;
H
Haojun Liao 已提交
7127
  SQueryAttr *pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
7128

H
hjxilinx 已提交
7129
  // load data from file to msg buffer
H
Haojun Liao 已提交
7130
  if (pQueryAttr->tsCompQuery) {
H
Haojun Liao 已提交
7131 7132
    SColumnInfoData* pColInfoData = taosArrayGet(pRuntimeEnv->outputBuf->pDataBlock, 0);
    FILE *f = *(FILE **)pColInfoData->pData;  // TODO refactor
7133

H
hjxilinx 已提交
7134
    // make sure file exist
D
fix bug  
dapan1121 已提交
7135 7136
    if (f) {
      off_t s = lseek(fileno(f), 0, SEEK_END);
H
Haojun Liao 已提交
7137
      assert(s == pRuntimeEnv->outputBuf->info.rows);
7138

H
Haojun Liao 已提交
7139
      qDebug("QInfo:0x%"PRIx64" ts comp data return, file:%p, size:%"PRId64, pQInfo->qId, f, (uint64_t)s);
D
fix bug  
dapan1121 已提交
7140 7141
      if (fseek(f, 0, SEEK_SET) >= 0) {
        size_t sz = fread(data, 1, s, f);
7142
        if(sz < s) {  // todo handle error
D
fix bug  
dapan1121 已提交
7143
          qError("fread(f:%p,%d) failed, rsize:%" PRId64 ", expect size:%" PRId64, f, fileno(f), (uint64_t)sz, (uint64_t)s);
7144 7145
          assert(0);
        }
H
Haojun Liao 已提交
7146
      } else {
7147
        UNUSED(s);
D
dapan1121 已提交
7148 7149 7150 7151
        qError("fseek(f:%p,%d) failed, error:%s", f, fileno(f), strerror(errno));
        assert(0);
      }

H
Haojun Liao 已提交
7152
      // dump error info
D
dapan1121 已提交
7153 7154 7155
      if (s <= (sizeof(STSBufFileHeader) + sizeof(STSGroupBlockInfo) + 6 * sizeof(int32_t))) {
        qDump(data, s);
        assert(0);
dengyihao's avatar
dengyihao 已提交
7156
      }
H
Haojun Liao 已提交
7157

D
fix bug  
dapan1121 已提交
7158
      fclose(f);
D
dapan1121 已提交
7159
      *(FILE **)pColInfoData->pData = NULL;
H
hjxilinx 已提交
7160
    }
7161

H
hjxilinx 已提交
7162
    // all data returned, set query over
H
Haojun Liao 已提交
7163 7164
    if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)) {
      setQueryStatus(pRuntimeEnv, QUERY_OVER);
H
hjxilinx 已提交
7165
    }
H
hjxilinx 已提交
7166
  } else {
H
Haojun Liao 已提交
7167
    doCopyQueryResultToMsg(pQInfo, (int32_t)pRuntimeEnv->outputBuf->info.rows, data);
7168
  }
7169

H
Haojun Liao 已提交
7170
  pRuntimeEnv->resultInfo.total += pRuntimeEnv->outputBuf->info.rows;
H
Haojun Liao 已提交
7171
  qDebug("QInfo:0x%"PRIx64" current numOfRes rows:%d, total:%" PRId64, pQInfo->qId,
H
Haojun Liao 已提交
7172
         pRuntimeEnv->outputBuf->info.rows, pRuntimeEnv->resultInfo.total);
7173

H
Haojun Liao 已提交
7174
  if (pQueryAttr->limit.limit > 0 && pQueryAttr->limit.limit == pRuntimeEnv->resultInfo.total) {
H
Haojun Liao 已提交
7175
    qDebug("QInfo:0x%"PRIx64" results limitation reached, limitation:%"PRId64, pQInfo->qId, pQueryAttr->limit.limit);
H
Haojun Liao 已提交
7176
    setQueryStatus(pRuntimeEnv, QUERY_OVER);
7177
  }
7178

H
hjxilinx 已提交
7179
  return TSDB_CODE_SUCCESS;
7180 7181
}

H
Haojun Liao 已提交
7182
bool doBuildResCheck(SQInfo* pQInfo) {
7183 7184 7185 7186 7187
  bool buildRes = false;

  pthread_mutex_lock(&pQInfo->lock);

  pQInfo->dataReady = QUERY_RESULT_READY;
7188
  buildRes = needBuildResAfterQueryComplete(pQInfo);
7189

H
Haojun Liao 已提交
7190 7191
  // 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 已提交
7192
  assert(pQInfo->owner == taosGetSelfPthreadId());
7193
  pQInfo->owner = 0;
H
Haojun Liao 已提交
7194

H
Haojun Liao 已提交
7195
  pthread_mutex_unlock(&pQInfo->lock);
H
Haojun Liao 已提交
7196

7197
  // used in retrieve blocking model.
H
Haojun Liao 已提交
7198
  tsem_post(&pQInfo->ready);
7199 7200 7201
  return buildRes;
}

H
Haojun Liao 已提交
7202 7203 7204 7205
static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
7206 7207
  }

7208 7209 7210
  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 已提交
7211
      int32_t len = bytes - VARSTR_HEADER_SIZE;   // remain available space
7212 7213 7214 7215 7216
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
7217
  } else {
H
Haojun Liao 已提交
7218
    memcpy(output, val, bytes);
7219 7220 7221
  }
}

H
Haojun Liao 已提交
7222
static int64_t getQuerySupportBufSize(size_t numOfTables) {
H
Haojun Liao 已提交
7223 7224 7225 7226
  size_t s1 = sizeof(STableQueryInfo);
  size_t s2 = sizeof(SHashNode);

//  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
H
Haojun Liao 已提交
7227
  return (int64_t)((s1 + s2) * 1.5 * numOfTables);
H
Haojun Liao 已提交
7228 7229
}

H
Haojun Liao 已提交
7230
int32_t checkForQueryBuf(size_t numOfTables) {
H
Haojun Liao 已提交
7231
  int64_t t = getQuerySupportBufSize(numOfTables);
7232
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7233
    return TSDB_CODE_SUCCESS;
7234
  } else if (tsQueryBufferSizeBytes > 0) {
H
Haojun Liao 已提交
7235 7236

    while(1) {
7237
      int64_t s = tsQueryBufferSizeBytes;
H
Haojun Liao 已提交
7238 7239
      int64_t remain = s - t;
      if (remain >= 0) {
7240
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
H
Haojun Liao 已提交
7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252
          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 已提交
7253
void releaseQueryBuf(size_t numOfTables) {
7254
  if (tsQueryBufferSizeBytes < 0) {
H
Haojun Liao 已提交
7255 7256 7257 7258 7259 7260
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
7261
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
H
Haojun Liao 已提交
7262
}
7263 7264 7265 7266 7267 7268 7269

void freeQueryAttr(SQueryAttr* pQueryAttr) {
  if (pQueryAttr != NULL) {
    if (pQueryAttr->fillVal != NULL) {
      tfree(pQueryAttr->fillVal);
    }

H
Haojun Liao 已提交
7270
    pQueryAttr->pFilterInfo = doDestroyFilterInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols);
7271 7272 7273

    pQueryAttr->pExpr1 = destroyQueryFuncExpr(pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
    pQueryAttr->pExpr2 = destroyQueryFuncExpr(pQueryAttr->pExpr2, pQueryAttr->numOfExpr2);
H
Haojun Liao 已提交
7274
    pQueryAttr->pExpr3 = destroyQueryFuncExpr(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3);
7275 7276 7277 7278

    tfree(pQueryAttr->tagColList);
    tfree(pQueryAttr->pFilterInfo);

H
Haojun Liao 已提交
7279
    if (pQueryAttr->tableCols != NULL) {
7280
      for (int32_t i = 0; i < pQueryAttr->numOfCols; i++) {
H
Haojun Liao 已提交
7281
        SColumnInfo* column = pQueryAttr->tableCols + i;
7282
        freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters);
7283
      }
H
Haojun Liao 已提交
7284
      tfree(pQueryAttr->tableCols);
7285 7286 7287 7288 7289 7290 7291 7292 7293
    }

    if (pQueryAttr->pGroupbyExpr != NULL) {
      taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo);
      tfree(pQueryAttr->pGroupbyExpr);
    }
  }
}