tsdbRead.c 140.5 KB
Newer Older
H
hjxilinx 已提交
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/>.
 */

dengyihao's avatar
dengyihao 已提交
16
#include "vnodeInt.h"
17

dengyihao's avatar
dengyihao 已提交
18 19
#define EXTRA_BYTES                2
#define ASCENDING_TRAVERSE(o)      (o == TSDB_ORDER_ASC)
20
#define QH_GET_NUM_OF_COLS(handle) ((size_t)(taosArrayGetSize((handle)->pColumns)))
H
hjxilinx 已提交
21

H
Haojun Liao 已提交
22 23 24 25
#define GET_FILE_DATA_BLOCK_INFO(_checkInfo, _block)                                   \
  ((SDataBlockInfo){.window = {.skey = (_block)->keyFirst, .ekey = (_block)->keyLast}, \
                    .numOfCols = (_block)->numOfCols,                                  \
                    .rows = (_block)->numOfRows,                                       \
26
                    .uid = (_checkInfo)->tableId})
H
Haojun Liao 已提交
27

H
hjxilinx 已提交
28
enum {
dengyihao's avatar
dengyihao 已提交
29 30
  TSDB_QUERY_TYPE_ALL = 1,
  TSDB_QUERY_TYPE_LAST = 2,
H
hjxilinx 已提交
31 32
};

33
enum {
dengyihao's avatar
dengyihao 已提交
34
  TSDB_CACHED_TYPE_NONE = 0,
35
  TSDB_CACHED_TYPE_LASTROW = 1,
dengyihao's avatar
dengyihao 已提交
36
  TSDB_CACHED_TYPE_LAST = 2,
37 38
};

39
typedef struct SQueryFilePos {
dengyihao's avatar
dengyihao 已提交
40 41 42 43 44 45 46
  int32_t     fid;
  int32_t     slot;
  int32_t     pos;
  int64_t     lastKey;
  int32_t     rows;
  bool        mixBlock;
  bool        blockCompleted;
47
  STimeWindow win;
48
} SQueryFilePos;
H
hjxilinx 已提交
49

50
typedef struct SDataBlockLoadInfo {
dengyihao's avatar
dengyihao 已提交
51 52 53 54
  SDFileSet* fileGroup;
  int32_t    slot;
  uint64_t   uid;
  SArray*    pLoadedCols;
55
} SDataBlockLoadInfo;
H
hjxilinx 已提交
56

57
typedef struct SLoadCompBlockInfo {
H
hjLiao 已提交
58
  int32_t tid; /* table tid */
59 60
  int32_t fileId;
} SLoadCompBlockInfo;
H
hjxilinx 已提交
61

62
enum {
dengyihao's avatar
dengyihao 已提交
63
  CHECKINFO_CHOSEN_MEM = 0,
64
  CHECKINFO_CHOSEN_IMEM = 1,
dengyihao's avatar
dengyihao 已提交
65
  CHECKINFO_CHOSEN_BOTH = 2  // for update=2(merge case)
66 67
};

68
typedef struct STableCheckInfo {
dengyihao's avatar
dengyihao 已提交
69 70 71 72 73 74 75 76 77
  uint64_t           tableId;
  TSKEY              lastKey;
  SBlockInfo*        pCompInfo;
  int32_t            compSize;
  int32_t            numOfBlocks : 29;  // number of qualified data blocks not the original blocks
  uint8_t            chosen : 2;        // indicate which iterator should move forward
  bool               initBuf : 1;       // whether to initialize the in-memory skip list iterator or not
  SSkipListIterator* iter;              // mem buffer skip list iterator
  SSkipListIterator* iiter;             // imem buffer skip list iterator
78
} STableCheckInfo;
79

80
typedef struct STableBlockInfo {
dengyihao's avatar
dengyihao 已提交
81 82
  SBlock*          compBlock;
  STableCheckInfo* pTableCheckInfo;
83
} STableBlockInfo;
84

85
typedef struct SBlockOrderSupporter {
dengyihao's avatar
dengyihao 已提交
86 87 88 89
  int32_t           numOfTables;
  STableBlockInfo** pDataBlockInfo;
  int32_t*          blockIndexArray;
  int32_t*          numOfBlocksPerTable;
90 91
} SBlockOrderSupporter;

H
Haojun Liao 已提交
92 93 94
typedef struct SIOCostSummary {
  int64_t blockLoadTime;
  int64_t statisInfoLoadTime;
H
Haojun Liao 已提交
95
  int64_t checkForNextTime;
96 97
  int64_t headFileLoad;
  int64_t headFileLoadTime;
H
Haojun Liao 已提交
98 99
} SIOCostSummary;

100
typedef struct STsdbReadHandle {
dengyihao's avatar
dengyihao 已提交
101
  STsdb*        pTsdb;
102
  SQueryFilePos cur;       // current position
dengyihao's avatar
dengyihao 已提交
103
  int16_t       order;
104 105
  STimeWindow   window;    // the primary query time window that applies to all queries
  SColumnDataAgg* statis;  // query level statistics, only one table block statistics info exists at any time
dengyihao's avatar
dengyihao 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
  int32_t       numOfBlocks;
  SArray*       pColumns;  // column list, SColumnInfoData array list
  bool          locateStart;
  int32_t       outputCapacity;
  int32_t       realNumOfRows;
  SArray*       pTableCheckInfo;  // SArray<STableCheckInfo>
  int32_t       activeIndex;
  bool          checkFiles;               // check file stage
  int8_t        cachelastrow;             // check if last row cached
  bool          loadExternalRow;          // load time window external data rows
  bool          currentLoadExternalRows;  // current load external rows
  int32_t       loadType;                 // block load type
  char*         idStr;                    // query info handle, for debug purpose
  int32_t type;  // query type: retrieve all data blocks, 2. retrieve only last row, 3. retrieve direct prev|next rows
  SDFileSet*         pFileGroup;
  SFSIter            fileIter;
  SReadH             rhelper;
  STableBlockInfo*   pDataBlockInfo;
  SDataCols*         pDataCols;          // in order to hold current file data block
  int32_t            allocSize;          // allocated data block size
  SArray*            defaultLoadColumn;  // default load column
  SDataBlockLoadInfo dataBlockLoadInfo;  /* record current block load information */
  SLoadCompBlockInfo compBlockLoadInfo;  /* record current compblock information in SQueryAttr */

  SArray*        prev;  // previous row which is before than time window
  SArray*        next;  // next row which is after the query time window
H
Haojun Liao 已提交
132
  SIOCostSummary cost;
133
} STsdbReadHandle;
134

H
Haojun Liao 已提交
135 136 137
typedef struct STableGroupSupporter {
  int32_t    numOfCols;
  SColIndex* pCols;
138
  SSchema*   pTagSchema;
H
Haojun Liao 已提交
139 140
} STableGroupSupporter;

dengyihao's avatar
dengyihao 已提交
141 142 143 144 145
int32_t tsdbQueryTableList(void* pMeta, SArray* pRes, void* filterInfo);

static STimeWindow updateLastrowForEachGroup(STableGroupInfo* groupList);
static int32_t     checkForCachedLastRow(STsdbReadHandle* pTsdbReadHandle, STableGroupInfo* groupList);
static int32_t     checkForCachedLast(STsdbReadHandle* pTsdbReadHandle);
H
Haojun Liao 已提交
146
// static int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey);
H
Haojun Liao 已提交
147

H
Haojun Liao 已提交
148
static void    changeQueryHandleForInterpQuery(tsdbReaderT pHandle);
149
static void    doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock);
150
static int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);
dengyihao's avatar
dengyihao 已提交
151 152
static int32_t tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
                                     STsdbReadHandle* pTsdbReadHandle);
153
static int32_t tsdbCheckInfoCompar(const void* key1, const void* key2);
dengyihao's avatar
dengyihao 已提交
154 155 156 157
// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, void* pMemRef);
// static void*   doFreeColumnInfoData(SArray* pColumnInfoData);
// static void*   destroyTableCheckInfo(SArray* pTableCheckInfo);
static bool tsdbGetExternalRow(tsdbReaderT pHandle);
Y
TD-1733  
yihaoDeng 已提交
158

159
static void tsdbInitDataBlockLoadInfo(SDataBlockLoadInfo* pBlockLoadInfo) {
H
hjxilinx 已提交
160
  pBlockLoadInfo->slot = -1;
dengyihao's avatar
dengyihao 已提交
161
  pBlockLoadInfo->uid = 0;
H
hjxilinx 已提交
162
  pBlockLoadInfo->fileGroup = NULL;
H
hjxilinx 已提交
163 164
}

165
static void tsdbInitCompBlockLoadInfo(SLoadCompBlockInfo* pCompBlockLoadInfo) {
H
hjLiao 已提交
166
  pCompBlockLoadInfo->tid = -1;
167 168
  pCompBlockLoadInfo->fileId = -1;
}
H
hjxilinx 已提交
169

170 171
static SArray* getColumnIdList(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfCols = QH_GET_NUM_OF_COLS(pTsdbReadHandle);
H
Haojun Liao 已提交
172 173 174 175
  assert(numOfCols <= TSDB_MAX_COLUMNS);

  SArray* pIdList = taosArrayInit(numOfCols, sizeof(int16_t));
  for (int32_t i = 0; i < numOfCols; ++i) {
176
    SColumnInfoData* pCol = taosArrayGet(pTsdbReadHandle->pColumns, i);
H
Haojun Liao 已提交
177 178 179 180 181 182
    taosArrayPush(pIdList, &pCol->info.colId);
  }

  return pIdList;
}

183 184
static SArray* getDefaultLoadColumns(STsdbReadHandle* pTsdbReadHandle, bool loadTS) {
  SArray* pLocalIdList = getColumnIdList(pTsdbReadHandle);
H
Haojun Liao 已提交
185 186 187 188 189

  // check if the primary time stamp column needs to load
  int16_t colId = *(int16_t*)taosArrayGet(pLocalIdList, 0);

  // the primary timestamp column does not be included in the the specified load column list, add it
H
Haojun Liao 已提交
190 191
  if (loadTS && colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
    int16_t columnId = PRIMARYKEY_TIMESTAMP_COL_ID;
H
Haojun Liao 已提交
192 193 194 195 196 197
    taosArrayInsert(pLocalIdList, 0, &columnId);
  }

  return pLocalIdList;
}

H
Haojun Liao 已提交
198
int64_t tsdbGetNumOfRowsInMemTable(tsdbReaderT* pHandle) {
dengyihao's avatar
dengyihao 已提交
199
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
H
Haojun Liao 已提交
200

dengyihao's avatar
dengyihao 已提交
201 202 203 204 205
  int64_t        rows = 0;
  STsdbMemTable* pMemTable = NULL;  // pTsdbReadHandle->pMemTable;
  if (pMemTable == NULL) {
    return rows;
  }
H
Haojun Liao 已提交
206

dengyihao's avatar
dengyihao 已提交
207 208
  //  STableData* pMem  = NULL;
  //  STableData* pIMem = NULL;
H
Haojun Liao 已提交
209

dengyihao's avatar
dengyihao 已提交
210 211
  //  SMemTable* pMemT = pMemRef->snapshot.mem;
  //  SMemTable* pIMemT = pMemRef->snapshot.imem;
H
Haojun Liao 已提交
212 213 214 215 216

  size_t size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
  for (int32_t i = 0; i < size; ++i) {
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);

dengyihao's avatar
dengyihao 已提交
217 218 219 220 221 222 223 224
    //    if (pMemT && pCheckInfo->tableId < pMemT->maxTables) {
    //      pMem = pMemT->tData[pCheckInfo->tableId];
    //      rows += (pMem && pMem->uid == pCheckInfo->tableId) ? pMem->numOfRows : 0;
    //    }
    //    if (pIMemT && pCheckInfo->tableId < pIMemT->maxTables) {
    //      pIMem = pIMemT->tData[pCheckInfo->tableId];
    //      rows += (pIMem && pIMem->uid == pCheckInfo->tableId) ? pIMem->numOfRows : 0;
    //    }
H
Haojun Liao 已提交
225 226 227
  }
  return rows;
}
228

229 230 231
static SArray* createCheckInfoFromTableGroup(STsdbReadHandle* pTsdbReadHandle, STableGroupInfo* pGroupList) {
  size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);
  assert(numOfGroup >= 1);
H
Haojun Liao 已提交
232 233 234 235 236 237 238 239

  // allocate buffer in order to load data blocks from file
  SArray* pTableCheckInfo = taosArrayInit(pGroupList->numOfTables, sizeof(STableCheckInfo));
  if (pTableCheckInfo == NULL) {
    return NULL;
  }

  // todo apply the lastkey of table check to avoid to load header file
240
  for (int32_t i = 0; i < numOfGroup; ++i) {
dengyihao's avatar
dengyihao 已提交
241
    SArray* group = *(SArray**)taosArrayGet(pGroupList->pGroupList, i);
H
Haojun Liao 已提交
242 243 244 245 246

    size_t gsize = taosArrayGetSize(group);
    assert(gsize > 0);

    for (int32_t j = 0; j < gsize; ++j) {
dengyihao's avatar
dengyihao 已提交
247
      STableKeyInfo* pKeyInfo = (STableKeyInfo*)taosArrayGet(group, j);
H
Haojun Liao 已提交
248

dengyihao's avatar
dengyihao 已提交
249
      STableCheckInfo info = {.lastKey = pKeyInfo->lastKey, .tableId = pKeyInfo->uid};
250 251 252
      if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
        if (info.lastKey == INT64_MIN || info.lastKey < pTsdbReadHandle->window.skey) {
          info.lastKey = pTsdbReadHandle->window.skey;
253 254
        }

255
        assert(info.lastKey >= pTsdbReadHandle->window.skey && info.lastKey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
256
      } else {
257
        assert(info.lastKey >= pTsdbReadHandle->window.ekey && info.lastKey <= pTsdbReadHandle->window.skey);
H
Haojun Liao 已提交
258 259 260
      }

      taosArrayPush(pTableCheckInfo, &info);
dengyihao's avatar
dengyihao 已提交
261 262
      tsdbDebug("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pTsdbReadHandle, info.tableId,
                info.lastKey, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
263 264 265
    }
  }

266
  // TODO  group table according to the tag value.
267
  taosArraySort(pTableCheckInfo, tsdbCheckInfoCompar);
H
Haojun Liao 已提交
268 269 270
  return pTableCheckInfo;
}

271 272
static void resetCheckInfo(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
273 274 275 276
  assert(numOfTables >= 1);

  // todo apply the lastkey of table check to avoid to load header file
  for (int32_t i = 0; i < numOfTables; ++i) {
dengyihao's avatar
dengyihao 已提交
277
    STableCheckInfo* pCheckInfo = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
278
    pCheckInfo->lastKey = pTsdbReadHandle->window.skey;
dengyihao's avatar
dengyihao 已提交
279 280
    pCheckInfo->iter = tSkipListDestroyIter(pCheckInfo->iter);
    pCheckInfo->iiter = tSkipListDestroyIter(pCheckInfo->iiter);
281
    pCheckInfo->initBuf = false;
H
Haojun Liao 已提交
282

283 284
    if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
      assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.skey);
285
    } else {
286
      assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.skey);
287
    }
H
Haojun Liao 已提交
288 289 290
  }
}

H
Haojun Liao 已提交
291 292 293
// only one table, not need to sort again
static SArray* createCheckInfoFromCheckInfo(STableCheckInfo* pCheckInfo, TSKEY skey, SArray** psTable) {
  SArray* pNew = taosArrayInit(1, sizeof(STableCheckInfo));
D
fix bug  
dapan1121 已提交
294

dengyihao's avatar
dengyihao 已提交
295
  STableCheckInfo info = {.lastKey = skey};
H
Haojun Liao 已提交
296

H
Haojun Liao 已提交
297 298
  info.tableId = pCheckInfo->tableId;
  taosArrayPush(pNew, &info);
H
Haojun Liao 已提交
299 300 301
  return pNew;
}

302 303
static bool emptyQueryTimewindow(STsdbReadHandle* pTsdbReadHandle) {
  assert(pTsdbReadHandle != NULL);
304

305
  STimeWindow* w = &pTsdbReadHandle->window;
dengyihao's avatar
dengyihao 已提交
306
  bool         asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
307 308 309 310

  return ((asc && w->skey > w->ekey) || (!asc && w->ekey > w->skey));
}

311 312
// Update the query time window according to the data time to live(TTL) information, in order to avoid to return
// the expired data to client, even it is queried already.
313
static int64_t getEarliestValidTimestamp(STsdb* pTsdb) {
314 315 316
  STsdbCfg* pCfg = &pTsdb->config;

  int64_t now = taosGetTimestamp(pCfg->precision);
H
Hongze Cheng 已提交
317
  return now - (tsTickPerDay[pCfg->precision] * pCfg->keep2) + 1;  // needs to add one tick
318 319
}

320 321
static void setQueryTimewindow(STsdbReadHandle* pTsdbReadHandle, STsdbQueryCond* pCond) {
  pTsdbReadHandle->window = pCond->twindow;
322

323
  bool    updateTs = false;
324 325 326 327
  int64_t startTs = getEarliestValidTimestamp(pTsdbReadHandle->pTsdb);
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
    if (startTs > pTsdbReadHandle->window.skey) {
      pTsdbReadHandle->window.skey = startTs;
328 329
      pCond->twindow.skey = startTs;
      updateTs = true;
330 331
    }
  } else {
332 333
    if (startTs > pTsdbReadHandle->window.ekey) {
      pTsdbReadHandle->window.ekey = startTs;
334 335
      pCond->twindow.ekey = startTs;
      updateTs = true;
336 337 338
    }
  }

339
  if (updateTs) {
H
Haojun Liao 已提交
340 341 342
    tsdbDebug("%p update the query time window, old:%" PRId64 " - %" PRId64 ", new:%" PRId64 " - %" PRId64 ", %s",
              pTsdbReadHandle, pCond->twindow.skey, pCond->twindow.ekey, pTsdbReadHandle->window.skey,
              pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
343
  }
344 345
}

H
Haojun Liao 已提交
346
static STsdbReadHandle* tsdbQueryTablesImpl(STsdb* tsdb, STsdbQueryCond* pCond, uint64_t qId, uint64_t taskId) {
wafwerar's avatar
wafwerar 已提交
347
  STsdbReadHandle* pReadHandle = taosMemoryCalloc(1, sizeof(STsdbReadHandle));
348
  if (pReadHandle == NULL) {
349
    goto _end;
350
  }
H
Haojun Liao 已提交
351

dengyihao's avatar
dengyihao 已提交
352 353 354 355 356 357 358 359
  pReadHandle->order = pCond->order;
  pReadHandle->pTsdb = tsdb;
  pReadHandle->type = TSDB_QUERY_TYPE_ALL;
  pReadHandle->cur.fid = INT32_MIN;
  pReadHandle->cur.win = TSWINDOW_INITIALIZER;
  pReadHandle->checkFiles = true;
  pReadHandle->activeIndex = 0;  // current active table index
  pReadHandle->allocSize = 0;
360
  pReadHandle->locateStart = false;
dengyihao's avatar
dengyihao 已提交
361
  pReadHandle->loadType = pCond->type;
362

dengyihao's avatar
dengyihao 已提交
363
  pReadHandle->outputCapacity = 4096;  //((STsdb*)tsdb)->config.maxRowsPerFileBlock;
364 365 366
  pReadHandle->loadExternalRow = pCond->loadExternalRows;
  pReadHandle->currentLoadExternalRows = pCond->loadExternalRows;

H
Haojun Liao 已提交
367
  char buf[128] = {0};
dengyihao's avatar
dengyihao 已提交
368
  snprintf(buf, tListLen(buf), "TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, qId);
H
Haojun Liao 已提交
369 370
  pReadHandle->idStr = strdup(buf);

371
  if (tsdbInitReadH(&pReadHandle->rhelper, (STsdb*)tsdb) != 0) {
372
    goto _end;
B
Bomin Zhang 已提交
373
  }
H
Haojun Liao 已提交
374

375 376
  assert(pCond != NULL);
  setQueryTimewindow(pReadHandle, pCond);
377

378 379
  if (pCond->numOfCols > 0) {
    // allocate buffer in order to load data blocks from file
380
    pReadHandle->statis = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnDataAgg));
381
    if (pReadHandle->statis == NULL) {
382
      goto _end;
383
    }
H
Haojun Liao 已提交
384

385
    // todo: use list instead of array?
386 387
    pReadHandle->pColumns = taosArrayInit(pCond->numOfCols, sizeof(SColumnInfoData));
    if (pReadHandle->pColumns == NULL) {
388
      goto _end;
389
    }
H
Haojun Liao 已提交
390

391 392 393
    for (int32_t i = 0; i < pCond->numOfCols; ++i) {
      SColumnInfoData colInfo = {{0}, 0};
      colInfo.info = pCond->colList[i];
H
Haojun Liao 已提交
394

395
      int32_t code = colInfoDataEnsureCapacity(&colInfo, 0, pReadHandle->outputCapacity);
396
      if (code != TSDB_CODE_SUCCESS) {
397
        goto _end;
398
      }
399

400 401
      taosArrayPush(pReadHandle->pColumns, &colInfo);
      pReadHandle->statis[i].colId = colInfo.info.colId;
B
Bomin Zhang 已提交
402
    }
H
Haojun Liao 已提交
403

404
    pReadHandle->defaultLoadColumn = getDefaultLoadColumns(pReadHandle, true);
H
Haojun Liao 已提交
405
  }
406

H
refact  
Hongze Cheng 已提交
407
  pReadHandle->pDataCols = tdNewDataCols(1000, pReadHandle->pTsdb->config.maxRows);
408
  if (pReadHandle->pDataCols == NULL) {
H
Haojun Liao 已提交
409
    tsdbError("%p failed to malloc buf for pDataCols, %s", pReadHandle, pReadHandle->idStr);
H
Haojun Liao 已提交
410
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
411
    goto _end;
H
hjxilinx 已提交
412
  }
413

414 415
  tsdbInitDataBlockLoadInfo(&pReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pReadHandle->compBlockLoadInfo);
416

H
Haojun Liao 已提交
417
  return (tsdbReaderT)pReadHandle;
418

dengyihao's avatar
dengyihao 已提交
419
_end:
420
  tsdbCleanupReadHandle(pReadHandle);
421
  terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
422
  return NULL;
H
hjxilinx 已提交
423 424
}

dengyihao's avatar
dengyihao 已提交
425 426
tsdbReaderT* tsdbQueryTables(STsdb* tsdb, STsdbQueryCond* pCond, STableGroupInfo* groupList, uint64_t qId,
                             uint64_t taskId) {
H
Haojun Liao 已提交
427
  STsdbReadHandle* pTsdbReadHandle = tsdbQueryTablesImpl(tsdb, pCond, qId, taskId);
428
  if (pTsdbReadHandle == NULL) {
429 430 431
    return NULL;
  }

432
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
433
    return (tsdbReaderT*)pTsdbReadHandle;
434
  }
H
Haojun Liao 已提交
435 436

  // todo apply the lastkey of table check to avoid to load header file
437
  pTsdbReadHandle->pTableCheckInfo = createCheckInfoFromTableGroup(pTsdbReadHandle, groupList);
438
  if (pTsdbReadHandle->pTableCheckInfo == NULL) {
dengyihao's avatar
dengyihao 已提交
439
    //    tsdbCleanupReadHandle(pTsdbReadHandle);
H
Haojun Liao 已提交
440 441 442 443
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    return NULL;
  }

dengyihao's avatar
dengyihao 已提交
444 445 446
  tsdbDebug("%p total numOfTable:%" PRIzu " in this query, group %" PRIzu " %s", pTsdbReadHandle,
            taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo), taosArrayGetSize(groupList->pGroupList),
            pTsdbReadHandle->idStr);
447

dengyihao's avatar
dengyihao 已提交
448
  return (tsdbReaderT)pTsdbReadHandle;
H
Haojun Liao 已提交
449 450
}

dengyihao's avatar
dengyihao 已提交
451
void tsdbResetQueryHandle(tsdbReaderT queryHandle, STsdbQueryCond* pCond) {
452
  STsdbReadHandle* pTsdbReadHandle = queryHandle;
H
Haojun Liao 已提交
453

454 455 456
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
    if (pCond->order != pTsdbReadHandle->order) {
      pTsdbReadHandle->order = pCond->order;
dengyihao's avatar
dengyihao 已提交
457
      TSWAP(pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, int64_t);
458 459 460 461 462
    }

    return;
  }

dengyihao's avatar
dengyihao 已提交
463 464 465 466 467 468 469
  pTsdbReadHandle->order = pCond->order;
  pTsdbReadHandle->window = pCond->twindow;
  pTsdbReadHandle->type = TSDB_QUERY_TYPE_ALL;
  pTsdbReadHandle->cur.fid = -1;
  pTsdbReadHandle->cur.win = TSWINDOW_INITIALIZER;
  pTsdbReadHandle->checkFiles = true;
  pTsdbReadHandle->activeIndex = 0;  // current active table index
470 471
  pTsdbReadHandle->locateStart = false;
  pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
H
Haojun Liao 已提交
472 473

  if (ASCENDING_TRAVERSE(pCond->order)) {
474
    assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
475
  } else {
476
    assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
477 478 479
  }

  // allocate buffer in order to load data blocks from file
480
  memset(pTsdbReadHandle->statis, 0, sizeof(SColumnDataAgg));
H
Haojun Liao 已提交
481

482 483
  tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
H
Haojun Liao 已提交
484

485
  resetCheckInfo(pTsdbReadHandle);
H
Haojun Liao 已提交
486 487
}

dengyihao's avatar
dengyihao 已提交
488
void tsdbResetQueryHandleForNewTable(tsdbReaderT queryHandle, STsdbQueryCond* pCond, STableGroupInfo* groupList) {
489
  STsdbReadHandle* pTsdbReadHandle = queryHandle;
H
Haojun Liao 已提交
490

dengyihao's avatar
dengyihao 已提交
491 492 493 494 495 496 497
  pTsdbReadHandle->order = pCond->order;
  pTsdbReadHandle->window = pCond->twindow;
  pTsdbReadHandle->type = TSDB_QUERY_TYPE_ALL;
  pTsdbReadHandle->cur.fid = -1;
  pTsdbReadHandle->cur.win = TSWINDOW_INITIALIZER;
  pTsdbReadHandle->checkFiles = true;
  pTsdbReadHandle->activeIndex = 0;  // current active table index
498 499
  pTsdbReadHandle->locateStart = false;
  pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
H
Haojun Liao 已提交
500 501

  if (ASCENDING_TRAVERSE(pCond->order)) {
502
    assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
503
  } else {
504
    assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
505 506 507
  }

  // allocate buffer in order to load data blocks from file
508
  memset(pTsdbReadHandle->statis, 0, sizeof(SColumnDataAgg));
H
Haojun Liao 已提交
509

510 511
  tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
H
Haojun Liao 已提交
512

H
Haojun Liao 已提交
513
  SArray* pTable = NULL;
dengyihao's avatar
dengyihao 已提交
514
  //  STsdbMeta* pMeta = tsdbGetMeta(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
515

dengyihao's avatar
dengyihao 已提交
516
  //  pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
517

dengyihao's avatar
dengyihao 已提交
518 519
  pTsdbReadHandle->pTableCheckInfo = NULL;  // createCheckInfoFromTableGroup(pTsdbReadHandle, groupList, pMeta,
                                            // &pTable);
520
  if (pTsdbReadHandle->pTableCheckInfo == NULL) {
dengyihao's avatar
dengyihao 已提交
521
    //    tsdbCleanupReadHandle(pTsdbReadHandle);
H
Haojun Liao 已提交
522 523
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
  }
H
Haojun Liao 已提交
524

dengyihao's avatar
dengyihao 已提交
525 526
  //  pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
  //  pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
H
Haojun Liao 已提交
527 528
}

dengyihao's avatar
dengyihao 已提交
529 530
tsdbReaderT tsdbQueryLastRow(STsdb* tsdb, STsdbQueryCond* pCond, STableGroupInfo* groupList, uint64_t qId,
                             uint64_t taskId) {
531
  pCond->twindow = updateLastrowForEachGroup(groupList);
H
Haojun Liao 已提交
532 533 534 535 536 537

  // no qualified table
  if (groupList->numOfTables == 0) {
    return NULL;
  }

dengyihao's avatar
dengyihao 已提交
538
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbQueryTables(tsdb, pCond, groupList, qId, taskId);
539
  if (pTsdbReadHandle == NULL) {
540 541 542
    return NULL;
  }

543
  int32_t code = checkForCachedLastRow(pTsdbReadHandle, groupList);
dengyihao's avatar
dengyihao 已提交
544
  if (code != TSDB_CODE_SUCCESS) {  // set the numOfTables to be 0
H
Haojun Liao 已提交
545 546 547
    terrno = code;
    return NULL;
  }
H
Haojun Liao 已提交
548 549

  assert(pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey <= pCond->twindow.ekey);
550 551
  if (pTsdbReadHandle->cachelastrow) {
    pTsdbReadHandle->type = TSDB_QUERY_TYPE_LAST;
D
init  
dapan1121 已提交
552
  }
dengyihao's avatar
dengyihao 已提交
553

554
  return pTsdbReadHandle;
D
init  
dapan1121 已提交
555 556
}

557
#if 0
H
Haojun Liao 已提交
558
tsdbReaderT tsdbQueryCacheLast(STsdb *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, STsdbMemTable* pMemRef) {
559 560
  STsdbReadHandle *pTsdbReadHandle = (STsdbReadHandle*) tsdbQueryTables(tsdb, pCond, groupList, qId, pMemRef);
  if (pTsdbReadHandle == NULL) {
561 562 563
    return NULL;
  }

564
  int32_t code = checkForCachedLast(pTsdbReadHandle);
D
init  
dapan1121 已提交
565 566 567 568 569
  if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0
    terrno = code;
    return NULL;
  }

570 571
  if (pTsdbReadHandle->cachelastrow) {
    pTsdbReadHandle->type = TSDB_QUERY_TYPE_LAST;
D
fix bug  
dapan1121 已提交
572
  }
D
init  
dapan1121 已提交
573
  
574
  return pTsdbReadHandle;
H
hjxilinx 已提交
575 576
}

577
#endif
dengyihao's avatar
dengyihao 已提交
578
SArray* tsdbGetQueriedTableList(tsdbReaderT* pHandle) {
579
  assert(pHandle != NULL);
H
Haojun Liao 已提交
580

dengyihao's avatar
dengyihao 已提交
581
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
H
Haojun Liao 已提交
582

dengyihao's avatar
dengyihao 已提交
583
  size_t  size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
584
  SArray* res = taosArrayInit(size, POINTER_BYTES);
585 586 587
  return res;
}

H
Haojun Liao 已提交
588 589 590 591 592
// leave only one table for each group
static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGroupList) {
  assert(pGroupList);
  size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);

wafwerar's avatar
wafwerar 已提交
593
  STableGroupInfo* pNew = taosMemoryCalloc(1, sizeof(STableGroupInfo));
Y
yihaoDeng 已提交
594
  pNew->pGroupList = taosArrayInit(numOfGroup, POINTER_BYTES);
H
Haojun Liao 已提交
595

dengyihao's avatar
dengyihao 已提交
596
  for (int32_t i = 0; i < numOfGroup; ++i) {
H
Haojun Liao 已提交
597
    SArray* oneGroup = taosArrayGetP(pGroupList->pGroupList, i);
dengyihao's avatar
dengyihao 已提交
598
    size_t  numOfTables = taosArrayGetSize(oneGroup);
H
Haojun Liao 已提交
599 600 601 602

    SArray* px = taosArrayInit(4, sizeof(STableKeyInfo));
    for (int32_t j = 0; j < numOfTables; ++j) {
      STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(oneGroup, j);
dengyihao's avatar
dengyihao 已提交
603 604 605 606 607
      //      if (window->skey <= pInfo->lastKey && ((STable*)pInfo->pTable)->lastKey != TSKEY_INITIAL_VAL) {
      //        taosArrayPush(px, pInfo);
      //        pNew->numOfTables += 1;
      //        break;
      //      }
H
Haojun Liao 已提交
608 609 610 611 612 613 614 615 616 617 618 619 620
    }

    // there are no data in this group
    if (taosArrayGetSize(px) == 0) {
      taosArrayDestroy(px);
    } else {
      taosArrayPush(pNew->pGroupList, &px);
    }
  }

  return pNew;
}

dengyihao's avatar
dengyihao 已提交
621 622
tsdbReaderT tsdbQueryRowsInExternalWindow(STsdb* tsdb, STsdbQueryCond* pCond, STableGroupInfo* groupList, uint64_t qId,
                                          uint64_t taskId) {
H
Haojun Liao 已提交
623 624
  STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);

625 626 627 628 629 630 631 632 633 634 635 636
  if (pNew->numOfTables == 0) {
    tsdbDebug("update query time range to invalidate time window");

    assert(taosArrayGetSize(pNew->pGroupList) == 0);
    bool asc = ASCENDING_TRAVERSE(pCond->order);
    if (asc) {
      pCond->twindow.ekey = pCond->twindow.skey - 1;
    } else {
      pCond->twindow.skey = pCond->twindow.ekey - 1;
    }
  }

dengyihao's avatar
dengyihao 已提交
637
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbQueryTables(tsdb, pCond, pNew, qId, taskId);
638 639
  pTsdbReadHandle->loadExternalRow = true;
  pTsdbReadHandle->currentLoadExternalRows = true;
640

641
  return pTsdbReadHandle;
642 643
}

644
static bool initTableMemIterator(STsdbReadHandle* pHandle, STableCheckInfo* pCheckInfo) {
645
  if (pCheckInfo->initBuf) {
646 647
    return true;
  }
H
Haojun Liao 已提交
648

649
  pCheckInfo->initBuf = true;
650
  int32_t order = pHandle->order;
H
Haojun Liao 已提交
651

652 653 654
  STbData** pMem = NULL;
  STbData** pIMem = NULL;

H
Haojun Liao 已提交
655
  TSKEY tLastKey = 0;  /// keyToTkey(pCheckInfo->lastKey);
656 657 658
  if (pHandle->pTsdb->mem != NULL) {
    pMem = taosHashGet(pHandle->pTsdb->mem->pHashIdx, &pCheckInfo->tableId, sizeof(pCheckInfo->tableId));
    if (pMem != NULL) {
H
Haojun Liao 已提交
659
      pCheckInfo->iter =
660
          tSkipListCreateIterFromVal((*pMem)->pData, (const char*)&tLastKey, TSDB_DATA_TYPE_TIMESTAMP, order);
H
Haojun Liao 已提交
661
    }
662
  }
H
Haojun Liao 已提交
663

664 665 666
  if (pHandle->pTsdb->imem != NULL) {
    pIMem = taosHashGet(pHandle->pTsdb->imem->pHashIdx, &pCheckInfo->tableId, sizeof(pCheckInfo->tableId));
    if (pIMem != NULL) {
H
Haojun Liao 已提交
667
      pCheckInfo->iiter =
668
          tSkipListCreateIterFromVal((*pIMem)->pData, (const char*)&tLastKey, TSDB_DATA_TYPE_TIMESTAMP, order);
H
Haojun Liao 已提交
669
    }
670
  }
H
Haojun Liao 已提交
671

672 673 674 675
  // both iterators are NULL, no data in buffer right now
  if (pCheckInfo->iter == NULL && pCheckInfo->iiter == NULL) {
    return false;
  }
H
Haojun Liao 已提交
676

dengyihao's avatar
dengyihao 已提交
677
  bool memEmpty = (pCheckInfo->iter == NULL) || (pCheckInfo->iter != NULL && !tSkipListIterNext(pCheckInfo->iter));
678
  bool imemEmpty = (pCheckInfo->iiter == NULL) || (pCheckInfo->iiter != NULL && !tSkipListIterNext(pCheckInfo->iiter));
dengyihao's avatar
dengyihao 已提交
679
  if (memEmpty && imemEmpty) {  // buffer is empty
680 681
    return false;
  }
H
Haojun Liao 已提交
682

683 684 685
  if (!memEmpty) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    assert(node != NULL);
H
Haojun Liao 已提交
686

H
Haojun Liao 已提交
687 688
    STSRow* row = (STSRow*)SL_GET_NODE_DATA(node);
    TSKEY   key = TD_ROW_KEY(row);  // first timestamp in buffer
689
    tsdbDebug("%p uid:%" PRId64 ", check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
dengyihao's avatar
dengyihao 已提交
690 691 692
              "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
              pHandle, pCheckInfo->tableId, key, order, (*pMem)->keyMin, (*pMem)->keyMax, pCheckInfo->lastKey,
              (*pMem)->nrows, pHandle->idStr);
H
Haojun Liao 已提交
693 694 695 696 697 698 699

    if (ASCENDING_TRAVERSE(order)) {
      assert(pCheckInfo->lastKey <= key);
    } else {
      assert(pCheckInfo->lastKey >= key);
    }

700
  } else {
dengyihao's avatar
dengyihao 已提交
701
    tsdbDebug("%p uid:%" PRId64 ", no data in mem, %s", pHandle, pCheckInfo->tableId, pHandle->idStr);
702
  }
H
Haojun Liao 已提交
703

704 705 706
  if (!imemEmpty) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
    assert(node != NULL);
H
Haojun Liao 已提交
707

H
Haojun Liao 已提交
708 709
    STSRow* row = (STSRow*)SL_GET_NODE_DATA(node);
    TSKEY   key = TD_ROW_KEY(row);  // first timestamp in buffer
710
    tsdbDebug("%p uid:%" PRId64 ", check data in imem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
dengyihao's avatar
dengyihao 已提交
711 712 713
              "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
              pHandle, pCheckInfo->tableId, key, order, (*pIMem)->keyMin, (*pIMem)->keyMax, pCheckInfo->lastKey,
              (*pIMem)->nrows, pHandle->idStr);
H
Haojun Liao 已提交
714 715 716 717 718 719

    if (ASCENDING_TRAVERSE(order)) {
      assert(pCheckInfo->lastKey <= key);
    } else {
      assert(pCheckInfo->lastKey >= key);
    }
720
  } else {
dengyihao's avatar
dengyihao 已提交
721
    tsdbDebug("%p uid:%" PRId64 ", no data in imem, %s", pHandle, pCheckInfo->tableId, pHandle->idStr);
722
  }
H
Haojun Liao 已提交
723

724 725 726
  return true;
}

H
Haojun Liao 已提交
727 728 729 730 731
static void destroyTableMemIterator(STableCheckInfo* pCheckInfo) {
  tSkipListDestroyIter(pCheckInfo->iter);
  tSkipListDestroyIter(pCheckInfo->iiter);
}

732
static TSKEY extractFirstTraverseKey(STableCheckInfo* pCheckInfo, int32_t order, int32_t update) {
H
Haojun Liao 已提交
733
  STSRow *rmem = NULL, *rimem = NULL;
734 735 736
  if (pCheckInfo->iter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    if (node != NULL) {
H
Haojun Liao 已提交
737
      rmem = (STSRow*)SL_GET_NODE_DATA(node);
738 739 740 741 742 743
    }
  }

  if (pCheckInfo->iiter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
    if (node != NULL) {
H
Haojun Liao 已提交
744
      rimem = (STSRow*)SL_GET_NODE_DATA(node);
745 746 747 748 749 750 751 752 753
    }
  }

  if (rmem == NULL && rimem == NULL) {
    return TSKEY_INITIAL_VAL;
  }

  if (rmem != NULL && rimem == NULL) {
    pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
H
Haojun Liao 已提交
754
    return TD_ROW_KEY(rmem);
755 756 757 758
  }

  if (rmem == NULL && rimem != NULL) {
    pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
759
    return TD_ROW_KEY(rimem);
760 761
  }

H
Haojun Liao 已提交
762 763
  TSKEY r1 = TD_ROW_KEY(rmem);
  TSKEY r2 = TD_ROW_KEY(rimem);
764 765

  if (r1 == r2) {
dengyihao's avatar
dengyihao 已提交
766
    if (update == TD_ROW_DISCARD_UPDATE) {
767 768
      pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
      tSkipListIterNext(pCheckInfo->iter);
dengyihao's avatar
dengyihao 已提交
769
    } else if (update == TD_ROW_OVERWRITE_UPDATE) {
770 771 772 773 774 775 776 777 778
      pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
      tSkipListIterNext(pCheckInfo->iiter);
    } else {
      pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
    }
    return r1;
  } else if (r1 < r2 && ASCENDING_TRAVERSE(order)) {
    pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
    return r1;
dengyihao's avatar
dengyihao 已提交
779
  } else {
780 781 782 783 784
    pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
    return r2;
  }
}

H
Haojun Liao 已提交
785 786
static STSRow* getSRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order, int32_t update, STSRow** extraRow) {
  STSRow *rmem = NULL, *rimem = NULL;
H
Haojun Liao 已提交
787 788 789
  if (pCheckInfo->iter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    if (node != NULL) {
H
Haojun Liao 已提交
790
      rmem = (STSRow*)SL_GET_NODE_DATA(node);
H
Haojun Liao 已提交
791 792
    }
  }
793

H
Haojun Liao 已提交
794 795 796
  if (pCheckInfo->iiter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
    if (node != NULL) {
H
Haojun Liao 已提交
797
      rimem = (STSRow*)SL_GET_NODE_DATA(node);
H
Haojun Liao 已提交
798 799
    }
  }
800

H
Haojun Liao 已提交
801 802
  if (rmem == NULL && rimem == NULL) {
    return NULL;
H
Haojun Liao 已提交
803
  }
804

H
Haojun Liao 已提交
805
  if (rmem != NULL && rimem == NULL) {
H
Haojun Liao 已提交
806 807 808
    pCheckInfo->chosen = 0;
    return rmem;
  }
809

H
Haojun Liao 已提交
810
  if (rmem == NULL && rimem != NULL) {
H
Haojun Liao 已提交
811 812 813
    pCheckInfo->chosen = 1;
    return rimem;
  }
814

H
Haojun Liao 已提交
815 816
  TSKEY r1 = TD_ROW_KEY(rmem);
  TSKEY r2 = TD_ROW_KEY(rimem);
H
Haojun Liao 已提交
817

818 819
  if (r1 == r2) {
    if (update == TD_ROW_DISCARD_UPDATE) {
H
TD-1439  
Hongze Cheng 已提交
820
      tSkipListIterNext(pCheckInfo->iter);
821
      pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
TD-1439  
Hongze Cheng 已提交
822
      return rimem;
dengyihao's avatar
dengyihao 已提交
823
    } else if (update == TD_ROW_OVERWRITE_UPDATE) {
H
TD-1439  
Hongze Cheng 已提交
824
      tSkipListIterNext(pCheckInfo->iiter);
825 826 827 828
      pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
      return rmem;
    } else {
      pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
H
Haojun Liao 已提交
829
      *extraRow = rimem;
H
TD-1439  
Hongze Cheng 已提交
830 831
      return rmem;
    }
H
Haojun Liao 已提交
832 833 834
  } else {
    if (ASCENDING_TRAVERSE(order)) {
      if (r1 < r2) {
835
        pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
H
Haojun Liao 已提交
836 837
        return rmem;
      } else {
838
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
839 840 841 842
        return rimem;
      }
    } else {
      if (r1 < r2) {
843
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
844 845
        return rimem;
      } else {
846
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
847 848 849 850
        return rmem;
      }
    }
  }
H
Haojun Liao 已提交
851 852
}

853
static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
H
Haojun Liao 已提交
854
  bool hasNext = false;
855
  if (pCheckInfo->chosen == CHECKINFO_CHOSEN_MEM) {
H
Haojun Liao 已提交
856 857 858
    if (pCheckInfo->iter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iter);
    }
859

H
Haojun Liao 已提交
860 861 862
    if (hasNext) {
      return hasNext;
    }
863

H
Haojun Liao 已提交
864 865 866
    if (pCheckInfo->iiter != NULL) {
      return tSkipListIterGet(pCheckInfo->iiter) != NULL;
    }
dengyihao's avatar
dengyihao 已提交
867
  } else if (pCheckInfo->chosen == CHECKINFO_CHOSEN_IMEM) {
868 869 870
    if (pCheckInfo->iiter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iiter);
    }
871

872 873 874
    if (hasNext) {
      return hasNext;
    }
875

876 877
    if (pCheckInfo->iter != NULL) {
      return tSkipListIterGet(pCheckInfo->iter) != NULL;
H
Haojun Liao 已提交
878
    }
879 880 881 882 883 884 885
  } else {
    if (pCheckInfo->iter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iter);
    }
    if (pCheckInfo->iiter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iiter) || hasNext;
    }
H
Haojun Liao 已提交
886
  }
887

H
Haojun Liao 已提交
888 889 890
  return hasNext;
}

891
static bool hasMoreDataInCache(STsdbReadHandle* pHandle) {
dengyihao's avatar
dengyihao 已提交
892 893
  STsdbCfg* pCfg = &pHandle->pTsdb->config;
  size_t    size = taosArrayGetSize(pHandle->pTableCheckInfo);
894
  assert(pHandle->activeIndex < size && pHandle->activeIndex >= 0 && size >= 1);
D
dapan1121 已提交
895
  pHandle->cur.fid = INT32_MIN;
H
Haojun Liao 已提交
896

897
  STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
H
Haojun Liao 已提交
898 899 900 901
  if (!pCheckInfo->initBuf) {
    initTableMemIterator(pHandle, pCheckInfo);
  }

H
Haojun Liao 已提交
902
  STSRow* row = getSRowInTableMem(pCheckInfo, pHandle->order, pCfg->update, NULL);
H
Haojun Liao 已提交
903
  if (row == NULL) {
904 905
    return false;
  }
906

H
Haojun Liao 已提交
907
  pCheckInfo->lastKey = TD_ROW_KEY(row);  // first timestamp in buffer
dengyihao's avatar
dengyihao 已提交
908 909
  tsdbDebug("%p uid:%" PRId64 ", check data in buffer from skey:%" PRId64 ", order:%d, %s", pHandle,
            pCheckInfo->tableId, pCheckInfo->lastKey, pHandle->order, pHandle->idStr);
H
Haojun Liao 已提交
910

911
  // all data in mem are checked already.
912 913
  if ((pCheckInfo->lastKey > pHandle->window.ekey && ASCENDING_TRAVERSE(pHandle->order)) ||
      (pCheckInfo->lastKey < pHandle->window.ekey && !ASCENDING_TRAVERSE(pHandle->order))) {
914 915
    return false;
  }
H
Haojun Liao 已提交
916

dengyihao's avatar
dengyihao 已提交
917
  int32_t      step = ASCENDING_TRAVERSE(pHandle->order) ? 1 : -1;
918
  STimeWindow* win = &pHandle->cur.win;
H
Haojun Liao 已提交
919
  pHandle->cur.rows = tsdbReadRowsFromCache(pCheckInfo, pHandle->window.ekey, pHandle->outputCapacity, win, pHandle);
H
Haojun Liao 已提交
920

921 922 923 924
  // update the last key value
  pCheckInfo->lastKey = win->ekey + step;
  pHandle->cur.lastKey = win->ekey + step;
  pHandle->cur.mixBlock = true;
925

926
  if (!ASCENDING_TRAVERSE(pHandle->order)) {
dengyihao's avatar
dengyihao 已提交
927
    TSWAP(win->skey, win->ekey, TSKEY);
928
  }
H
Haojun Liao 已提交
929

930
  return true;
931
}
H
hjxilinx 已提交
932

933 934
static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precision) {
  assert(precision >= TSDB_TIME_PRECISION_MICRO || precision <= TSDB_TIME_PRECISION_NANO);
935 936 937
  if (key == TSKEY_INITIAL_VAL) {
    return INT32_MIN;
  }
H
Haojun Liao 已提交
938

D
dapan1121 已提交
939
  if (key < 0) {
940
    key -= (daysPerFile * tsTickPerDay[precision]);
D
dapan1121 已提交
941
  }
dengyihao's avatar
dengyihao 已提交
942

943
  int64_t fid = (int64_t)(key / (daysPerFile * tsTickPerDay[precision]));  // set the starting fileId
dengyihao's avatar
dengyihao 已提交
944
  if (fid < 0L && llabs(fid) > INT32_MAX) {                                // data value overflow for INT32
945 946
    fid = INT32_MIN;
  }
H
Haojun Liao 已提交
947

948
  if (fid > 0L && fid > INT32_MAX) {
949 950
    fid = INT32_MAX;
  }
H
Haojun Liao 已提交
951

S
TD-1057  
Shengliang Guan 已提交
952
  return (int32_t)fid;
953 954
}

H
refact  
Hongze Cheng 已提交
955
static int32_t binarySearchForBlock(SBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) {
956 957
  int32_t firstSlot = 0;
  int32_t lastSlot = numOfBlocks - 1;
H
Haojun Liao 已提交
958

959
  int32_t midSlot = firstSlot;
H
Haojun Liao 已提交
960

961 962 963
  while (1) {
    numOfBlocks = lastSlot - firstSlot + 1;
    midSlot = (firstSlot + (numOfBlocks >> 1));
H
Haojun Liao 已提交
964

965
    if (numOfBlocks == 1) break;
H
Haojun Liao 已提交
966

967 968 969 970 971 972 973 974 975 976 977
    if (skey > pBlock[midSlot].keyLast) {
      if (numOfBlocks == 2) break;
      if ((order == TSDB_ORDER_DESC) && (skey < pBlock[midSlot + 1].keyFirst)) break;
      firstSlot = midSlot + 1;
    } else if (skey < pBlock[midSlot].keyFirst) {
      if ((order == TSDB_ORDER_ASC) && (skey > pBlock[midSlot - 1].keyLast)) break;
      lastSlot = midSlot - 1;
    } else {
      break;  // got the slot
    }
  }
H
Haojun Liao 已提交
978

979 980
  return midSlot;
}
981

dengyihao's avatar
dengyihao 已提交
982
static int32_t loadBlockInfo(STsdbReadHandle* pTsdbReadHandle, int32_t index, int32_t* numOfBlocks) {
H
Haojun Liao 已提交
983
  int32_t code = 0;
H
Haojun Liao 已提交
984

985
  STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, index);
H
Haojun Liao 已提交
986
  pCheckInfo->numOfBlocks = 0;
987

H
Haojun Liao 已提交
988
  STable table = {.uid = pCheckInfo->tableId, .tid = pCheckInfo->tableId};
H
Hongze Cheng 已提交
989
  table.pSchema = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), pCheckInfo->tableId, 0);
H
Haojun Liao 已提交
990 991

  if (tsdbSetReadTable(&pTsdbReadHandle->rhelper, &table) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
992 993 994
    code = terrno;
    return code;
  }
995

996
  SBlockIdx* compIndex = pTsdbReadHandle->rhelper.pBlkIdx;
H
Hongze Cheng 已提交
997

H
Haojun Liao 已提交
998
  // no data block in this file, try next file
999
  if (compIndex == NULL || compIndex->uid != pCheckInfo->tableId) {
H
Haojun Liao 已提交
1000 1001
    return 0;  // no data blocks in the file belongs to pCheckInfo->pTable
  }
1002

H
Haojun Liao 已提交
1003 1004 1005
  if (pCheckInfo->compSize < (int32_t)compIndex->len) {
    assert(compIndex->len > 0);

wafwerar's avatar
wafwerar 已提交
1006
    char* t = taosMemoryRealloc(pCheckInfo->pCompInfo, compIndex->len);
H
Haojun Liao 已提交
1007 1008 1009 1010
    if (t == NULL) {
      terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
      code = TSDB_CODE_TDB_OUT_OF_MEMORY;
      return code;
1011 1012
    }

H
Haojun Liao 已提交
1013 1014 1015
    pCheckInfo->pCompInfo = (SBlockInfo*)t;
    pCheckInfo->compSize = compIndex->len;
  }
1016

1017
  if (tsdbLoadBlockInfo(&(pTsdbReadHandle->rhelper), (void*)(pCheckInfo->pCompInfo)) < 0) {
H
Hongze Cheng 已提交
1018 1019
    return terrno;
  }
H
Haojun Liao 已提交
1020
  SBlockInfo* pCompInfo = pCheckInfo->pCompInfo;
1021

H
Haojun Liao 已提交
1022
  TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL;
1023

1024
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1025 1026
    assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.ekey &&
           pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1027
  } else {
dengyihao's avatar
dengyihao 已提交
1028 1029
    assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.ekey &&
           pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1030
  }
1031

dengyihao's avatar
dengyihao 已提交
1032 1033
  s = TMIN(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
  e = TMAX(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
1034

H
Haojun Liao 已提交
1035 1036 1037
  // discard the unqualified data block based on the query time window
  int32_t start = binarySearchForBlock(pCompInfo->blocks, compIndex->numOfBlocks, s, TSDB_ORDER_ASC);
  int32_t end = start;
H
TD-100  
hzcheng 已提交
1038

H
Haojun Liao 已提交
1039 1040 1041
  if (s > pCompInfo->blocks[start].keyLast) {
    return 0;
  }
1042

H
Haojun Liao 已提交
1043 1044 1045 1046
  // todo speedup the procedure of located end block
  while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) {
    end += 1;
  }
1047

H
Haojun Liao 已提交
1048
  pCheckInfo->numOfBlocks = (end - start);
1049

H
Haojun Liao 已提交
1050 1051 1052
  if (start > 0) {
    memmove(pCompInfo->blocks, &pCompInfo->blocks[start], pCheckInfo->numOfBlocks * sizeof(SBlock));
  }
1053

H
Haojun Liao 已提交
1054 1055 1056
  (*numOfBlocks) += pCheckInfo->numOfBlocks;
  return 0;
}
1057

1058
static int32_t getFileCompInfo(STsdbReadHandle* pTsdbReadHandle, int32_t* numOfBlocks) {
H
Haojun Liao 已提交
1059 1060 1061 1062
  // load all the comp offset value for all tables in this file
  int32_t code = TSDB_CODE_SUCCESS;
  *numOfBlocks = 0;

1063
  pTsdbReadHandle->cost.headFileLoad += 1;
1064 1065
  int64_t s = taosGetTimestampUs();

H
Haojun Liao 已提交
1066
  size_t numOfTables = 0;
1067 1068 1069 1070
  if (pTsdbReadHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) {
    code = loadBlockInfo(pTsdbReadHandle, pTsdbReadHandle->activeIndex, numOfBlocks);
  } else if (pTsdbReadHandle->loadType == BLOCK_LOAD_OFFSET_SEQ_ORDER) {
    numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
1071

H
Haojun Liao 已提交
1072
    for (int32_t i = 0; i < numOfTables; ++i) {
1073
      code = loadBlockInfo(pTsdbReadHandle, i, numOfBlocks);
H
Haojun Liao 已提交
1074
      if (code != TSDB_CODE_SUCCESS) {
1075 1076
        int64_t e = taosGetTimestampUs();

1077
        pTsdbReadHandle->cost.headFileLoadTime += (e - s);
H
Haojun Liao 已提交
1078 1079 1080 1081 1082
        return code;
      }
    }
  } else {
    assert(0);
1083
  }
1084

1085
  int64_t e = taosGetTimestampUs();
1086
  pTsdbReadHandle->cost.headFileLoadTime += (e - s);
H
Haojun Liao 已提交
1087
  return code;
1088 1089
}

dengyihao's avatar
dengyihao 已提交
1090 1091
static int32_t doLoadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
                                   int32_t slotIndex) {
H
Haojun Liao 已提交
1092
  int64_t st = taosGetTimestampUs();
1093

H
Hongze Cheng 已提交
1094
  STSchema* pSchema = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), pCheckInfo->tableId, 0);
1095
  int32_t   code = tdInitDataCols(pTsdbReadHandle->pDataCols, pSchema);
H
Haojun Liao 已提交
1096
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1097
    tsdbError("%p failed to malloc buf for pDataCols, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1098 1099 1100 1101
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }

1102
  code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[0], pSchema);
H
Haojun Liao 已提交
1103
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1104
    tsdbError("%p failed to malloc buf for rhelper.pDataCols[0], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1105 1106 1107 1108
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }

1109
  code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[1], pSchema);
H
Haojun Liao 已提交
1110
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1111
    tsdbError("%p failed to malloc buf for rhelper.pDataCols[1], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1112 1113 1114
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }
1115

1116
  int16_t* colIds = pTsdbReadHandle->defaultLoadColumn->pData;
H
Haojun Liao 已提交
1117

dengyihao's avatar
dengyihao 已提交
1118 1119
  int32_t ret = tsdbLoadBlockDataCols(&(pTsdbReadHandle->rhelper), pBlock, pCheckInfo->pCompInfo, colIds,
                                      (int)(QH_GET_NUM_OF_COLS(pTsdbReadHandle)), true);
H
Haojun Liao 已提交
1120
  if (ret != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1121 1122 1123
    int32_t c = terrno;
    assert(c != TSDB_CODE_SUCCESS);
    goto _error;
H
Haojun Liao 已提交
1124
  }
1125

1126
  SDataBlockLoadInfo* pBlockLoadInfo = &pTsdbReadHandle->dataBlockLoadInfo;
1127

1128 1129
  pBlockLoadInfo->fileGroup = pTsdbReadHandle->pFileGroup;
  pBlockLoadInfo->slot = pTsdbReadHandle->cur.slot;
H
Haojun Liao 已提交
1130
  pBlockLoadInfo->uid = pCheckInfo->tableId;
1131

1132
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
1133
  assert(pCols->numOfRows != 0 && pCols->numOfRows <= pBlock->numOfRows);
1134

1135
  pBlock->numOfRows = pCols->numOfRows;
H
Haojun Liao 已提交
1136

1137
  // Convert from TKEY to TSKEY for primary timestamp column if current block has timestamp before 1970-01-01T00:00:00Z
dengyihao's avatar
dengyihao 已提交
1138
  if (pBlock->keyFirst < 0 && colIds[0] == PRIMARYKEY_TIMESTAMP_COL_ID) {
1139
    int64_t* src = pCols->cols[0].pData;
dengyihao's avatar
dengyihao 已提交
1140
    for (int32_t i = 0; i < pBlock->numOfRows; ++i) {
1141 1142 1143 1144
      src[i] = tdGetKey(src[i]);
    }
  }

H
Haojun Liao 已提交
1145
  int64_t elapsedTime = (taosGetTimestampUs() - st);
1146
  pTsdbReadHandle->cost.blockLoadTime += elapsedTime;
1147

dengyihao's avatar
dengyihao 已提交
1148 1149 1150 1151
  tsdbDebug("%p load file block into buffer, index:%d, brange:%" PRId64 "-%" PRId64 ", rows:%d, elapsed time:%" PRId64
            " us, %s",
            pTsdbReadHandle, slotIndex, pBlock->keyFirst, pBlock->keyLast, pBlock->numOfRows, elapsedTime,
            pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1152
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
1153 1154 1155 1156

_error:
  pBlock->numOfRows = 0;

dengyihao's avatar
dengyihao 已提交
1157
  tsdbError("%p error occurs in loading file block, index:%d, brange:%" PRId64 "-%" PRId64 ", rows:%d, %s",
H
Haojun Liao 已提交
1158
            pTsdbReadHandle, slotIndex, pBlock->keyFirst, pBlock->keyLast, pBlock->numOfRows, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1159
  return terrno;
H
hjxilinx 已提交
1160 1161
}

1162
static int32_t getEndPosInDataBlock(STsdbReadHandle* pTsdbReadHandle, SDataBlockInfo* pBlockInfo);
dengyihao's avatar
dengyihao 已提交
1163 1164 1165 1166 1167 1168 1169 1170
static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows,
                                       int32_t start, int32_t end);
static void    moveDataToFront(STsdbReadHandle* pTsdbReadHandle, int32_t numOfRows, int32_t numOfCols);
static void    doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle);
static void    copyAllRemainRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo,
                                              SDataBlockInfo* pBlockInfo, int32_t endPos);

static int32_t handleDataMergeIfNeeded(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo) {
1171 1172
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
  STsdbCfg*      pCfg = &pTsdbReadHandle->pTsdb->config;
H
Haojun Liao 已提交
1173
  SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
1174
  TSKEY          key;
dengyihao's avatar
dengyihao 已提交
1175
  int32_t        code = TSDB_CODE_SUCCESS;
1176

1177
  /*bool hasData = */ initTableMemIterator(pTsdbReadHandle, pCheckInfo);
H
Haojun Liao 已提交
1178 1179
  assert(cur->pos >= 0 && cur->pos <= binfo.rows);

1180
  key = extractFirstTraverseKey(pCheckInfo, pTsdbReadHandle->order, pCfg->update);
1181

H
Haojun Liao 已提交
1182
  if (key != TSKEY_INITIAL_VAL) {
dengyihao's avatar
dengyihao 已提交
1183
    tsdbDebug("%p key in mem:%" PRId64 ", %s", pTsdbReadHandle, key, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1184
  } else {
H
Haojun Liao 已提交
1185
    tsdbDebug("%p no data in mem, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1186
  }
H
Haojun Liao 已提交
1187

1188 1189 1190 1191
  if ((ASCENDING_TRAVERSE(pTsdbReadHandle->order) && (key != TSKEY_INITIAL_VAL && key <= binfo.window.ekey)) ||
      (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && (key != TSKEY_INITIAL_VAL && key >= binfo.window.skey))) {
    if ((ASCENDING_TRAVERSE(pTsdbReadHandle->order) && (key != TSKEY_INITIAL_VAL && key < binfo.window.skey)) ||
        (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && (key != TSKEY_INITIAL_VAL && key > binfo.window.ekey))) {
H
Haojun Liao 已提交
1192
      // do not load file block into buffer
1193
      int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
H
Haojun Liao 已提交
1194

dengyihao's avatar
dengyihao 已提交
1195 1196 1197 1198
      TSKEY maxKey =
          ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? (binfo.window.skey - step) : (binfo.window.ekey - step);
      cur->rows =
          tsdbReadRowsFromCache(pCheckInfo, maxKey, pTsdbReadHandle->outputCapacity, &cur->win, pTsdbReadHandle);
1199
      pTsdbReadHandle->realNumOfRows = cur->rows;
H
Haojun Liao 已提交
1200 1201 1202

      // update the last key value
      pCheckInfo->lastKey = cur->win.ekey + step;
1203
      if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1204
        TSWAP(cur->win.skey, cur->win.ekey, TSKEY);
H
Haojun Liao 已提交
1205
      }
H
Haojun Liao 已提交
1206

H
Haojun Liao 已提交
1207 1208
      cur->mixBlock = true;
      cur->blockCompleted = false;
H
Haojun Liao 已提交
1209
      return code;
H
Haojun Liao 已提交
1210
    }
H
Haojun Liao 已提交
1211

1212
    // return error, add test cases
1213
    if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1214
      return code;
1215 1216
    }

1217
    doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1218
  } else {
1219 1220 1221 1222 1223 1224
    /*
     * no data in cache, only load data from file
     * during the query processing, data in cache will not be checked anymore.
     *
     * Here the buffer is not enough, so only part of file block can be loaded into memory buffer
     */
1225 1226
    assert(pTsdbReadHandle->outputCapacity >= binfo.rows);
    int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &binfo);
1227

dengyihao's avatar
dengyihao 已提交
1228
    if ((cur->pos == 0 && endPos == binfo.rows - 1 && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
1229 1230
        (cur->pos == (binfo.rows - 1) && endPos == 0 && (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)))) {
      pTsdbReadHandle->realNumOfRows = binfo.rows;
1231 1232

      cur->rows = binfo.rows;
dengyihao's avatar
dengyihao 已提交
1233
      cur->win = binfo.window;
1234
      cur->mixBlock = false;
H
Haojun Liao 已提交
1235 1236
      cur->blockCompleted = true;

1237
      if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
H
Haojun Liao 已提交
1238 1239 1240 1241 1242 1243
        cur->lastKey = binfo.window.ekey + 1;
        cur->pos = binfo.rows;
      } else {
        cur->lastKey = binfo.window.skey - 1;
        cur->pos = -1;
      }
dengyihao's avatar
dengyihao 已提交
1244
    } else {  // partially copy to dest buffer
1245
      copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &binfo, endPos);
1246 1247
      cur->mixBlock = true;
    }
1248

H
Haojun Liao 已提交
1249
    assert(cur->blockCompleted);
H
Haojun Liao 已提交
1250
    if (cur->rows == binfo.rows) {
dengyihao's avatar
dengyihao 已提交
1251
      tsdbDebug("%p whole file block qualified, brange:%" PRId64 "-%" PRId64 ", rows:%d, lastKey:%" PRId64 ", %s",
H
Haojun Liao 已提交
1252
                pTsdbReadHandle, cur->win.skey, cur->win.ekey, cur->rows, cur->lastKey, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1253
    } else {
dengyihao's avatar
dengyihao 已提交
1254 1255 1256 1257
      tsdbDebug("%p create data block from remain file block, brange:%" PRId64 "-%" PRId64
                ", rows:%d, total:%d, lastKey:%" PRId64 ", %s",
                pTsdbReadHandle, cur->win.skey, cur->win.ekey, cur->rows, binfo.rows, cur->lastKey,
                pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1258
    }
1259
  }
H
Haojun Liao 已提交
1260 1261

  return code;
1262 1263
}

dengyihao's avatar
dengyihao 已提交
1264 1265
static int32_t loadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
                                 bool* exists) {
1266
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
dengyihao's avatar
dengyihao 已提交
1267 1268
  int32_t        code = TSDB_CODE_SUCCESS;
  bool           asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
1269

1270
  if (asc) {
H
Haojun Liao 已提交
1271
    // query ended in/started from current block
1272 1273
    if (pTsdbReadHandle->window.ekey < pBlock->keyLast || pCheckInfo->lastKey > pBlock->keyFirst) {
      if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1274 1275
        *exists = false;
        return code;
1276
      }
1277

1278
      SDataCols* pTSCol = pTsdbReadHandle->rhelper.pDCols[0];
H
Haojun Liao 已提交
1279
      assert(pTSCol->cols->type == TSDB_DATA_TYPE_TIMESTAMP && pTSCol->numOfRows == pBlock->numOfRows);
H
Haojun Liao 已提交
1280

1281 1282
      if (pCheckInfo->lastKey > pBlock->keyFirst) {
        cur->pos =
1283
            binarySearchForKey(pTSCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
1284 1285 1286
      } else {
        cur->pos = 0;
      }
H
Haojun Liao 已提交
1287

H
Haojun Liao 已提交
1288
      assert(pCheckInfo->lastKey <= pBlock->keyLast);
1289
      doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1290
    } else {  // the whole block is loaded in to buffer
dengyihao's avatar
dengyihao 已提交
1291
      cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
1292
      code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
H
[td-32]  
hjxilinx 已提交
1293
    }
dengyihao's avatar
dengyihao 已提交
1294
  } else {  // desc order, query ended in current block
1295 1296
    if (pTsdbReadHandle->window.ekey > pBlock->keyFirst || pCheckInfo->lastKey < pBlock->keyLast) {
      if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1297 1298
        *exists = false;
        return code;
1299
      }
H
Haojun Liao 已提交
1300

1301
      SDataCols* pTsCol = pTsdbReadHandle->rhelper.pDCols[0];
1302
      if (pCheckInfo->lastKey < pBlock->keyLast) {
dengyihao's avatar
dengyihao 已提交
1303 1304
        cur->pos =
            binarySearchForKey(pTsCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
1305
      } else {
H
Haojun Liao 已提交
1306
        cur->pos = pBlock->numOfRows - 1;
1307
      }
H
Haojun Liao 已提交
1308

H
Haojun Liao 已提交
1309
      assert(pCheckInfo->lastKey >= pBlock->keyFirst);
1310
      doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1311
    } else {
dengyihao's avatar
dengyihao 已提交
1312
      cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
1313
      code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
H
[td-32]  
hjxilinx 已提交
1314
    }
1315
  }
1316

1317
  *exists = pTsdbReadHandle->realNumOfRows > 0;
H
Haojun Liao 已提交
1318
  return code;
H
[td-32]  
hjxilinx 已提交
1319 1320
}

1321
static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
1322
  int    firstPos, lastPos, midPos = -1;
H
Haojun Liao 已提交
1323
  int    numOfRows;
1324 1325
  TSKEY* keyList;

1326
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
H
Haojun Liao 已提交
1327

1328
  if (num <= 0) return -1;
1329 1330

  keyList = (TSKEY*)pValue;
1331 1332
  firstPos = 0;
  lastPos = num - 1;
1333

1334
  if (order == TSDB_ORDER_DESC) {
1335 1336 1337 1338 1339
    // 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;
1340

H
Haojun Liao 已提交
1341 1342
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1343

1344 1345 1346 1347 1348 1349 1350 1351
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
1352

1353 1354 1355 1356 1357
  } 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;
1358

1359 1360 1361 1362 1363 1364 1365
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
1366

H
Haojun Liao 已提交
1367 1368
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1369

1370 1371 1372 1373 1374 1375 1376 1377 1378
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
1379

1380 1381 1382
  return midPos;
}

dengyihao's avatar
dengyihao 已提交
1383 1384 1385
static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows,
                                       int32_t start, int32_t end) {
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
H
Haojun Liao 已提交
1386

1387
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
dengyihao's avatar
dengyihao 已提交
1388
  TSKEY*     tsArray = pCols->cols[0].pData;
H
Haojun Liao 已提交
1389

1390
  int32_t num = end - start + 1;
H
Haojun Liao 已提交
1391 1392 1393 1394 1395 1396
  assert(num >= 0);

  if (num == 0) {
    return numOfRows;
  }

1397
  int32_t requiredNumOfCols = (int32_t)taosArrayGetSize(pTsdbReadHandle->pColumns);
H
Haojun Liao 已提交
1398

dengyihao's avatar
dengyihao 已提交
1399
  // data in buffer has greater timestamp, copy data in file block
1400
  int32_t i = 0, j = 0;
dengyihao's avatar
dengyihao 已提交
1401
  while (i < requiredNumOfCols && j < pCols->numOfCols) {
1402
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1403 1404 1405 1406 1407 1408 1409

    SDataCol* src = &pCols->cols[j];
    if (src->colId < pColInfo->info.colId) {
      j++;
      continue;
    }

L
Liu Jicong 已提交
1410
    if (!isAllRowsNull(src) && pColInfo->info.colId == src->colId) {
1411
      if (!IS_VAR_DATA_TYPE(pColInfo->info.type)) {  // todo opt performance
dengyihao's avatar
dengyihao 已提交
1412 1413
        //        memmove(pData, (char*)src->pData + bytes * start, bytes * num);
        for (int32_t k = start; k < num + start; ++k) {
1414
          SCellVal sVal = {0};
C
Cary Xu 已提交
1415
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
1416 1417
            TASSERT(0);
          }
1418

1419
          if (sVal.valType == TD_VTYPE_NULL) {
1420
            colDataAppendNULL(pColInfo, k);
1421 1422 1423 1424 1425
          } else {
            colDataAppend(pColInfo, k, sVal.val, false);
          }
        }
      } else {  // handle the var-string
1426 1427
        // todo refactor, only copy one-by-one
        for (int32_t k = start; k < num + start; ++k) {
1428
          SCellVal sVal = {0};
dengyihao's avatar
dengyihao 已提交
1429
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
H
Haojun Liao 已提交
1430 1431
            TASSERT(0);
          }
1432

1433 1434 1435 1436 1437
          if (sVal.valType == TD_VTYPE_NULL) {
            colDataAppendNULL(pColInfo, k);
          } else {
            colDataAppend(pColInfo, k, sVal.val, false);
          }
1438 1439
        }
      }
1440 1441 1442

      j++;
      i++;
dengyihao's avatar
dengyihao 已提交
1443 1444
    } else {                                           // pColInfo->info.colId < src->colId, it is a NULL data
      for (int32_t k = start; k < num + start; ++k) {  // TODO opt performance
1445
        colDataAppend(pColInfo, k, NULL, true);
1446 1447
      }
      i++;
1448 1449
    }
  }
1450

dengyihao's avatar
dengyihao 已提交
1451
  while (i < requiredNumOfCols) {  // the remain columns are all null data
1452
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
1453 1454
    for (int32_t k = start; k < num + start; ++k) {
      colDataAppend(pColInfo, k, NULL, true);  // TODO add a fast version to set a number of consecutive NULL value.
1455 1456
    }
    i++;
1457
  }
H
Haojun Liao 已提交
1458

1459 1460
  pTsdbReadHandle->cur.win.ekey = tsArray[end];
  pTsdbReadHandle->cur.lastKey = tsArray[end] + step;
1461

1462
  return numOfRows + num;
1463 1464
}

H
Haojun Liao 已提交
1465
// TODO fix bug for reverse copy data problem
1466
// Note: row1 always has high priority
H
Haojun Liao 已提交
1467 1468 1469 1470
static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows, STSRow* row1,
                               STSRow* row2, int32_t numOfCols, uint64_t uid, STSchema* pSchema1, STSchema* pSchema2,
                               bool forceSetNull) {
#if 1
dengyihao's avatar
dengyihao 已提交
1471 1472 1473 1474 1475 1476 1477 1478 1479
  STSchema* pSchema;
  STSRow*   row;
  int16_t   colId;
  int16_t   offset;

  bool     isRow1DataRow = TD_IS_TP_ROW(row1);
  bool     isRow2DataRow;
  bool     isChosenRowDataRow;
  int32_t  chosen_itr;
H
Haojun Liao 已提交
1480
  SCellVal sVal = {0};
1481

H
Haojun Liao 已提交
1482
  // the schema version info is embeded in STSRow
1483 1484 1485
  int32_t numOfColsOfRow1 = 0;

  if (pSchema1 == NULL) {
H
Hongze Cheng 已提交
1486
    pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row1));
1487
  }
1488

dengyihao's avatar
dengyihao 已提交
1489
  if (isRow1DataRow) {
1490
    numOfColsOfRow1 = schemaNCols(pSchema1);
H
Haojun Liao 已提交
1491
  } else {
H
Haojun Liao 已提交
1492
    numOfColsOfRow1 = tdRowGetNCols(row1);
D
fix bug  
dapan1121 已提交
1493
  }
1494

1495
  int32_t numOfColsOfRow2 = 0;
dengyihao's avatar
dengyihao 已提交
1496
  if (row2) {
H
Haojun Liao 已提交
1497
    isRow2DataRow = TD_IS_TP_ROW(row2);
1498
    if (pSchema2 == NULL) {
H
Hongze Cheng 已提交
1499
      pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row2));
1500
    }
dengyihao's avatar
dengyihao 已提交
1501
    if (isRow2DataRow) {
1502 1503
      numOfColsOfRow2 = schemaNCols(pSchema2);
    } else {
H
Haojun Liao 已提交
1504
      numOfColsOfRow2 = tdRowGetNCols(row2);
1505 1506
    }
  }
C
Cary Xu 已提交
1507

1508
  int32_t i = 0, j = 0, k = 0;
dengyihao's avatar
dengyihao 已提交
1509
  while (i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) {
1510
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1511 1512

    int32_t colIdOfRow1;
dengyihao's avatar
dengyihao 已提交
1513
    if (j >= numOfColsOfRow1) {
1514
      colIdOfRow1 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1515
    } else if (isRow1DataRow) {
1516 1517
      colIdOfRow1 = pSchema1->columns[j].colId;
    } else {
dengyihao's avatar
dengyihao 已提交
1518
      SKvRowIdx* pColIdx = tdKvRowColIdxAt(row1, j);
1519 1520 1521 1522
      colIdOfRow1 = pColIdx->colId;
    }

    int32_t colIdOfRow2;
dengyihao's avatar
dengyihao 已提交
1523
    if (k >= numOfColsOfRow2) {
1524
      colIdOfRow2 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1525
    } else if (isRow2DataRow) {
1526 1527
      colIdOfRow2 = pSchema2->columns[k].colId;
    } else {
dengyihao's avatar
dengyihao 已提交
1528
      SKvRowIdx* pColIdx = tdKvRowColIdxAt(row2, k);
1529 1530 1531
      colIdOfRow2 = pColIdx->colId;
    }

dengyihao's avatar
dengyihao 已提交
1532 1533
    if (colIdOfRow1 == colIdOfRow2) {
      if (colIdOfRow1 < pColInfo->info.colId) {
C
Cary Xu 已提交
1534
        j++;
1535
        k++;
C
Cary Xu 已提交
1536 1537
        continue;
      }
1538 1539 1540 1541
      row = row1;
      pSchema = pSchema1;
      isChosenRowDataRow = isRow1DataRow;
      chosen_itr = j;
dengyihao's avatar
dengyihao 已提交
1542 1543
    } else if (colIdOfRow1 < colIdOfRow2) {
      if (colIdOfRow1 < pColInfo->info.colId) {
1544 1545
        j++;
        continue;
C
Cary Xu 已提交
1546
      }
1547 1548 1549 1550 1551
      row = row1;
      pSchema = pSchema1;
      isChosenRowDataRow = isRow1DataRow;
      chosen_itr = j;
    } else {
dengyihao's avatar
dengyihao 已提交
1552
      if (colIdOfRow2 < pColInfo->info.colId) {
1553 1554 1555 1556 1557 1558 1559 1560
        k++;
        continue;
      }
      row = row2;
      pSchema = pSchema2;
      chosen_itr = k;
      isChosenRowDataRow = isRow2DataRow;
    }
dengyihao's avatar
dengyihao 已提交
1561
    if (isChosenRowDataRow) {
1562 1563
      colId = pSchema->columns[chosen_itr].colId;
      offset = pSchema->columns[chosen_itr].offset;
C
Cary Xu 已提交
1564 1565
      // TODO: use STSRowIter
      tdSTpRowGetVal(row, colId, pSchema->columns[chosen_itr].type, pSchema->flen, offset, chosen_itr - 1, &sVal);
1566
    } else {
C
Cary Xu 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
      // TODO: use STSRowIter
      if (chosen_itr == 0) {
        colId = PRIMARYKEY_TIMESTAMP_COL_ID;
        tdSKvRowGetVal(row, PRIMARYKEY_TIMESTAMP_COL_ID, -1, -1, &sVal);
      } else {
        SKvRowIdx* pColIdx = tdKvRowColIdxAt(row, chosen_itr - 1);
        colId = pColIdx->colId;
        offset = pColIdx->offset;
        tdSKvRowGetVal(row, colId, offset, chosen_itr - 1, &sVal);
      }
1577 1578 1579
    }

    if (colId == pColInfo->info.colId) {
H
Haojun Liao 已提交
1580
      if (tdValTypeIsNorm(sVal.valType)) {
H
Haojun Liao 已提交
1581
        colDataAppend(pColInfo, numOfRows, sVal.val, false);
H
Haojun Liao 已提交
1582
      } else if (forceSetNull) {
H
Haojun Liao 已提交
1583
        colDataAppend(pColInfo, numOfRows, NULL, true);
1584
      }
H
Haojun Liao 已提交
1585

1586
      i++;
C
Cary Xu 已提交
1587

dengyihao's avatar
dengyihao 已提交
1588
      if (row == row1) {
C
Cary Xu 已提交
1589
        j++;
1590 1591 1592 1593
      } else {
        k++;
      }
    } else {
dengyihao's avatar
dengyihao 已提交
1594
      if (forceSetNull) {
H
Haojun Liao 已提交
1595
        colDataAppend(pColInfo, numOfRows, NULL, true);
C
Cary Xu 已提交
1596
      }
1597
      i++;
1598
    }
1599
  }
1600

dengyihao's avatar
dengyihao 已提交
1601 1602
  if (forceSetNull) {
    while (i < numOfCols) {  // the remain columns are all null data
1603
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
H
Haojun Liao 已提交
1604
      colDataAppend(pColInfo, numOfRows, NULL, true);
1605
      i++;
1606 1607
    }
  }
H
Haojun Liao 已提交
1608
#endif
1609
}
1610

1611 1612
static void moveDataToFront(STsdbReadHandle* pTsdbReadHandle, int32_t numOfRows, int32_t numOfCols) {
  if (numOfRows == 0 || ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1613 1614 1615 1616
    return;
  }

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
1617 1618
  if (numOfRows < pTsdbReadHandle->outputCapacity) {
    int32_t emptySize = pTsdbReadHandle->outputCapacity - numOfRows;
dengyihao's avatar
dengyihao 已提交
1619
    for (int32_t i = 0; i < numOfCols; ++i) {
1620
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
1621 1622
      memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes,
              numOfRows * pColInfo->info.bytes);
1623 1624 1625 1626
    }
  }
}

dengyihao's avatar
dengyihao 已提交
1627 1628
static void getQualifiedRowsPos(STsdbReadHandle* pTsdbReadHandle, int32_t startPos, int32_t endPos,
                                int32_t numOfExisted, int32_t* start, int32_t* end) {
1629 1630
  *start = -1;

1631
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1632
    int32_t remain = endPos - startPos + 1;
1633 1634
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = (pTsdbReadHandle->outputCapacity - numOfExisted) + startPos - 1;
H
Haojun Liao 已提交
1635 1636
    } else {
      *end = endPos;
1637 1638 1639 1640 1641
    }

    *start = startPos;
  } else {
    int32_t remain = (startPos - endPos) + 1;
1642 1643
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = startPos + 1 - (pTsdbReadHandle->outputCapacity - numOfExisted);
H
Haojun Liao 已提交
1644 1645
    } else {
      *end = endPos;
1646 1647 1648 1649 1650 1651 1652
    }

    *start = *end;
    *end = startPos;
  }
}

dengyihao's avatar
dengyihao 已提交
1653 1654
static void updateInfoAfterMerge(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, int32_t numOfRows,
                                 int32_t endPos) {
1655
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
1656 1657

  pCheckInfo->lastKey = cur->lastKey;
1658
  pTsdbReadHandle->realNumOfRows = numOfRows;
1659 1660 1661 1662
  cur->rows = numOfRows;
  cur->pos = endPos;
}

1663 1664
static void doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
1665 1666

  if (cur->rows > 0) {
1667 1668
    if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
      assert(cur->win.skey >= pTsdbReadHandle->window.skey && cur->win.ekey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1669
    } else {
1670
      assert(cur->win.skey >= pTsdbReadHandle->window.ekey && cur->win.ekey <= pTsdbReadHandle->window.skey);
H
Haojun Liao 已提交
1671 1672
    }

1673
    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, 0);
dengyihao's avatar
dengyihao 已提交
1674 1675
    assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] &&
           cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows - 1]);
H
Haojun Liao 已提交
1676
  } else {
1677
    cur->win = pTsdbReadHandle->window;
H
Haojun Liao 已提交
1678

dengyihao's avatar
dengyihao 已提交
1679
    int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1680
    cur->lastKey = pTsdbReadHandle->window.ekey + step;
H
Haojun Liao 已提交
1681 1682 1683
  }
}

dengyihao's avatar
dengyihao 已提交
1684 1685
static void copyAllRemainRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo,
                                           SDataBlockInfo* pBlockInfo, int32_t endPos) {
1686
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
1687

1688
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
dengyihao's avatar
dengyihao 已提交
1689
  TSKEY*     tsArray = pCols->cols[0].pData;
H
Haojun Liao 已提交
1690

dengyihao's avatar
dengyihao 已提交
1691
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1692
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
H
Haojun Liao 已提交
1693 1694 1695 1696 1697 1698

  int32_t pos = cur->pos;

  int32_t start = cur->pos;
  int32_t end = endPos;

1699
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1700
    TSWAP(start, end, int32_t);
H
Haojun Liao 已提交
1701 1702
  }

1703 1704
  assert(pTsdbReadHandle->outputCapacity >= (end - start + 1));
  int32_t numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, start, end);
H
Haojun Liao 已提交
1705 1706

  // the time window should always be ascending order: skey <= ekey
dengyihao's avatar
dengyihao 已提交
1707
  cur->win = (STimeWindow){.skey = tsArray[start], .ekey = tsArray[end]};
H
Haojun Liao 已提交
1708
  cur->mixBlock = (numOfRows != pBlockInfo->rows);
H
Haojun Liao 已提交
1709
  cur->lastKey = tsArray[endPos] + step;
H
Haojun Liao 已提交
1710
  cur->blockCompleted = true;
H
Haojun Liao 已提交
1711 1712

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
1713
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
H
Haojun Liao 已提交
1714 1715 1716

  // The value of pos may be -1 or pBlockInfo->rows, and it is invalid in both cases.
  pos = endPos + step;
1717 1718
  updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
  doCheckGeneratedBlockRange(pTsdbReadHandle);
H
Haojun Liao 已提交
1719

dengyihao's avatar
dengyihao 已提交
1720 1721 1722
  tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
            pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
            pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1723 1724
}

1725
int32_t getEndPosInDataBlock(STsdbReadHandle* pTsdbReadHandle, SDataBlockInfo* pBlockInfo) {
H
Haojun Liao 已提交
1726 1727
  // NOTE: reverse the order to find the end position in data block
  int32_t endPos = -1;
dengyihao's avatar
dengyihao 已提交
1728
  int32_t order = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
H
Haojun Liao 已提交
1729

1730
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
dengyihao's avatar
dengyihao 已提交
1731
  SDataCols*     pCols = pTsdbReadHandle->rhelper.pDCols[0];
H
Haojun Liao 已提交
1732

1733
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order) && pTsdbReadHandle->window.ekey >= pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
1734 1735
    endPos = pBlockInfo->rows - 1;
    cur->mixBlock = (cur->pos != 0);
1736
  } else if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && pTsdbReadHandle->window.ekey <= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
1737 1738 1739 1740
    endPos = 0;
    cur->mixBlock = (cur->pos != pBlockInfo->rows - 1);
  } else {
    assert(pCols->numOfRows > 0);
1741
    endPos = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, pTsdbReadHandle->window.ekey, order);
H
Haojun Liao 已提交
1742 1743 1744 1745 1746 1747
    cur->mixBlock = true;
  }

  return endPos;
}

H
[td-32]  
hjxilinx 已提交
1748 1749
// only return the qualified data to client in terms of query time window, data rows in the same block but do not
// be included in the query time window will be discarded
1750 1751
static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
dengyihao's avatar
dengyihao 已提交
1752
  SDataBlockInfo blockInfo = {0};  // GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
1753
  STsdbCfg*      pCfg = &pTsdbReadHandle->pTsdb->config;
H
Haojun Liao 已提交
1754

1755
  initTableMemIterator(pTsdbReadHandle, pCheckInfo);
1756

1757 1758
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
  assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_ID &&
dengyihao's avatar
dengyihao 已提交
1759
         cur->pos >= 0 && cur->pos < pBlock->numOfRows);
H
Haojun Liao 已提交
1760

1761
  TSKEY* tsArray = pCols->cols[0].pData;
dengyihao's avatar
dengyihao 已提交
1762 1763
  assert(pCols->numOfRows == pBlock->numOfRows && tsArray[0] == pBlock->keyFirst &&
         tsArray[pBlock->numOfRows - 1] == pBlock->keyLast);
1764 1765

  // for search the endPos, so the order needs to reverse
dengyihao's avatar
dengyihao 已提交
1766
  int32_t order = (pTsdbReadHandle->order == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
1767

dengyihao's avatar
dengyihao 已提交
1768
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1769
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
1770

H
Haojun Liao 已提交
1771
  STable* pTable = NULL;
1772
  int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &blockInfo);
H
Haojun Liao 已提交
1773

dengyihao's avatar
dengyihao 已提交
1774 1775
  tsdbDebug("%p uid:%" PRIu64 " start merge data block, file block range:%" PRIu64 "-%" PRIu64
            " rows:%d, start:%d,"
H
Haojun Liao 已提交
1776
            "end:%d, %s",
dengyihao's avatar
dengyihao 已提交
1777 1778
            pTsdbReadHandle, pCheckInfo->tableId, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows,
            cur->pos, endPos, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1779

1780 1781
  // compared with the data from in-memory buffer, to generate the correct timestamp array list
  int32_t numOfRows = 0;
H
Haojun Liao 已提交
1782

dengyihao's avatar
dengyihao 已提交
1783 1784
  int16_t   rv1 = -1;
  int16_t   rv2 = -1;
1785 1786
  STSchema* pSchema1 = NULL;
  STSchema* pSchema2 = NULL;
D
fix bug  
dapan1121 已提交
1787

H
Haojun Liao 已提交
1788 1789
  int32_t pos = cur->pos;
  cur->win = TSWINDOW_INITIALIZER;
1790

1791 1792
  // no data in buffer, load data from file directly
  if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) {
1793
    copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &blockInfo, endPos);
1794
    return;
1795
  } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) {
1796 1797
    SSkipListNode* node = NULL;
    do {
H
Haojun Liao 已提交
1798 1799
      STSRow* row2 = NULL;
      STSRow* row1 = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, &row2);
1800
      if (row1 == NULL) {
H
[td-32]  
hjxilinx 已提交
1801
        break;
1802
      }
1803

H
Haojun Liao 已提交
1804
      TSKEY key = TD_ROW_KEY(row1);
1805 1806
      if ((key > pTsdbReadHandle->window.ekey && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          (key < pTsdbReadHandle->window.ekey && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1807 1808 1809
        break;
      }

dengyihao's avatar
dengyihao 已提交
1810 1811 1812 1813
      if (((pos > endPos || tsArray[pos] > pTsdbReadHandle->window.ekey) &&
           ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          ((pos < endPos || tsArray[pos] < pTsdbReadHandle->window.ekey) &&
           !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1814 1815 1816
        break;
      }

1817 1818
      if ((key < tsArray[pos] && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          (key > tsArray[pos] && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
H
Haojun Liao 已提交
1819
        if (rv1 != TD_ROW_SVER(row1)) {
dengyihao's avatar
dengyihao 已提交
1820
          //          pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
H
Haojun Liao 已提交
1821
          rv1 = TD_ROW_SVER(row1);
C
Cary Xu 已提交
1822
        }
dengyihao's avatar
dengyihao 已提交
1823 1824
        if (row2 && rv2 != TD_ROW_SVER(row2)) {
          //          pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
H
Haojun Liao 已提交
1825
          rv2 = TD_ROW_SVER(row2);
1826
        }
dengyihao's avatar
dengyihao 已提交
1827 1828 1829

        mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                           pCheckInfo->tableId, pSchema1, pSchema2, true);
1830 1831 1832 1833
        numOfRows += 1;
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = key;
        }
1834

1835
        cur->win.ekey = key;
dengyihao's avatar
dengyihao 已提交
1836
        cur->lastKey = key + step;
1837 1838
        cur->mixBlock = true;

1839
        moveToNextRowInMem(pCheckInfo);
1840
      } else if (key == tsArray[pos]) {  // data in buffer has the same timestamp of data in file block, ignore it
H
TD-1439  
Hongze Cheng 已提交
1841
        if (pCfg->update) {
dengyihao's avatar
dengyihao 已提交
1842
          if (pCfg->update == TD_ROW_PARTIAL_UPDATE) {
1843
            doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, pos, pos);
D
fix bug  
dapan1121 已提交
1844
          }
H
Haojun Liao 已提交
1845
          if (rv1 != TD_ROW_SVER(row1)) {
dengyihao's avatar
dengyihao 已提交
1846
            //            pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
H
Haojun Liao 已提交
1847
            rv1 = TD_ROW_SVER(row1);
1848
          }
dengyihao's avatar
dengyihao 已提交
1849 1850
          if (row2 && rv2 != TD_ROW_SVER(row2)) {
            //            pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
H
Haojun Liao 已提交
1851
            rv2 = TD_ROW_SVER(row2);
1852
          }
dengyihao's avatar
dengyihao 已提交
1853

1854
          bool forceSetNull = pCfg->update != TD_ROW_PARTIAL_UPDATE;
dengyihao's avatar
dengyihao 已提交
1855 1856
          mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                             pCheckInfo->tableId, pSchema1, pSchema2, forceSetNull);
H
TD-1439  
Hongze Cheng 已提交
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
          numOfRows += 1;
          if (cur->win.skey == TSKEY_INITIAL_VAL) {
            cur->win.skey = key;
          }

          cur->win.ekey = key;
          cur->lastKey = key + step;
          cur->mixBlock = true;

          moveToNextRowInMem(pCheckInfo);
          pos += step;
        } else {
          moveToNextRowInMem(pCheckInfo);
        }
1871
      } else if ((key > tsArray[pos] && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
dengyihao's avatar
dengyihao 已提交
1872
                 (key < tsArray[pos] && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1873 1874 1875
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = tsArray[pos];
        }
1876

1877
        int32_t end = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, key, order);
1878 1879
        assert(end != -1);

dengyihao's avatar
dengyihao 已提交
1880
        if (tsArray[end] == key) {  // the value of key in cache equals to the end timestamp value, ignore it
1881
          if (pCfg->update == TD_ROW_DISCARD_UPDATE) {
H
Hongze Cheng 已提交
1882 1883 1884 1885
            moveToNextRowInMem(pCheckInfo);
          } else {
            end -= step;
          }
H
Haojun Liao 已提交
1886
        }
1887

1888
        int32_t qstart = 0, qend = 0;
1889
        getQualifiedRowsPos(pTsdbReadHandle, pos, end, numOfRows, &qstart, &qend);
1890

1891
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, qstart, qend);
1892 1893
        pos += (qend - qstart + 1) * step;

dengyihao's avatar
dengyihao 已提交
1894 1895
        cur->win.ekey = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? tsArray[qend] : tsArray[qstart];
        cur->lastKey = cur->win.ekey + step;
1896
      }
1897
    } while (numOfRows < pTsdbReadHandle->outputCapacity);
H
Haojun Liao 已提交
1898

1899
    if (numOfRows < pTsdbReadHandle->outputCapacity) {
H
Haojun Liao 已提交
1900 1901 1902 1903
      /**
       * if cache is empty, load remain file block data. In contrast, if there are remain data in cache, do NOT
       * copy them all to result buffer, since it may be overlapped with file data block.
       */
1904
      if (node == NULL ||
H
Haojun Liao 已提交
1905
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) > pTsdbReadHandle->window.ekey) &&
1906
           ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
H
Haojun Liao 已提交
1907
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) < pTsdbReadHandle->window.ekey) &&
1908
           !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1909 1910 1911 1912 1913
        // no data in cache or data in cache is greater than the ekey of time window, load data from file block
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = tsArray[pos];
        }

1914
        int32_t start = -1, end = -1;
1915
        getQualifiedRowsPos(pTsdbReadHandle, pos, endPos, numOfRows, &start, &end);
1916

1917
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, start, end);
1918
        pos += (end - start + 1) * step;
1919

dengyihao's avatar
dengyihao 已提交
1920 1921
        cur->win.ekey = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? tsArray[end] : tsArray[start];
        cur->lastKey = cur->win.ekey + step;
H
Haojun Liao 已提交
1922
        cur->mixBlock = true;
1923
      }
1924 1925
    }
  }
H
Haojun Liao 已提交
1926 1927

  cur->blockCompleted =
1928 1929
      (((pos > endPos || cur->lastKey > pTsdbReadHandle->window.ekey) && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
       ((pos < endPos || cur->lastKey < pTsdbReadHandle->window.ekey) && !ASCENDING_TRAVERSE(pTsdbReadHandle->order)));
1930

1931
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1932
    TSWAP(cur->win.skey, cur->win.ekey, TSKEY);
1933
  }
1934

1935 1936 1937
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
  updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
  doCheckGeneratedBlockRange(pTsdbReadHandle);
H
Haojun Liao 已提交
1938

dengyihao's avatar
dengyihao 已提交
1939 1940 1941
  tsdbDebug("%p uid:%" PRIu64 ", data block created, mixblock:%d, brange:%" PRIu64 "-%" PRIu64 " rows:%d, %s",
            pTsdbReadHandle, pCheckInfo->tableId, cur->mixBlock, cur->win.skey, cur->win.ekey, cur->rows,
            pTsdbReadHandle->idStr);
1942 1943
}

1944
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
H
[td-32]  
hjxilinx 已提交
1945
  int    firstPos, lastPos, midPos = -1;
H
Haojun Liao 已提交
1946
  int    numOfRows;
1947 1948
  TSKEY* keyList;

H
[td-32]  
hjxilinx 已提交
1949
  if (num <= 0) return -1;
1950 1951

  keyList = (TSKEY*)pValue;
H
[td-32]  
hjxilinx 已提交
1952 1953
  firstPos = 0;
  lastPos = num - 1;
1954

1955
  if (order == TSDB_ORDER_DESC) {
H
[td-32]  
hjxilinx 已提交
1956 1957 1958 1959 1960
    // 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;
1961

H
Haojun Liao 已提交
1962 1963
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1964

H
[td-32]  
hjxilinx 已提交
1965 1966 1967 1968 1969 1970 1971 1972
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
1973

H
[td-32]  
hjxilinx 已提交
1974 1975 1976 1977 1978
  } 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;
1979

H
[td-32]  
hjxilinx 已提交
1980 1981 1982 1983 1984 1985 1986
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
1987

H
Haojun Liao 已提交
1988 1989
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1990

H
[td-32]  
hjxilinx 已提交
1991 1992 1993 1994 1995 1996 1997 1998 1999
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2000

H
[td-32]  
hjxilinx 已提交
2001 2002 2003
  return midPos;
}

2004
static void cleanBlockOrderSupporter(SBlockOrderSupporter* pSupporter, int32_t numOfTables) {
wafwerar's avatar
wafwerar 已提交
2005 2006
  taosMemoryFreeClear(pSupporter->numOfBlocksPerTable);
  taosMemoryFreeClear(pSupporter->blockIndexArray);
2007 2008

  for (int32_t i = 0; i < numOfTables; ++i) {
H
Haojun Liao 已提交
2009
    STableBlockInfo* pBlockInfo = pSupporter->pDataBlockInfo[i];
wafwerar's avatar
wafwerar 已提交
2010
    taosMemoryFreeClear(pBlockInfo);
2011 2012
  }

wafwerar's avatar
wafwerar 已提交
2013
  taosMemoryFreeClear(pSupporter->pDataBlockInfo);
2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
}

static int32_t dataBlockOrderCompar(const void* pLeft, const void* pRight, void* param) {
  int32_t leftTableIndex = *(int32_t*)pLeft;
  int32_t rightTableIndex = *(int32_t*)pRight;

  SBlockOrderSupporter* pSupporter = (SBlockOrderSupporter*)param;

  int32_t leftTableBlockIndex = pSupporter->blockIndexArray[leftTableIndex];
  int32_t rightTableBlockIndex = pSupporter->blockIndexArray[rightTableIndex];

2025
  if (leftTableBlockIndex > pSupporter->numOfBlocksPerTable[leftTableIndex]) {
2026 2027
    /* left block is empty */
    return 1;
2028
  } else if (rightTableBlockIndex > pSupporter->numOfBlocksPerTable[rightTableIndex]) {
2029 2030 2031 2032 2033 2034 2035
    /* right block is empty */
    return -1;
  }

  STableBlockInfo* pLeftBlockInfoEx = &pSupporter->pDataBlockInfo[leftTableIndex][leftTableBlockIndex];
  STableBlockInfo* pRightBlockInfoEx = &pSupporter->pDataBlockInfo[rightTableIndex][rightTableBlockIndex];

H
Haojun Liao 已提交
2036
  //    assert(pLeftBlockInfoEx->compBlock->offset != pRightBlockInfoEx->compBlock->offset);
dengyihao's avatar
dengyihao 已提交
2037
#if 0  // TODO: temporarily comment off requested by Dr. Liao
H
Haojun Liao 已提交
2038 2039
  if (pLeftBlockInfoEx->compBlock->offset == pRightBlockInfoEx->compBlock->offset &&
      pLeftBlockInfoEx->compBlock->last == pRightBlockInfoEx->compBlock->last) {
B
Bomin Zhang 已提交
2040
    tsdbError("error in header file, two block with same offset:%" PRId64, (int64_t)pLeftBlockInfoEx->compBlock->offset);
2041
  }
H
Haojun Liao 已提交
2042
#endif
2043

H
Haojun Liao 已提交
2044
  return pLeftBlockInfoEx->compBlock->offset > pRightBlockInfoEx->compBlock->offset ? 1 : -1;
2045 2046
}

2047
static int32_t createDataBlocksInfo(STsdbReadHandle* pTsdbReadHandle, int32_t numOfBlocks, int32_t* numOfAllocBlocks) {
H
Haojun Liao 已提交
2048 2049
  size_t size = sizeof(STableBlockInfo) * numOfBlocks;

2050 2051
  if (pTsdbReadHandle->allocSize < size) {
    pTsdbReadHandle->allocSize = (int32_t)size;
wafwerar's avatar
wafwerar 已提交
2052
    char* tmp = taosMemoryRealloc(pTsdbReadHandle->pDataBlockInfo, pTsdbReadHandle->allocSize);
H
Haojun Liao 已提交
2053 2054 2055 2056
    if (tmp == NULL) {
      return TSDB_CODE_TDB_OUT_OF_MEMORY;
    }

dengyihao's avatar
dengyihao 已提交
2057
    pTsdbReadHandle->pDataBlockInfo = (STableBlockInfo*)tmp;
2058 2059
  }

2060
  memset(pTsdbReadHandle->pDataBlockInfo, 0, size);
2061 2062
  *numOfAllocBlocks = numOfBlocks;

H
Haojun Liao 已提交
2063
  // access data blocks according to the offset of each block in asc/desc order.
2064
  int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
2065

2066 2067
  SBlockOrderSupporter sup = {0};
  sup.numOfTables = numOfTables;
wafwerar's avatar
wafwerar 已提交
2068 2069 2070
  sup.numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.blockIndexArray = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
2071

2072
  if (sup.numOfBlocksPerTable == NULL || sup.blockIndexArray == NULL || sup.pDataBlockInfo == NULL) {
2073
    cleanBlockOrderSupporter(&sup, 0);
2074
    return TSDB_CODE_TDB_OUT_OF_MEMORY;
2075
  }
H
Haojun Liao 已提交
2076

2077
  int32_t cnt = 0;
2078
  int32_t numOfQualTables = 0;
H
Haojun Liao 已提交
2079

2080
  for (int32_t j = 0; j < numOfTables; ++j) {
2081
    STableCheckInfo* pTableCheck = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, j);
2082 2083 2084
    if (pTableCheck->numOfBlocks <= 0) {
      continue;
    }
H
Haojun Liao 已提交
2085

H
refact  
Hongze Cheng 已提交
2086
    SBlock* pBlock = pTableCheck->pCompInfo->blocks;
2087
    sup.numOfBlocksPerTable[numOfQualTables] = pTableCheck->numOfBlocks;
2088

wafwerar's avatar
wafwerar 已提交
2089
    char* buf = taosMemoryMalloc(sizeof(STableBlockInfo) * pTableCheck->numOfBlocks);
2090
    if (buf == NULL) {
2091
      cleanBlockOrderSupporter(&sup, numOfQualTables);
2092
      return TSDB_CODE_TDB_OUT_OF_MEMORY;
2093 2094
    }

2095
    sup.pDataBlockInfo[numOfQualTables] = (STableBlockInfo*)buf;
2096 2097

    for (int32_t k = 0; k < pTableCheck->numOfBlocks; ++k) {
H
Haojun Liao 已提交
2098
      STableBlockInfo* pBlockInfo = &sup.pDataBlockInfo[numOfQualTables][k];
2099

H
Haojun Liao 已提交
2100 2101
      pBlockInfo->compBlock = &pBlock[k];
      pBlockInfo->pTableCheckInfo = pTableCheck;
2102 2103 2104
      cnt++;
    }

2105
    numOfQualTables++;
2106 2107
  }

H
Haojun Liao 已提交
2108
  assert(numOfBlocks == cnt);
2109

H
Haojun Liao 已提交
2110 2111
  // since there is only one table qualified, blocks are not sorted
  if (numOfQualTables == 1) {
2112
    memcpy(pTsdbReadHandle->pDataBlockInfo, sup.pDataBlockInfo[0], sizeof(STableBlockInfo) * numOfBlocks);
H
Haojun Liao 已提交
2113
    cleanBlockOrderSupporter(&sup, numOfQualTables);
2114

H
Haojun Liao 已提交
2115
    tsdbDebug("%p create data blocks info struct completed for 1 table, %d blocks not sorted %s", pTsdbReadHandle, cnt,
dengyihao's avatar
dengyihao 已提交
2116
              pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
2117 2118
    return TSDB_CODE_SUCCESS;
  }
2119

H
Haojun Liao 已提交
2120
  tsdbDebug("%p create data blocks info struct completed, %d blocks in %d tables %s", pTsdbReadHandle, cnt,
dengyihao's avatar
dengyihao 已提交
2121
            numOfQualTables, pTsdbReadHandle->idStr);
2122

2123
  assert(cnt <= numOfBlocks && numOfQualTables <= numOfTables);  // the pTableQueryInfo[j]->numOfBlocks may be 0
2124
  sup.numOfTables = numOfQualTables;
2125

2126
  SMultiwayMergeTreeInfo* pTree = NULL;
dengyihao's avatar
dengyihao 已提交
2127
  uint8_t                 ret = tMergeTreeCreate(&pTree, sup.numOfTables, &sup, dataBlockOrderCompar);
2128 2129
  if (ret != TSDB_CODE_SUCCESS) {
    cleanBlockOrderSupporter(&sup, numOfTables);
2130
    return TSDB_CODE_TDB_OUT_OF_MEMORY;
2131 2132 2133 2134 2135
  }

  int32_t numOfTotal = 0;

  while (numOfTotal < cnt) {
2136
    int32_t pos = tMergeTreeGetChosenIndex(pTree);
2137 2138
    int32_t index = sup.blockIndexArray[pos]++;

H
Haojun Liao 已提交
2139
    STableBlockInfo* pBlocksInfo = sup.pDataBlockInfo[pos];
2140
    pTsdbReadHandle->pDataBlockInfo[numOfTotal++] = pBlocksInfo[index];
2141 2142

    // set data block index overflow, in order to disable the offset comparator
2143 2144
    if (sup.blockIndexArray[pos] >= sup.numOfBlocksPerTable[pos]) {
      sup.blockIndexArray[pos] = sup.numOfBlocksPerTable[pos] + 1;
2145
    }
2146

H
Haojun Liao 已提交
2147
    tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
2148 2149 2150 2151 2152
  }

  /*
   * available when no import exists
   * for(int32_t i = 0; i < cnt - 1; ++i) {
H
Haojun Liao 已提交
2153
   *   assert((*pDataBlockInfo)[i].compBlock->offset < (*pDataBlockInfo)[i+1].compBlock->offset);
2154 2155 2156
   * }
   */

H
Haojun Liao 已提交
2157
  tsdbDebug("%p %d data blocks sort completed, %s", pTsdbReadHandle, cnt, pTsdbReadHandle->idStr);
2158
  cleanBlockOrderSupporter(&sup, numOfTables);
wafwerar's avatar
wafwerar 已提交
2159
  taosMemoryFree(pTree);
2160 2161 2162 2163

  return TSDB_CODE_SUCCESS;
}

2164
static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists);
H
Haojun Liao 已提交
2165

dengyihao's avatar
dengyihao 已提交
2166 2167
static int32_t getDataBlockRv(STsdbReadHandle* pTsdbReadHandle, STableBlockInfo* pNext, bool* exists) {
  int32_t        step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
2168
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
2169

dengyihao's avatar
dengyihao 已提交
2170
  while (1) {
2171
    int32_t code = loadFileDataBlock(pTsdbReadHandle, pNext->compBlock, pNext->pTableCheckInfo, exists);
H
Haojun Liao 已提交
2172 2173 2174 2175
    if (code != TSDB_CODE_SUCCESS || *exists) {
      return code;
    }

2176 2177
    if ((cur->slot == pTsdbReadHandle->numOfBlocks - 1 && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
        (cur->slot == 0 && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
H
Haojun Liao 已提交
2178
      // all data blocks in current file has been checked already, try next file if exists
2179
      return getFirstFileDataBlock(pTsdbReadHandle, exists);
H
Haojun Liao 已提交
2180 2181 2182 2183
    } else {  // next block of the same file
      cur->slot += step;
      cur->mixBlock = false;
      cur->blockCompleted = false;
2184
      pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
H
Haojun Liao 已提交
2185 2186 2187 2188
    }
  }
}

2189 2190 2191
static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  pTsdbReadHandle->numOfBlocks = 0;
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
2192 2193 2194

  int32_t code = TSDB_CODE_SUCCESS;

2195
  int32_t numOfBlocks = 0;
2196
  int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
2197

dengyihao's avatar
dengyihao 已提交
2198
  STsdbCfg*   pCfg = &pTsdbReadHandle->pTsdb->config;
2199 2200
  STimeWindow win = TSWINDOW_INITIALIZER;

H
Hongze Cheng 已提交
2201
  while (true) {
2202
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2203

2204 2205
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2206 2207 2208
      break;
    }

H
refact  
Hongze Cheng 已提交
2209
    tsdbGetFidKeyRange(pCfg->days, pCfg->precision, pTsdbReadHandle->pFileGroup->fid, &win.skey, &win.ekey);
2210 2211

    // current file are not overlapped with query time window, ignore remain files
2212 2213 2214
    if ((ASCENDING_TRAVERSE(pTsdbReadHandle->order) && win.skey > pTsdbReadHandle->window.ekey) ||
        (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && win.ekey < pTsdbReadHandle->window.ekey)) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2215 2216
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
                pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
2217 2218
      pTsdbReadHandle->pFileGroup = NULL;
      assert(pTsdbReadHandle->numOfBlocks == 0);
2219 2220 2221
      break;
    }

2222 2223
    if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2224 2225 2226 2227
      code = terrno;
      break;
    }

2228
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2229

2230
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Hongze Cheng 已提交
2231 2232 2233 2234
      code = terrno;
      break;
    }

2235
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
2236 2237
      break;
    }
H
Haojun Liao 已提交
2238

H
Haojun Liao 已提交
2239 2240
    tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pTsdbReadHandle, numOfBlocks, numOfTables,
              pTsdbReadHandle->pFileGroup->fid, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
2241

2242 2243 2244 2245
    assert(numOfBlocks >= 0);
    if (numOfBlocks == 0) {
      continue;
    }
H
Haojun Liao 已提交
2246

2247
    // todo return error code to query engine
dengyihao's avatar
dengyihao 已提交
2248 2249
    if ((code = createDataBlocksInfo(pTsdbReadHandle, numOfBlocks, &pTsdbReadHandle->numOfBlocks)) !=
        TSDB_CODE_SUCCESS) {
2250 2251
      break;
    }
H
Haojun Liao 已提交
2252

2253 2254
    assert(numOfBlocks >= pTsdbReadHandle->numOfBlocks);
    if (pTsdbReadHandle->numOfBlocks > 0) {
2255 2256 2257
      break;
    }
  }
H
Haojun Liao 已提交
2258

2259
  // no data in file anymore
2260
  if (pTsdbReadHandle->numOfBlocks <= 0 || code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2261
    if (code == TSDB_CODE_SUCCESS) {
2262
      assert(pTsdbReadHandle->pFileGroup == NULL);
H
Haojun Liao 已提交
2263 2264
    }

D
dapan1121 已提交
2265
    cur->fid = INT32_MIN;  // denote that there are no data in file anymore
H
Haojun Liao 已提交
2266 2267
    *exists = false;
    return code;
2268
  }
H
Haojun Liao 已提交
2269

2270
  assert(pTsdbReadHandle->pFileGroup != NULL && pTsdbReadHandle->numOfBlocks > 0);
dengyihao's avatar
dengyihao 已提交
2271
  cur->slot = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 0 : pTsdbReadHandle->numOfBlocks - 1;
2272
  cur->fid = pTsdbReadHandle->pFileGroup->fid;
H
Haojun Liao 已提交
2273

2274 2275
  STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
  return getDataBlockRv(pTsdbReadHandle, pBlockInfo, exists);
H
Haojun Liao 已提交
2276 2277 2278 2279 2280 2281 2282
}

static bool isEndFileDataBlock(SQueryFilePos* cur, int32_t numOfBlocks, bool ascTrav) {
  assert(cur != NULL && numOfBlocks > 0);
  return (cur->slot == numOfBlocks - 1 && ascTrav) || (cur->slot == 0 && !ascTrav);
}

2283
static void moveToNextDataBlockInCurrentFile(STsdbReadHandle* pTsdbReadHandle) {
dengyihao's avatar
dengyihao 已提交
2284
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
H
Haojun Liao 已提交
2285

2286 2287
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
  assert(cur->slot < pTsdbReadHandle->numOfBlocks && cur->slot >= 0);
H
Haojun Liao 已提交
2288 2289

  cur->slot += step;
dengyihao's avatar
dengyihao 已提交
2290
  cur->mixBlock = false;
H
Haojun Liao 已提交
2291
  cur->blockCompleted = false;
2292
}
H
Haojun Liao 已提交
2293 2294

int32_t tsdbGetFileBlocksDistInfo(tsdbReaderT* queryHandle, STableBlockDistInfo* pTableBlockInfo) {
dengyihao's avatar
dengyihao 已提交
2295
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
H
Haojun Liao 已提交
2296

H
Haojun Liao 已提交
2297
  pTableBlockInfo->totalSize = 0;
2298
  pTableBlockInfo->totalRows = 0;
H
Haojun Liao 已提交
2299

2300
  STsdbFS* pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
2301 2302

  // find the start data block in file
2303 2304
  pTsdbReadHandle->locateStart = true;
  STsdbCfg* pCfg = &pTsdbReadHandle->pTsdb->config;
H
refact  
Hongze Cheng 已提交
2305
  int32_t   fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
H
Haojun Liao 已提交
2306 2307

  tsdbRLockFS(pFileHandle);
2308 2309
  tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
  tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Haojun Liao 已提交
2310 2311
  tsdbUnLockFS(pFileHandle);

H
Haojun Liao 已提交
2312
  pTableBlockInfo->numOfFiles += 1;
H
Haojun Liao 已提交
2313

H
Haojun Liao 已提交
2314
  int32_t     code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2315
  int32_t     numOfBlocks = 0;
2316
  int32_t     numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
dengyihao's avatar
dengyihao 已提交
2317
  int         defaultRows = 4096;  // TSDB_DEFAULT_BLOCK_ROWS(pCfg->maxRowsPerFileBlock);
H
Haojun Liao 已提交
2318 2319
  STimeWindow win = TSWINDOW_INITIALIZER;

H
Haojun Liao 已提交
2320 2321
  bool ascTraverse = ASCENDING_TRAVERSE(pTsdbReadHandle->order);

H
Haojun Liao 已提交
2322 2323
  while (true) {
    numOfBlocks = 0;
2324
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2325

2326 2327
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2328 2329 2330
      break;
    }

H
refact  
Hongze Cheng 已提交
2331
    tsdbGetFidKeyRange(pCfg->days, pCfg->precision, pTsdbReadHandle->pFileGroup->fid, &win.skey, &win.ekey);
H
Haojun Liao 已提交
2332 2333

    // current file are not overlapped with query time window, ignore remain files
dengyihao's avatar
dengyihao 已提交
2334 2335
    if ((ascTraverse && win.skey > pTsdbReadHandle->window.ekey) ||
        (!ascTraverse && win.ekey < pTsdbReadHandle->window.ekey)) {
2336
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2337 2338
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
                pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
2339
      pTsdbReadHandle->pFileGroup = NULL;
H
Haojun Liao 已提交
2340 2341 2342
      break;
    }

H
Haojun Liao 已提交
2343
    pTableBlockInfo->numOfFiles += 1;
2344 2345
    if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2346 2347 2348 2349
      code = terrno;
      break;
    }

2350
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2351

2352
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Haojun Liao 已提交
2353 2354 2355 2356
      code = terrno;
      break;
    }

2357
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2358 2359 2360
      break;
    }

H
Haojun Liao 已提交
2361 2362
    tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pTsdbReadHandle, numOfBlocks, numOfTables,
              pTsdbReadHandle->pFileGroup->fid, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
2363 2364 2365 2366 2367 2368

    if (numOfBlocks == 0) {
      continue;
    }

    for (int32_t i = 0; i < numOfTables; ++i) {
2369
      STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2370 2371 2372

      SBlock* pBlock = pCheckInfo->pCompInfo->blocks;
      for (int32_t j = 0; j < pCheckInfo->numOfBlocks; ++j) {
H
Haojun Liao 已提交
2373
        pTableBlockInfo->totalSize += pBlock[j].len;
H
Haojun Liao 已提交
2374

H
Haojun Liao 已提交
2375
        int32_t numOfRows = pBlock[j].numOfRows;
2376
        pTableBlockInfo->totalRows += numOfRows;
H
Haojun Liao 已提交
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
        if (numOfRows > pTableBlockInfo->maxRows) {
          pTableBlockInfo->maxRows = numOfRows;
        }

        if (numOfRows < pTableBlockInfo->minRows) {
          pTableBlockInfo->minRows = numOfRows;
        }

        if (numOfRows < defaultRows) {
          pTableBlockInfo->numOfSmallBlocks += 1;
        }
dengyihao's avatar
dengyihao 已提交
2388 2389 2390
        //        int32_t  stepIndex = (numOfRows-1)/TSDB_BLOCK_DIST_STEP_ROWS;
        //        SFileBlockInfo *blockInfo = (SFileBlockInfo*)taosArrayGet(pTableBlockInfo->dataBlockInfos, stepIndex);
        //        blockInfo->numBlocksOfStep++;
H
Haojun Liao 已提交
2391 2392 2393 2394 2395 2396 2397
      }
    }
  }

  return code;
}

2398 2399 2400
static int32_t getDataBlocksInFiles(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  STsdbFS*       pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2401 2402

  // find the start data block in file
2403 2404 2405
  if (!pTsdbReadHandle->locateStart) {
    pTsdbReadHandle->locateStart = true;
    STsdbCfg* pCfg = &pTsdbReadHandle->pTsdb->config;
H
refact  
Hongze Cheng 已提交
2406
    int32_t   fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
H
Haojun Liao 已提交
2407

H
Hongze Cheng 已提交
2408
    tsdbRLockFS(pFileHandle);
2409 2410
    tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
    tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Hongze Cheng 已提交
2411
    tsdbUnLockFS(pFileHandle);
2412

2413
    return getFirstFileDataBlock(pTsdbReadHandle, exists);
2414
  } else {
2415
    // check if current file block is all consumed
2416
    STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
2417
    STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
H
Haojun Liao 已提交
2418

2419
    // current block is done, try next
H
Haojun Liao 已提交
2420
    if ((!cur->mixBlock) || cur->blockCompleted) {
H
Haojun Liao 已提交
2421
      // all data blocks in current file has been checked already, try next file if exists
2422
    } else {
H
Haojun Liao 已提交
2423 2424
      tsdbDebug("%p continue in current data block, index:%d, pos:%d, %s", pTsdbReadHandle, cur->slot, cur->pos,
                pTsdbReadHandle->idStr);
2425 2426
      int32_t code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlockInfo->compBlock, pCheckInfo);
      *exists = (pTsdbReadHandle->realNumOfRows > 0);
H
Haojun Liao 已提交
2427

H
Haojun Liao 已提交
2428 2429 2430 2431 2432 2433 2434
      if (code != TSDB_CODE_SUCCESS || *exists) {
        return code;
      }
    }

    // current block is empty, try next block in file
    // all data blocks in current file has been checked already, try next file if exists
2435 2436
    if (isEndFileDataBlock(cur, pTsdbReadHandle->numOfBlocks, ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
      return getFirstFileDataBlock(pTsdbReadHandle, exists);
H
Haojun Liao 已提交
2437
    } else {
2438 2439 2440
      moveToNextDataBlockInCurrentFile(pTsdbReadHandle);
      STableBlockInfo* pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
      return getDataBlockRv(pTsdbReadHandle, pNext, exists);
2441 2442
    }
  }
2443 2444
}

2445 2446
static bool doHasDataInBuffer(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
dengyihao's avatar
dengyihao 已提交
2447

2448 2449
  while (pTsdbReadHandle->activeIndex < numOfTables) {
    if (hasMoreDataInCache(pTsdbReadHandle)) {
2450 2451
      return true;
    }
H
Haojun Liao 已提交
2452

2453
    pTsdbReadHandle->activeIndex += 1;
2454
  }
H
Haojun Liao 已提交
2455

2456 2457 2458
  return false;
}

dengyihao's avatar
dengyihao 已提交
2459
// todo not unref yet, since it is not support multi-group interpolation query
H
Haojun Liao 已提交
2460
static UNUSED_FUNC void changeQueryHandleForInterpQuery(tsdbReaderT pHandle) {
H
Haojun Liao 已提交
2461
  // filter the queried time stamp in the first place
dengyihao's avatar
dengyihao 已提交
2462
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
H
Haojun Liao 已提交
2463 2464

  // starts from the buffer in case of descending timestamp order check data blocks
2465
  size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
2466 2467

  int32_t i = 0;
dengyihao's avatar
dengyihao 已提交
2468
  while (i < numOfTables) {
2469
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2470 2471

    // the first qualified table for interpolation query
dengyihao's avatar
dengyihao 已提交
2472 2473 2474 2475
    //    if ((pTsdbReadHandle->window.skey <= pCheckInfo->pTableObj->lastKey) &&
    //        (pCheckInfo->pTableObj->lastKey != TSKEY_INITIAL_VAL)) {
    //      break;
    //    }
H
Haojun Liao 已提交
2476 2477 2478 2479 2480 2481 2482 2483 2484

    i++;
  }

  // there are no data in all the tables
  if (i == numOfTables) {
    return;
  }

dengyihao's avatar
dengyihao 已提交
2485
  STableCheckInfo info = *(STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
2486
  taosArrayClear(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
2487

2488 2489
  info.lastKey = pTsdbReadHandle->window.skey;
  taosArrayPush(pTsdbReadHandle->pTableCheckInfo, &info);
H
Haojun Liao 已提交
2490 2491 2492
}

static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
2493
                                 STsdbReadHandle* pTsdbReadHandle) {
dengyihao's avatar
dengyihao 已提交
2494 2495
  int       numOfRows = 0;
  int32_t   numOfCols = (int32_t)taosArrayGetSize(pTsdbReadHandle->pColumns);
2496
  STsdbCfg* pCfg = &pTsdbReadHandle->pTsdb->config;
H
Haojun Liao 已提交
2497 2498
  win->skey = TSKEY_INITIAL_VAL;

dengyihao's avatar
dengyihao 已提交
2499 2500
  int64_t   st = taosGetTimestampUs();
  int16_t   rv = -1;
D
fix bug  
dapan1121 已提交
2501
  STSchema* pSchema = NULL;
H
Haojun Liao 已提交
2502 2503

  do {
H
Haojun Liao 已提交
2504
    STSRow* row = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, NULL);
H
Haojun Liao 已提交
2505 2506 2507 2508
    if (row == NULL) {
      break;
    }

H
Haojun Liao 已提交
2509
    TSKEY key = TD_ROW_KEY(row);
dengyihao's avatar
dengyihao 已提交
2510 2511 2512 2513
    if ((key > maxKey && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
        (key < maxKey && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
      tsdbDebug("%p key:%" PRIu64 " beyond qrange:%" PRId64 " - %" PRId64 ", no more data in buffer", pTsdbReadHandle,
                key, pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
2514 2515 2516 2517 2518 2519 2520 2521 2522

      break;
    }

    if (win->skey == INT64_MIN) {
      win->skey = key;
    }

    win->ekey = key;
H
Haojun Liao 已提交
2523
    if (rv != TD_ROW_SVER(row)) {
H
Hongze Cheng 已提交
2524
      pSchema = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), pCheckInfo->tableId, 0);
H
Haojun Liao 已提交
2525
      rv = TD_ROW_SVER(row);
D
fix bug  
dapan1121 已提交
2526
    }
dengyihao's avatar
dengyihao 已提交
2527 2528
    mergeTwoRowFromMem(pTsdbReadHandle, maxRowsToRead, numOfRows, row, NULL, numOfCols, pCheckInfo->tableId, pSchema,
                       NULL, true);
H
Haojun Liao 已提交
2529 2530 2531 2532 2533 2534

    if (++numOfRows >= maxRowsToRead) {
      moveToNextRowInMem(pCheckInfo);
      break;
    }

dengyihao's avatar
dengyihao 已提交
2535
  } while (moveToNextRowInMem(pCheckInfo));
H
Haojun Liao 已提交
2536 2537 2538 2539

  assert(numOfRows <= maxRowsToRead);

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
2540
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && numOfRows < maxRowsToRead) {
H
Haojun Liao 已提交
2541 2542
    int32_t emptySize = maxRowsToRead - numOfRows;

dengyihao's avatar
dengyihao 已提交
2543
    for (int32_t i = 0; i < numOfCols; ++i) {
2544
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
2545 2546
      memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes,
              numOfRows * pColInfo->info.bytes);
H
Haojun Liao 已提交
2547 2548 2549 2550
    }
  }

  int64_t elapsedTime = taosGetTimestampUs() - st;
dengyihao's avatar
dengyihao 已提交
2551 2552
  tsdbDebug("%p build data block from cache completed, elapsed time:%" PRId64 " us, numOfRows:%d, numOfCols:%d, %s",
            pTsdbReadHandle, elapsedTime, numOfRows, numOfCols, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
2553 2554 2555 2556

  return numOfRows;
}

2557 2558
static int32_t getAllTableList(SMeta* pMeta, uint64_t uid, SArray* list) {
  SMCtbCursor* pCur = metaOpenCtbCursor(pMeta, uid);
H
Haojun Liao 已提交
2559

2560 2561 2562 2563 2564
  while (1) {
    tb_uid_t id = metaCtbCursorNext(pCur);
    if (id == 0) {
      break;
    }
H
Haojun Liao 已提交
2565

2566
    STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, uid = id};
H
Haojun Liao 已提交
2567 2568 2569
    taosArrayPush(list, &info);
  }

2570
  metaCloseCtbCurosr(pCur);
H
Haojun Liao 已提交
2571 2572 2573 2574 2575 2576 2577 2578
  return TSDB_CODE_SUCCESS;
}

static void destroyHelper(void* param) {
  if (param == NULL) {
    return;
  }

dengyihao's avatar
dengyihao 已提交
2579 2580 2581 2582 2583 2584
  //  tQueryInfo* pInfo = (tQueryInfo*)param;
  //  if (pInfo->optr != TSDB_RELATION_IN) {
  //    taosMemoryFreeClear(pInfo->q);
  //  } else {
  //    taosHashCleanup((SHashObj *)(pInfo->q));
  //  }
H
Haojun Liao 已提交
2585

wafwerar's avatar
wafwerar 已提交
2586
  taosMemoryFree(param);
H
Haojun Liao 已提交
2587 2588
}

dengyihao's avatar
dengyihao 已提交
2589 2590
#define TSDB_PREV_ROW 0x1
#define TSDB_NEXT_ROW 0x2
2591

dengyihao's avatar
dengyihao 已提交
2592
static bool loadBlockOfActiveTable(STsdbReadHandle* pTsdbReadHandle) {
2593
  if (pTsdbReadHandle->checkFiles) {
H
Haojun Liao 已提交
2594 2595
    // check if the query range overlaps with the file data block
    bool exists = true;
H
Haojun Liao 已提交
2596

2597
    int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
H
Haojun Liao 已提交
2598
    if (code != TSDB_CODE_SUCCESS) {
2599
      pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2600 2601
      return false;
    }
H
Haojun Liao 已提交
2602

H
Haojun Liao 已提交
2603
    if (exists) {
dengyihao's avatar
dengyihao 已提交
2604
      tsdbRetrieveDataBlock((tsdbReaderT*)pTsdbReadHandle, NULL);
2605 2606 2607
      if (pTsdbReadHandle->currentLoadExternalRows && pTsdbReadHandle->window.skey == pTsdbReadHandle->window.ekey) {
        SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, 0);
        assert(*(int64_t*)pColInfo->pData == pTsdbReadHandle->window.skey);
H
Haojun Liao 已提交
2608 2609
      }

dengyihao's avatar
dengyihao 已提交
2610
      pTsdbReadHandle->currentLoadExternalRows = false;  // clear the flag, since the exact matched row is found.
H
Haojun Liao 已提交
2611 2612
      return exists;
    }
H
Haojun Liao 已提交
2613

2614
    pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2615
  }
H
Haojun Liao 已提交
2616

2617 2618
  if (hasMoreDataInCache(pTsdbReadHandle)) {
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2619 2620
    return true;
  }
H
Haojun Liao 已提交
2621

H
Haojun Liao 已提交
2622
  // current result is empty
dengyihao's avatar
dengyihao 已提交
2623 2624 2625
  if (pTsdbReadHandle->currentLoadExternalRows && pTsdbReadHandle->window.skey == pTsdbReadHandle->window.ekey &&
      pTsdbReadHandle->cur.rows == 0) {
    //    STsdbMemTable* pMemRef = pTsdbReadHandle->pMemTable;
H
Haojun Liao 已提交
2626

dengyihao's avatar
dengyihao 已提交
2627 2628
    //    doGetExternalRow(pTsdbReadHandle, TSDB_PREV_ROW, pMemRef);
    //    doGetExternalRow(pTsdbReadHandle, TSDB_NEXT_ROW, pMemRef);
H
Haojun Liao 已提交
2629

2630
    bool result = tsdbGetExternalRow(pTsdbReadHandle);
H
Haojun Liao 已提交
2631

dengyihao's avatar
dengyihao 已提交
2632 2633
    //    pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
    //    pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
2634
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2635 2636

    return result;
2637
  }
H
Haojun Liao 已提交
2638

H
Haojun Liao 已提交
2639 2640
  return false;
}
2641

2642
static bool loadCachedLastRow(STsdbReadHandle* pTsdbReadHandle) {
H
Haojun Liao 已提交
2643
  // the last row is cached in buffer, return it directly.
2644
  // here note that the pTsdbReadHandle->window must be the TS_INITIALIZER
dengyihao's avatar
dengyihao 已提交
2645
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
2646
  size_t  numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
2647 2648
  assert(numOfTables > 0 && numOfCols > 0);

2649
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2650

dengyihao's avatar
dengyihao 已提交
2651 2652 2653
  STSRow* pRow = NULL;
  TSKEY   key = TSKEY_INITIAL_VAL;
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
2654 2655 2656

  if (++pTsdbReadHandle->activeIndex < numOfTables) {
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
dengyihao's avatar
dengyihao 已提交
2657 2658 2659 2660 2661 2662
    //    int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key);
    //    if (ret != TSDB_CODE_SUCCESS) {
    //      return false;
    //    }
    mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, pRow, NULL, numOfCols, pCheckInfo->tableId,
                       NULL, NULL, true);
wafwerar's avatar
wafwerar 已提交
2663
    taosMemoryFreeClear(pRow);
H
Haojun Liao 已提交
2664

H
Haojun Liao 已提交
2665 2666 2667
    // update the last key value
    pCheckInfo->lastKey = key + step;

dengyihao's avatar
dengyihao 已提交
2668 2669
    cur->rows = 1;  // only one row
    cur->lastKey = key + step;
H
Haojun Liao 已提交
2670 2671 2672 2673 2674
    cur->mixBlock = true;
    cur->win.skey = key;
    cur->win.ekey = key;

    return true;
2675
  }
H
Haojun Liao 已提交
2676

H
Haojun Liao 已提交
2677 2678 2679
  return false;
}

dengyihao's avatar
dengyihao 已提交
2680
// static bool loadCachedLast(STsdbReadHandle* pTsdbReadHandle) {
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699
//  // the last row is cached in buffer, return it directly.
//  // here note that the pTsdbReadHandle->window must be the TS_INITIALIZER
//  int32_t tgNumOfCols = (int32_t)QH_GET_NUM_OF_COLS(pTsdbReadHandle);
//  size_t  numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
//  int32_t numOfRows = 0;
//  assert(numOfTables > 0 && tgNumOfCols > 0);
//  SQueryFilePos* cur = &pTsdbReadHandle->cur;
//  TSKEY priKey = TSKEY_INITIAL_VAL;
//  int32_t priIdx = -1;
//  SColumnInfoData* pColInfo = NULL;
//
//  while (++pTsdbReadHandle->activeIndex < numOfTables) {
//    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
//    STable* pTable = pCheckInfo->pTableObj;
//    char* pData = NULL;
//
//    int32_t numOfCols = pTable->maxColNum;
//
//    if (pTable->lastCols == NULL || pTable->maxColNum <= 0) {
dengyihao's avatar
dengyihao 已提交
2700 2701
//      tsdbWarn("no last cached for table %s, uid:%" PRIu64 ",tid:%d", pTable->name->data, pTable->uid,
//      pTable->tableId); continue;
2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831
//    }
//
//    int32_t i = 0, j = 0;
//    while(i < tgNumOfCols && j < numOfCols) {
//      pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
//      if (pTable->lastCols[j].colId < pColInfo->info.colId) {
//        j++;
//        continue;
//      } else if (pTable->lastCols[j].colId > pColInfo->info.colId) {
//        i++;
//        continue;
//      }
//
//      pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
//
//      if (pTable->lastCols[j].bytes > 0) {
//        void* value = pTable->lastCols[j].pData;
//        switch (pColInfo->info.type) {
//          case TSDB_DATA_TYPE_BINARY:
//          case TSDB_DATA_TYPE_NCHAR:
//            memcpy(pData, value, varDataTLen(value));
//            break;
//          case TSDB_DATA_TYPE_NULL:
//          case TSDB_DATA_TYPE_BOOL:
//          case TSDB_DATA_TYPE_TINYINT:
//          case TSDB_DATA_TYPE_UTINYINT:
//            *(uint8_t *)pData = *(uint8_t *)value;
//            break;
//          case TSDB_DATA_TYPE_SMALLINT:
//          case TSDB_DATA_TYPE_USMALLINT:
//            *(uint16_t *)pData = *(uint16_t *)value;
//            break;
//          case TSDB_DATA_TYPE_INT:
//          case TSDB_DATA_TYPE_UINT:
//            *(uint32_t *)pData = *(uint32_t *)value;
//            break;
//          case TSDB_DATA_TYPE_BIGINT:
//          case TSDB_DATA_TYPE_UBIGINT:
//            *(uint64_t *)pData = *(uint64_t *)value;
//            break;
//          case TSDB_DATA_TYPE_FLOAT:
//            SET_FLOAT_PTR(pData, value);
//            break;
//          case TSDB_DATA_TYPE_DOUBLE:
//            SET_DOUBLE_PTR(pData, value);
//            break;
//          case TSDB_DATA_TYPE_TIMESTAMP:
//            if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
//              priKey = tdGetKey(*(TKEY *)value);
//              priIdx = i;
//
//              i++;
//              j++;
//              continue;
//            } else {
//              *(TSKEY *)pData = *(TSKEY *)value;
//            }
//            break;
//          default:
//            memcpy(pData, value, pColInfo->info.bytes);
//        }
//
//        for (int32_t n = 0; n < tgNumOfCols; ++n) {
//          if (n == i) {
//            continue;
//          }
//
//          pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, n);
//          pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;;
//
//          if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
////            *(TSKEY *)pData = pTable->lastCols[j].ts;
//            continue;
//          }
//
//          if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
//            setVardataNull(pData, pColInfo->info.type);
//          } else {
//            setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
//          }
//        }
//
//        numOfRows++;
//        assert(numOfRows < pTsdbReadHandle->outputCapacity);
//      }
//
//      i++;
//      j++;
//    }
//
//    // leave the real ts column as the last row, because last function only (not stable) use the last row as res
//    if (priKey != TSKEY_INITIAL_VAL) {
//      pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, priIdx);
//      pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
//
//      *(TSKEY *)pData = priKey;
//
//      for (int32_t n = 0; n < tgNumOfCols; ++n) {
//        if (n == priIdx) {
//          continue;
//        }
//
//        pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, n);
//        pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;;
//
//        assert (pColInfo->info.colId != PRIMARYKEY_TIMESTAMP_COL_ID);
//
//        if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
//          setVardataNull(pData, pColInfo->info.type);
//        } else {
//          setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
//        }
//      }
//
//      numOfRows++;
//    }
//
//    if (numOfRows > 0) {
//      cur->rows     = numOfRows;
//      cur->mixBlock = true;
//
//      return true;
//    }
//  }
//
//  return false;
//}

static bool loadDataBlockFromTableSeq(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
2832 2833 2834
  assert(numOfTables > 0);

  int64_t stime = taosGetTimestampUs();
H
Haojun Liao 已提交
2835

dengyihao's avatar
dengyihao 已提交
2836
  while (pTsdbReadHandle->activeIndex < numOfTables) {
2837
    if (loadBlockOfActiveTable(pTsdbReadHandle)) {
H
Haojun Liao 已提交
2838 2839 2840
      return true;
    }

2841
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
H
Haojun Liao 已提交
2842 2843
    pCheckInfo->numOfBlocks = 0;

2844 2845
    pTsdbReadHandle->activeIndex += 1;
    pTsdbReadHandle->locateStart = false;
dengyihao's avatar
dengyihao 已提交
2846 2847
    pTsdbReadHandle->checkFiles = true;
    pTsdbReadHandle->cur.rows = 0;
2848
    pTsdbReadHandle->currentLoadExternalRows = pTsdbReadHandle->loadExternalRow;
H
Haojun Liao 已提交
2849 2850 2851 2852

    terrno = TSDB_CODE_SUCCESS;

    int64_t elapsedTime = taosGetTimestampUs() - stime;
2853
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2854 2855 2856
  }

  return false;
2857 2858
}

H
Haojun Liao 已提交
2859
// handle data in cache situation
H
Haojun Liao 已提交
2860
bool tsdbNextDataBlock(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
2861
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
Y
yihaoDeng 已提交
2862

dengyihao's avatar
dengyihao 已提交
2863
  for (int32_t i = 0; i < taosArrayGetSize(pTsdbReadHandle->pColumns); ++i) {
2864 2865 2866 2867
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
    colInfoDataCleanup(pColInfo, pTsdbReadHandle->outputCapacity);
  }

2868
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
2869 2870
    tsdbDebug("%p query window not overlaps with the data set, no result returned, %s", pTsdbReadHandle,
              pTsdbReadHandle->idStr);
2871 2872 2873
    return false;
  }

Y
yihaoDeng 已提交
2874 2875 2876
  int64_t stime = taosGetTimestampUs();
  int64_t elapsedTime = stime;

2877
  // TODO refactor: remove "type"
2878 2879
  if (pTsdbReadHandle->type == TSDB_QUERY_TYPE_LAST) {
    if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LASTROW) {
dengyihao's avatar
dengyihao 已提交
2880
      //      return loadCachedLastRow(pTsdbReadHandle);
2881
    } else if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LAST) {
dengyihao's avatar
dengyihao 已提交
2882
      //      return loadCachedLast(pTsdbReadHandle);
D
init  
dapan1121 已提交
2883
    }
H
Haojun Liao 已提交
2884
  }
Y
yihaoDeng 已提交
2885

2886 2887
  if (pTsdbReadHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) {
    return loadDataBlockFromTableSeq(pTsdbReadHandle);
dengyihao's avatar
dengyihao 已提交
2888
  } else {  // loadType == RR and Offset Order
2889
    if (pTsdbReadHandle->checkFiles) {
H
Haojun Liao 已提交
2890 2891 2892
      // check if the query range overlaps with the file data block
      bool exists = true;

2893
      int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
H
Haojun Liao 已提交
2894
      if (code != TSDB_CODE_SUCCESS) {
2895 2896
        pTsdbReadHandle->activeIndex = 0;
        pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2897 2898 2899 2900 2901

        return false;
      }

      if (exists) {
2902
        pTsdbReadHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime);
H
Haojun Liao 已提交
2903 2904
        return exists;
      }
Y
yihaoDeng 已提交
2905

2906 2907
      pTsdbReadHandle->activeIndex = 0;
      pTsdbReadHandle->checkFiles = false;
Y
yihaoDeng 已提交
2908 2909
    }

H
Haojun Liao 已提交
2910
    // TODO: opt by consider the scan order
2911
    bool ret = doHasDataInBuffer(pTsdbReadHandle);
H
Haojun Liao 已提交
2912
    terrno = TSDB_CODE_SUCCESS;
Y
yihaoDeng 已提交
2913

H
Haojun Liao 已提交
2914
    elapsedTime = taosGetTimestampUs() - stime;
2915
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2916
    return ret;
Y
yihaoDeng 已提交
2917 2918
  }
}
2919

dengyihao's avatar
dengyihao 已提交
2920
// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, STsdbMemTable* pMemRef) {
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954
//  STsdbReadHandle* pSecQueryHandle = NULL;
//
//  if (type == TSDB_PREV_ROW && pTsdbReadHandle->prev) {
//    return TSDB_CODE_SUCCESS;
//  }
//
//  if (type == TSDB_NEXT_ROW && pTsdbReadHandle->next) {
//    return TSDB_CODE_SUCCESS;
//  }
//
//  // prepare the structure
//  int32_t numOfCols = (int32_t) QH_GET_NUM_OF_COLS(pTsdbReadHandle);
//
//  if (type == TSDB_PREV_ROW) {
//    pTsdbReadHandle->prev = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
//    if (pTsdbReadHandle->prev == NULL) {
//      terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//      goto out_of_memory;
//    }
//  } else {
//    pTsdbReadHandle->next = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
//    if (pTsdbReadHandle->next == NULL) {
//      terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//      goto out_of_memory;
//    }
//  }
//
//  SArray* row = (type == TSDB_PREV_ROW)? pTsdbReadHandle->prev : pTsdbReadHandle->next;
//
//  for (int32_t i = 0; i < numOfCols; ++i) {
//    SColumnInfoData* pCol = taosArrayGet(pTsdbReadHandle->pColumns, i);
//
//    SColumnInfoData colInfo = {{0}, 0};
//    colInfo.info = pCol->info;
wafwerar's avatar
wafwerar 已提交
2955
//    colInfo.pData = taosMemoryCalloc(1, pCol->info.bytes);
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973
//    if (colInfo.pData == NULL) {
//      terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//      goto out_of_memory;
//    }
//
//    taosArrayPush(row, &colInfo);
//  }
//
//  // load the previous row
//  STsdbQueryCond cond = {.numOfCols = numOfCols, .loadExternalRows = false, .type = BLOCK_LOAD_OFFSET_SEQ_ORDER};
//  if (type == TSDB_PREV_ROW) {
//    cond.order = TSDB_ORDER_DESC;
//    cond.twindow = (STimeWindow){pTsdbReadHandle->window.skey, INT64_MIN};
//  } else {
//    cond.order = TSDB_ORDER_ASC;
//    cond.twindow = (STimeWindow){pTsdbReadHandle->window.skey, INT64_MAX};
//  }
//
wafwerar's avatar
wafwerar 已提交
2974
//  cond.colList = taosMemoryCalloc(cond.numOfCols, sizeof(SColumnInfo));
2975 2976 2977 2978 2979 2980 2981 2982 2983 2984
//  if (cond.colList == NULL) {
//    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//    goto out_of_memory;
//  }
//
//  for (int32_t i = 0; i < cond.numOfCols; ++i) {
//    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, i);
//    memcpy(&cond.colList[i], &pColInfoData->info, sizeof(SColumnInfo));
//  }
//
H
Haojun Liao 已提交
2985
//  pSecQueryHandle = tsdbQueryTablesImpl(pTsdbReadHandle->pTsdb, &cond, pTsdbReadHandle->idStr, pMemRef);
wafwerar's avatar
wafwerar 已提交
2986
//  taosMemoryFreeClear(cond.colList);
2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
//
//  // current table, only one table
//  STableCheckInfo* pCurrent = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
//
//  SArray* psTable = NULL;
//  pSecQueryHandle->pTableCheckInfo = createCheckInfoFromCheckInfo(pCurrent, pSecQueryHandle->window.skey, &psTable);
//  if (pSecQueryHandle->pTableCheckInfo == NULL) {
//    taosArrayDestroy(psTable);
//    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//    goto out_of_memory;
//  }
//
//
//  tsdbMayTakeMemSnapshot(pSecQueryHandle, psTable);
//  if (!tsdbNextDataBlock((void*)pSecQueryHandle)) {
//    // no result in current query, free the corresponding result rows structure
//    if (type == TSDB_PREV_ROW) {
//      pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
//    } else {
//      pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
//    }
//
//    goto out_of_memory;
//  }
//
//  SDataBlockInfo blockInfo = {{0}, 0};
//  tsdbRetrieveDataBlockInfo((void*)pSecQueryHandle, &blockInfo);
//  tsdbRetrieveDataBlock((void*)pSecQueryHandle, pSecQueryHandle->defaultLoadColumn);
//
//  row = (type == TSDB_PREV_ROW)? pTsdbReadHandle->prev:pTsdbReadHandle->next;
//  int32_t pos = (type == TSDB_PREV_ROW)?pSecQueryHandle->cur.rows - 1:0;
//
//  for (int32_t i = 0; i < numOfCols; ++i) {
//    SColumnInfoData* pCol = taosArrayGet(row, i);
//    SColumnInfoData* s = taosArrayGet(pSecQueryHandle->pColumns, i);
//    memcpy((char*)pCol->pData, (char*)s->pData + s->info.bytes * pos, pCol->info.bytes);
//  }
//
dengyihao's avatar
dengyihao 已提交
3025
// out_of_memory:
3026
//  tsdbCleanupReadHandle(pSecQueryHandle);
3027 3028 3029
//  return terrno;
//}

H
Haojun Liao 已提交
3030
bool tsdbGetExternalRow(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
3031 3032
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
  SQueryFilePos*   cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
3033

H
Haojun Liao 已提交
3034 3035
  cur->fid = INT32_MIN;
  cur->mixBlock = true;
3036
  if (pTsdbReadHandle->prev == NULL || pTsdbReadHandle->next == NULL) {
H
Haojun Liao 已提交
3037 3038
    cur->rows = 0;
    return false;
H
Haojun Liao 已提交
3039 3040
  }

dengyihao's avatar
dengyihao 已提交
3041
  int32_t numOfCols = (int32_t)QH_GET_NUM_OF_COLS(pTsdbReadHandle);
H
Haojun Liao 已提交
3042
  for (int32_t i = 0; i < numOfCols; ++i) {
3043 3044
    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, i);
    SColumnInfoData* first = taosArrayGet(pTsdbReadHandle->prev, i);
H
Haojun Liao 已提交
3045 3046 3047

    memcpy(pColInfoData->pData, first->pData, pColInfoData->info.bytes);

3048
    SColumnInfoData* sec = taosArrayGet(pTsdbReadHandle->next, i);
sangshuduo's avatar
sangshuduo 已提交
3049
    memcpy(((char*)pColInfoData->pData) + pColInfoData->info.bytes, sec->pData, pColInfoData->info.bytes);
H
Haojun Liao 已提交
3050 3051

    if (i == 0 && pColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
H
Haojun Liao 已提交
3052
      cur->win.skey = *(TSKEY*)pColInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3053
      cur->win.ekey = *(TSKEY*)(((char*)pColInfoData->pData) + TSDB_KEYSIZE);
H
Haojun Liao 已提交
3054 3055 3056
    }
  }

H
Haojun Liao 已提交
3057 3058
  cur->rows = 2;
  return true;
3059 3060
}

3061
/*
3062
 * if lastRow == NULL, return TSDB_CODE_TDB_NO_CACHE_LAST_ROW
3063
 * else set pRes and return TSDB_CODE_SUCCESS and save lastKey
3064
 */
H
Haojun Liao 已提交
3065
// int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey) {
3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081
//  int32_t code = TSDB_CODE_SUCCESS;
//
//  TSDB_RLOCK_TABLE(pTable);
//
//  if (!pTable->lastRow) {
//    code = TSDB_CODE_TDB_NO_CACHE_LAST_ROW;
//    goto out;
//  }
//
//  if (pRes) {
//    *pRes = tdMemRowDup(pTable->lastRow);
//    if (*pRes == NULL) {
//      code = TSDB_CODE_TDB_OUT_OF_MEMORY;
//    }
//  }
//
H
Haojun Liao 已提交
3082
// out:
3083 3084 3085 3086
//  TSDB_RUNLOCK_TABLE(pTable);
//  return code;
//}

3087
bool isTsdbCacheLastRow(tsdbReaderT* pReader) {
dengyihao's avatar
dengyihao 已提交
3088
  return ((STsdbReadHandle*)pReader)->cachelastrow > TSDB_CACHED_TYPE_NONE;
D
fix bug  
dapan1121 已提交
3089 3090
}

dengyihao's avatar
dengyihao 已提交
3091
int32_t checkForCachedLastRow(STsdbReadHandle* pTsdbReadHandle, STableGroupInfo* groupList) {
3092 3093
  assert(pTsdbReadHandle != NULL && groupList != NULL);

dengyihao's avatar
dengyihao 已提交
3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117
  //  TSKEY    key = TSKEY_INITIAL_VAL;
  //
  //  SArray* group = taosArrayGetP(groupList->pGroupList, 0);
  //  assert(group != NULL);
  //
  //  STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(group, 0);
  //
  //  int32_t code = 0;
  //
  //  if (((STable*)pInfo->pTable)->lastRow) {
  //    code = tsdbGetCachedLastRow(pInfo->pTable, NULL, &key);
  //    if (code != TSDB_CODE_SUCCESS) {
  //      pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_NONE;
  //    } else {
  //      pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LASTROW;
  //    }
  //  }
  //
  //  // update the tsdb query time range
  //  if (pTsdbReadHandle->cachelastrow != TSDB_CACHED_TYPE_NONE) {
  //    pTsdbReadHandle->window      = TSWINDOW_INITIALIZER;
  //    pTsdbReadHandle->checkFiles  = false;
  //    pTsdbReadHandle->activeIndex = -1;  // start from -1
  //  }
H
Haojun Liao 已提交
3118

3119
  return TSDB_CODE_SUCCESS;
3120 3121
}

3122 3123
int32_t checkForCachedLast(STsdbReadHandle* pTsdbReadHandle) {
  assert(pTsdbReadHandle != NULL);
D
update  
dapan1121 已提交
3124 3125

  int32_t code = 0;
dengyihao's avatar
dengyihao 已提交
3126 3127 3128
  //  if (pTsdbReadHandle->pTsdb && atomic_load_8(&pTsdbReadHandle->pTsdb->hasCachedLastColumn)){
  //    pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LAST;
  //  }
D
update  
dapan1121 已提交
3129 3130

  // update the tsdb query time range
3131
  if (pTsdbReadHandle->cachelastrow) {
dengyihao's avatar
dengyihao 已提交
3132
    pTsdbReadHandle->checkFiles = false;
3133
    pTsdbReadHandle->activeIndex = -1;  // start from -1
D
update  
dapan1121 已提交
3134 3135 3136 3137 3138
  }

  return code;
}

dengyihao's avatar
dengyihao 已提交
3139
STimeWindow updateLastrowForEachGroup(STableGroupInfo* groupList) {
H
Haojun Liao 已提交
3140
  STimeWindow window = {INT64_MAX, INT64_MIN};
H
Haojun Liao 已提交
3141

H
Haojun Liao 已提交
3142
  int32_t totalNumOfTable = 0;
3143
  SArray* emptyGroup = taosArrayInit(16, sizeof(int32_t));
H
Haojun Liao 已提交
3144

H
Haojun Liao 已提交
3145 3146
  // NOTE: starts from the buffer in case of descending timestamp order check data blocks
  size_t numOfGroups = taosArrayGetSize(groupList->pGroupList);
dengyihao's avatar
dengyihao 已提交
3147
  for (int32_t j = 0; j < numOfGroups; ++j) {
H
Haojun Liao 已提交
3148 3149
    SArray* pGroup = taosArrayGetP(groupList->pGroupList, j);
    TSKEY   key = TSKEY_INITIAL_VAL;
H
Haojun Liao 已提交
3150

H
Haojun Liao 已提交
3151
    STableKeyInfo keyInfo = {0};
H
Haojun Liao 已提交
3152

H
Haojun Liao 已提交
3153
    size_t numOfTables = taosArrayGetSize(pGroup);
dengyihao's avatar
dengyihao 已提交
3154 3155
    for (int32_t i = 0; i < numOfTables; ++i) {
      STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i);
H
Haojun Liao 已提交
3156

H
Haojun Liao 已提交
3157
      // if the lastKey equals to INT64_MIN, there is no data in this table
dengyihao's avatar
dengyihao 已提交
3158
      TSKEY lastKey = 0;  //((STable*)(pInfo->pTable))->lastKey;
H
Haojun Liao 已提交
3159 3160
      if (key < lastKey) {
        key = lastKey;
H
Haojun Liao 已提交
3161

dengyihao's avatar
dengyihao 已提交
3162
        //        keyInfo.pTable  = pInfo->pTable;
H
Haojun Liao 已提交
3163
        keyInfo.lastKey = key;
dengyihao's avatar
dengyihao 已提交
3164
        pInfo->lastKey = key;
H
Haojun Liao 已提交
3165

H
Haojun Liao 已提交
3166 3167 3168
        if (key < window.skey) {
          window.skey = key;
        }
3169

H
Haojun Liao 已提交
3170 3171 3172 3173
        if (key > window.ekey) {
          window.ekey = key;
        }
      }
3174
    }
H
Haojun Liao 已提交
3175

H
Haojun Liao 已提交
3176
    // more than one table in each group, only one table left for each group
dengyihao's avatar
dengyihao 已提交
3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188
    //    if (keyInfo.pTable != NULL) {
    //      totalNumOfTable++;
    //      if (taosArrayGetSize(pGroup) == 1) {
    //        // do nothing
    //      } else {
    //        taosArrayClear(pGroup);
    //        taosArrayPush(pGroup, &keyInfo);
    //      }
    //    } else {  // mark all the empty groups, and remove it later
    //      taosArrayDestroy(pGroup);
    //      taosArrayPush(emptyGroup, &j);
    //    }
3189
  }
H
Haojun Liao 已提交
3190

H
Haojun Liao 已提交
3191 3192 3193
  // window does not being updated, so set the original
  if (window.skey == INT64_MAX && window.ekey == INT64_MIN) {
    window = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3194
    assert(totalNumOfTable == 0 && taosArrayGetSize(groupList->pGroupList) == numOfGroups);
H
Haojun Liao 已提交
3195 3196
  }

dengyihao's avatar
dengyihao 已提交
3197
  taosArrayRemoveBatch(groupList->pGroupList, TARRAY_GET_START(emptyGroup), (int32_t)taosArrayGetSize(emptyGroup));
3198 3199
  taosArrayDestroy(emptyGroup);

H
Haojun Liao 已提交
3200
  groupList->numOfTables = totalNumOfTable;
H
Haojun Liao 已提交
3201
  return window;
H
hjxilinx 已提交
3202 3203
}

H
Haojun Liao 已提交
3204
void tsdbRetrieveDataBlockInfo(tsdbReaderT* pTsdbReadHandle, SDataBlockInfo* pDataBlockInfo) {
3205
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
dengyihao's avatar
dengyihao 已提交
3206
  SQueryFilePos*   cur = &pHandle->cur;
3207 3208

  uint64_t uid = 0;
H
Haojun Liao 已提交
3209

3210
  // there are data in file
D
dapan1121 已提交
3211
  if (pHandle->cur.fid != INT32_MIN) {
3212
    STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[cur->slot];
3213
    uid = pBlockInfo->pTableCheckInfo->tableId;
H
[td-32]  
hjxilinx 已提交
3214
  } else {
3215
    STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
3216
    uid = pCheckInfo->tableId;
3217
  }
3218

dengyihao's avatar
dengyihao 已提交
3219 3220
  tsdbDebug("data block generated, uid:%" PRIu64 " numOfRows:%d, tsrange:%" PRId64 " - %" PRId64 " %s", uid, cur->rows,
            cur->win.skey, cur->win.ekey, pHandle->idStr);
3221

dengyihao's avatar
dengyihao 已提交
3222 3223 3224
  //  pDataBlockInfo->uid    = uid; // block Id may be over write by assigning uid fro this data block. Do NOT assign
  //  the table uid
  pDataBlockInfo->rows = cur->rows;
H
Haojun Liao 已提交
3225
  pDataBlockInfo->window = cur->win;
S
TD-1057  
Shengliang Guan 已提交
3226
  pDataBlockInfo->numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pHandle));
3227
}
H
hjxilinx 已提交
3228

H
Haojun Liao 已提交
3229 3230 3231
/*
 * return null for mixed data block, if not a complete file data block, the statistics value will always return NULL
 */
3232
int32_t tsdbRetrieveDataBlockStatisInfo(tsdbReaderT* pTsdbReadHandle, SColumnDataAgg** pBlockStatis) {
dengyihao's avatar
dengyihao 已提交
3233
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
H
Haojun Liao 已提交
3234

H
Haojun Liao 已提交
3235 3236
  SQueryFilePos* c = &pHandle->cur;
  if (c->mixBlock) {
H
Haojun Liao 已提交
3237 3238 3239
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3240

H
Haojun Liao 已提交
3241 3242 3243 3244
  STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[c->slot];
  assert((c->slot >= 0 && c->slot < pHandle->numOfBlocks) || ((c->slot == pHandle->numOfBlocks) && (c->slot == 0)));

  // file block with sub-blocks has no statistics data
H
Haojun Liao 已提交
3245 3246 3247 3248
  if (pBlockInfo->compBlock->numOfSubBlocks > 1) {
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3249 3250

  int64_t stime = taosGetTimestampUs();
3251 3252
  int     statisStatus = tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock);
  if (statisStatus < TSDB_STATIS_OK) {
H
Hongze Cheng 已提交
3253
    return terrno;
3254 3255 3256
  } else if (statisStatus > TSDB_STATIS_OK) {
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
H
Hongze Cheng 已提交
3257
  }
H
Haojun Liao 已提交
3258

H
Haojun Liao 已提交
3259 3260
  int16_t* colIds = pHandle->defaultLoadColumn->pData;

H
Haojun Liao 已提交
3261
  size_t numOfCols = QH_GET_NUM_OF_COLS(pHandle);
3262
  memset(pHandle->statis, 0, numOfCols * sizeof(SColumnDataAgg));
dengyihao's avatar
dengyihao 已提交
3263
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
3264
    pHandle->statis[i].colId = colIds[i];
3265
  }
H
Haojun Liao 已提交
3266

3267
  tsdbGetBlockStatis(&pHandle->rhelper, pHandle->statis, (int)numOfCols, pBlockInfo->compBlock);
H
Haojun Liao 已提交
3268 3269

  // always load the first primary timestamp column data
3270
  SColumnDataAgg* pPrimaryColStatis = &pHandle->statis[0];
3271
  assert(pPrimaryColStatis->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
H
Haojun Liao 已提交
3272 3273 3274 3275 3276

  pPrimaryColStatis->numOfNull = 0;
  pPrimaryColStatis->min = pBlockInfo->compBlock->keyFirst;
  pPrimaryColStatis->max = pBlockInfo->compBlock->keyLast;

dengyihao's avatar
dengyihao 已提交
3277 3278 3279
  // update the number of NULL data rows
  for (int32_t i = 1; i < numOfCols; ++i) {
    if (pHandle->statis[i].numOfNull == -1) {  // set the column data are all NULL
H
Haojun Liao 已提交
3280 3281 3282
      pHandle->statis[i].numOfNull = pBlockInfo->compBlock->numOfRows;
    }
  }
H
Haojun Liao 已提交
3283 3284 3285 3286

  int64_t elapsed = taosGetTimestampUs() - stime;
  pHandle->cost.statisInfoLoadTime += elapsed;

H
Haojun Liao 已提交
3287
  *pBlockStatis = pHandle->statis;
3288
  return TSDB_CODE_SUCCESS;
H
hjxilinx 已提交
3289 3290
}

H
Haojun Liao 已提交
3291
SArray* tsdbRetrieveDataBlock(tsdbReaderT* pTsdbReadHandle, SArray* pIdList) {
H
[td-32]  
hjxilinx 已提交
3292
  /**
H
hjxilinx 已提交
3293
   * In the following two cases, the data has been loaded to SColumnInfoData.
H
[td-32]  
hjxilinx 已提交
3294 3295
   * 1. data is from cache, 2. data block is not completed qualified to query time range
   */
3296
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
D
dapan1121 已提交
3297
  if (pHandle->cur.fid == INT32_MIN) {
H
[td-32]  
hjxilinx 已提交
3298 3299
    return pHandle->pColumns;
  } else {
H
Haojun Liao 已提交
3300 3301
    STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[pHandle->cur.slot];
    STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
3302

3303
    if (pHandle->cur.mixBlock) {
H
[td-32]  
hjxilinx 已提交
3304 3305
      return pHandle->pColumns;
    } else {
H
Haojun Liao 已提交
3306
      SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlockInfo->compBlock);
3307
      assert(pHandle->realNumOfRows <= binfo.rows);
H
Haojun Liao 已提交
3308

H
hjxilinx 已提交
3309 3310
      // data block has been loaded, todo extract method
      SDataBlockLoadInfo* pBlockLoadInfo = &pHandle->dataBlockLoadInfo;
H
Haojun Liao 已提交
3311

H
Hongze Cheng 已提交
3312
      if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fid == pHandle->cur.fid &&
H
Haojun Liao 已提交
3313
          pBlockLoadInfo->uid == pCheckInfo->tableId) {
H
hjxilinx 已提交
3314
        return pHandle->pColumns;
H
Haojun Liao 已提交
3315
      } else {  // only load the file block
H
refact  
Hongze Cheng 已提交
3316
        SBlock* pBlock = pBlockInfo->compBlock;
H
Haojun Liao 已提交
3317
        if (doLoadFileDataBlock(pHandle, pBlock, pCheckInfo, pHandle->cur.slot) != TSDB_CODE_SUCCESS) {
3318 3319
          return NULL;
        }
H
Haojun Liao 已提交
3320

H
Haojun Liao 已提交
3321
        // todo refactor
H
Haojun Liao 已提交
3322
        int32_t numOfRows = doCopyRowsFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfRows - 1);
H
Haojun Liao 已提交
3323

H
Haojun Liao 已提交
3324
        // if the buffer is not full in case of descending order query, move the data in the front of the buffer
3325
        if (!ASCENDING_TRAVERSE(pHandle->order) && numOfRows < pHandle->outputCapacity) {
H
Haojun Liao 已提交
3326
          int32_t emptySize = pHandle->outputCapacity - numOfRows;
S
TD-1057  
Shengliang Guan 已提交
3327
          int32_t reqNumOfCols = (int32_t)taosArrayGetSize(pHandle->pColumns);
H
Haojun Liao 已提交
3328

dengyihao's avatar
dengyihao 已提交
3329
          for (int32_t i = 0; i < reqNumOfCols; ++i) {
H
Haojun Liao 已提交
3330
            SColumnInfoData* pColInfo = taosArrayGet(pHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
3331 3332
            memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes,
                    numOfRows * pColInfo->info.bytes);
H
Haojun Liao 已提交
3333 3334
          }
        }
H
Haojun Liao 已提交
3335

H
hjxilinx 已提交
3336 3337
        return pHandle->pColumns;
      }
H
[td-32]  
hjxilinx 已提交
3338 3339
    }
  }
H
hjxilinx 已提交
3340
}
3341
#if 0
3342
void filterPrepare(void* expr, void* param) {
3343
  tExprNode* pExpr = (tExprNode*)expr;
H
[td-32]  
hjxilinx 已提交
3344
  if (pExpr->_node.info != NULL) {
3345 3346
    return;
  }
3347

wafwerar's avatar
wafwerar 已提交
3348
  pExpr->_node.info = taosMemoryCalloc(1, sizeof(tQueryInfo));
H
Haojun Liao 已提交
3349

3350
  STSchema*   pTSSchema = (STSchema*) param;
H
hjxilinx 已提交
3351 3352 3353
  tQueryInfo* pInfo = pExpr->_node.info;
  tVariant*   pCond = pExpr->_node.pRight->pVal;
  SSchema*    pSchema = pExpr->_node.pLeft->pSchema;
3354

3355 3356
  pInfo->sch      = *pSchema;
  pInfo->optr     = pExpr->_node.optr;
Y
yihaoDeng 已提交
3357
  pInfo->compare  = getComparFunc(pInfo->sch.type, pInfo->optr);
H
Haojun Liao 已提交
3358
  pInfo->indexed  = pTSSchema->columns->colId == pInfo->sch.colId;
H
Haojun Liao 已提交
3359

H
hjxilinx 已提交
3360
  if (pInfo->optr == TSDB_RELATION_IN) {
Y
yihaoDeng 已提交
3361
     int dummy = -1;
3362
     SHashObj *pObj = NULL;
Y
yihaoDeng 已提交
3363 3364 3365 3366
     if (pInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) {
        pObj = taosHashInit(256, taosGetDefaultHashFunction(pInfo->sch.type), true, false);
        SArray *arr = (SArray *)(pCond->arr);
        for (size_t i = 0; i < taosArrayGetSize(arr); i++) {
Y
yihaoDeng 已提交
3367
          char* p = taosArrayGetP(arr, i);
3368 3369
          strntolower_s(varDataVal(p), varDataVal(p), varDataLen(p));
          taosHashPut(pObj, varDataVal(p), varDataLen(p), &dummy, sizeof(dummy));
Y
yihaoDeng 已提交
3370 3371 3372 3373
        }
     } else {
       buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen);
     }
3374
     pInfo->q = (char *)pObj;
H
Haojun Liao 已提交
3375
  } else if (pCond != NULL) {
3376 3377 3378 3379
    uint32_t size = pCond->nLen * TSDB_NCHAR_SIZE;
    if (size < (uint32_t)pSchema->bytes) {
      size = pSchema->bytes;
    }
wafwerar's avatar
wafwerar 已提交
3380
    // to make sure tonchar does not cause invalid write, since the '\0' needs at least sizeof(TdUcs4) space.
wafwerar's avatar
wafwerar 已提交
3381
    pInfo->q = taosMemoryCalloc(1, size + TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE);
3382
    tVariantDump(pCond, pInfo->q, pSchema->type, true);
weixin_48148422's avatar
weixin_48148422 已提交
3383
  }
3384 3385
}

3386
#endif
3387

dengyihao's avatar
dengyihao 已提交
3388
static int32_t tableGroupComparFn(const void* p1, const void* p2, const void* param) {
3389
#if 0
3390
  STableGroupSupporter* pTableGroupSupp = (STableGroupSupporter*) param;
3391 3392
  STable* pTable1 = ((STableKeyInfo*) p1)->uid;
  STable* pTable2 = ((STableKeyInfo*) p2)->uid;
H
Haojun Liao 已提交
3393

3394 3395 3396
  for (int32_t i = 0; i < pTableGroupSupp->numOfCols; ++i) {
    SColIndex* pColIndex = &pTableGroupSupp->pCols[i];
    int32_t colIndex = pColIndex->colIndex;
H
Haojun Liao 已提交
3397

H
Haojun Liao 已提交
3398
    assert(colIndex >= TSDB_TBNAME_COLUMN_INDEX);
H
Haojun Liao 已提交
3399

3400 3401 3402 3403
    char *  f1 = NULL;
    char *  f2 = NULL;
    int32_t type = 0;
    int32_t bytes = 0;
H
Haojun Liao 已提交
3404

H
Haojun Liao 已提交
3405 3406 3407
    if (colIndex == TSDB_TBNAME_COLUMN_INDEX) {
      f1 = (char*) TABLE_NAME(pTable1);
      f2 = (char*) TABLE_NAME(pTable2);
3408
      type = TSDB_DATA_TYPE_BINARY;
3409
      bytes = tGetTbnameColumnSchema()->bytes;
3410
    } else {
Y
yihaoDeng 已提交
3411 3412 3413 3414 3415 3416 3417
      if (pTableGroupSupp->pTagSchema && colIndex < pTableGroupSupp->pTagSchema->numOfCols) {
        STColumn* pCol = schemaColAt(pTableGroupSupp->pTagSchema, colIndex);
        bytes = pCol->bytes;
        type = pCol->type;
        f1 = tdGetKVRowValOfCol(pTable1->tagVal, pCol->colId);
        f2 = tdGetKVRowValOfCol(pTable2->tagVal, pCol->colId);
      } 
3418
    }
H
Haojun Liao 已提交
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432

    // this tags value may be NULL
    if (f1 == NULL && f2 == NULL) {
      continue;
    }

    if (f1 == NULL) {
      return -1;
    }

    if (f2 == NULL) {
      return 1;
    }

3433 3434 3435 3436 3437 3438 3439
    int32_t ret = doCompare(f1, f2, type, bytes);
    if (ret == 0) {
      continue;
    } else {
      return ret;
    }
  }
3440
#endif
3441 3442 3443
  return 0;
}

H
Haojun Liao 已提交
3444
static int tsdbCheckInfoCompar(const void* key1, const void* key2) {
3445
  if (((STableCheckInfo*)key1)->tableId < ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3446
    return -1;
3447
  } else if (((STableCheckInfo*)key1)->tableId > ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3448 3449 3450 3451 3452 3453 3454 3455 3456
    return 1;
  } else {
    ASSERT(false);
    return 0;
  }
}

void createTableGroupImpl(SArray* pGroups, SArray* pTableList, size_t numOfTables, TSKEY skey,
                          STableGroupSupporter* pSupp, __ext_compar_fn_t compareFn) {
3457
  STable* pTable = taosArrayGetP(pTableList, 0);
H
Haojun Liao 已提交
3458 3459
  SArray* g = taosArrayInit(16, sizeof(STableKeyInfo));

3460
  STableKeyInfo info = {.lastKey = skey};
H
Haojun Liao 已提交
3461
  taosArrayPush(g, &info);
3462

3463
  for (int32_t i = 1; i < numOfTables; ++i) {
3464 3465
    STable** prev = taosArrayGet(pTableList, i - 1);
    STable** p = taosArrayGet(pTableList, i);
H
Haojun Liao 已提交
3466

H
hjxilinx 已提交
3467
    int32_t ret = compareFn(prev, p, pSupp);
3468
    assert(ret == 0 || ret == -1);
H
Haojun Liao 已提交
3469

3470
    if (ret == 0) {
3471
      STableKeyInfo info1 = {.lastKey = skey};
H
Haojun Liao 已提交
3472
      taosArrayPush(g, &info1);
3473 3474
    } else {
      taosArrayPush(pGroups, &g);  // current group is ended, start a new group
H
Haojun Liao 已提交
3475 3476
      g = taosArrayInit(16, sizeof(STableKeyInfo));

3477
      STableKeyInfo info1 = {.lastKey = skey};
H
Haojun Liao 已提交
3478
      taosArrayPush(g, &info1);
3479 3480
    }
  }
H
Haojun Liao 已提交
3481

3482
  taosArrayPush(pGroups, &g);
3483 3484
}

dengyihao's avatar
dengyihao 已提交
3485 3486
SArray* createTableGroup(SArray* pTableList, SSchemaWrapper* pTagSchema, SColIndex* pCols, int32_t numOfOrderCols,
                         TSKEY skey) {
3487
  assert(pTableList != NULL);
3488
  SArray* pTableGroup = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3489

3490 3491
  size_t size = taosArrayGetSize(pTableList);
  if (size == 0) {
S
Shengliang Guan 已提交
3492
    tsdbDebug("no qualified tables");
3493 3494
    return pTableGroup;
  }
H
Haojun Liao 已提交
3495

dengyihao's avatar
dengyihao 已提交
3496
  if (numOfOrderCols == 0 || size == 1) {  // no group by tags clause or only one table
3497
    SArray* sa = taosArrayDup(pTableList);
H
Haojun Liao 已提交
3498 3499 3500 3501
    if (sa == NULL) {
      taosArrayDestroy(pTableGroup);
      return NULL;
    }
H
Haojun Liao 已提交
3502

3503
    taosArrayPush(pTableGroup, &sa);
S
TD-1057  
Shengliang Guan 已提交
3504
    tsdbDebug("all %" PRIzu " tables belong to one group", size);
3505
  } else {
H
Haojun Liao 已提交
3506 3507
    STableGroupSupporter sup = {0};
    sup.numOfCols = numOfOrderCols;
3508
    sup.pTagSchema = pTagSchema->pSchema;
H
Haojun Liao 已提交
3509 3510
    sup.pCols = pCols;

3511 3512
    taosqsort(pTableList->pData, size, sizeof(STableKeyInfo), &sup, tableGroupComparFn);
    createTableGroupImpl(pTableGroup, pTableList, size, skey, &sup, tableGroupComparFn);
3513
  }
H
Haojun Liao 已提交
3514

3515 3516 3517
  return pTableGroup;
}

dengyihao's avatar
dengyihao 已提交
3518
// static bool tableFilterFp(const void* pNode, void* param) {
3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601
//  tQueryInfo* pInfo = (tQueryInfo*) param;
//
//  STable* pTable = (STable*)(SL_GET_NODE_DATA((SSkipListNode*)pNode));
//
//  char* val = NULL;
//  if (pInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) {
//    val = (char*) TABLE_NAME(pTable);
//  } else {
//    val = tdGetKVRowValOfCol(pTable->tagVal, pInfo->sch.colId);
//  }
//
//  if (pInfo->optr == TSDB_RELATION_ISNULL || pInfo->optr == TSDB_RELATION_NOTNULL) {
//    if (pInfo->optr == TSDB_RELATION_ISNULL) {
//      return (val == NULL) || isNull(val, pInfo->sch.type);
//    } else if (pInfo->optr == TSDB_RELATION_NOTNULL) {
//      return (val != NULL) && (!isNull(val, pInfo->sch.type));
//    }
//  } else if (pInfo->optr == TSDB_RELATION_IN) {
//     int type = pInfo->sch.type;
//     if (type == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_TIMESTAMP) {
//       int64_t v;
//       GET_TYPED_DATA(v, int64_t, pInfo->sch.type, val);
//       return NULL != taosHashGet((SHashObj *)pInfo->q, (char *)&v, sizeof(v));
//     } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
//       uint64_t v;
//       GET_TYPED_DATA(v, uint64_t, pInfo->sch.type, val);
//       return NULL != taosHashGet((SHashObj *)pInfo->q, (char *)&v, sizeof(v));
//     }
//     else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
//       double v;
//       GET_TYPED_DATA(v, double, pInfo->sch.type, val);
//       return NULL != taosHashGet((SHashObj *)pInfo->q, (char *)&v, sizeof(v));
//     } else if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR){
//       return NULL != taosHashGet((SHashObj *)pInfo->q, varDataVal(val), varDataLen(val));
//     }
//
//  }
//
//  int32_t ret = 0;
//  if (val == NULL) { //the val is possible to be null, so check it out carefully
//    ret = -1; // val is missing in table tags value pairs
//  } else {
//    ret = pInfo->compare(val, pInfo->q);
//  }
//
//  switch (pInfo->optr) {
//    case TSDB_RELATION_EQUAL: {
//      return ret == 0;
//    }
//    case TSDB_RELATION_NOT_EQUAL: {
//      return ret != 0;
//    }
//    case TSDB_RELATION_GREATER_EQUAL: {
//      return ret >= 0;
//    }
//    case TSDB_RELATION_GREATER: {
//      return ret > 0;
//    }
//    case TSDB_RELATION_LESS_EQUAL: {
//      return ret <= 0;
//    }
//    case TSDB_RELATION_LESS: {
//      return ret < 0;
//    }
//    case TSDB_RELATION_LIKE: {
//      return ret == 0;
//    }
//    case TSDB_RELATION_MATCH: {
//      return ret == 0;
//    }
//    case TSDB_RELATION_NMATCH: {
//      return ret == 0;
//    }
//    case TSDB_RELATION_IN: {
//      return ret == 1;
//    }
//
//    default:
//      assert(false);
//  }
//
//  return true;
//}
H
Haojun Liao 已提交
3602

dengyihao's avatar
dengyihao 已提交
3603 3604
// static void getTableListfromSkipList(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, SExprTraverseSupp
// *param);
3605

dengyihao's avatar
dengyihao 已提交
3606 3607
// static int32_t doQueryTableList(STable* pSTable, SArray* pRes, tExprNode* pExpr) {
//  //  // query according to the expression tree
3608
//  SExprTraverseSupp supp = {
dengyihao's avatar
dengyihao 已提交
3609
//      .nodeFilterFn = (__result_filter_fn_t)tableFilterFp,
3610 3611
//      .setupInfoFn = filterPrepare,
//      .pExtInfo = pSTable->tagSchema,
dengyihao's avatar
dengyihao 已提交
3612
//  };
3613 3614 3615 3616 3617
//
//  getTableListfromSkipList(pExpr, pSTable->pIndex, pRes, &supp);
//  tExprTreeDestroy(pExpr, destroyHelper);
//  return TSDB_CODE_SUCCESS;
//}
3618

H
Haojun Liao 已提交
3619
int32_t tsdbQuerySTableByTagCond(void* pMeta, uint64_t uid, TSKEY skey, const char* pTagCond, size_t len,
3620
                                 int16_t tagNameRelType, const char* tbnameCond, STableGroupInfo* pGroupInfo,
3621
                                 SColIndex* pColIndex, int32_t numOfCols, uint64_t reqId, uint64_t taskId) {
H
Haojun Liao 已提交
3622
  STbCfg* pTbCfg = metaGetTbInfoByUid(pMeta, uid);
3623
  if (pTbCfg == NULL) {
dengyihao's avatar
dengyihao 已提交
3624
    tsdbError("%p failed to get stable, uid:%" PRIu64 ", TID:0x%" PRIx64 " QID:0x%" PRIx64, pMeta, uid, taskId, reqId);
3625 3626
    terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
    goto _error;
3627
  }
H
Haojun Liao 已提交
3628

3629
  if (pTbCfg->type != META_SUPER_TABLE) {
dengyihao's avatar
dengyihao 已提交
3630 3631 3632
    tsdbError("%p query normal tag not allowed, uid:%" PRIu64 ", TID:0x%" PRIx64 " QID:0x%" PRIx64, pMeta, uid, taskId,
              reqId);
    terrno = TSDB_CODE_OPS_NOT_SUPPORT;  // basically, this error is caused by invalid sql issued by client
3633
    goto _error;
H
hjxilinx 已提交
3634
  }
3635

dengyihao's avatar
dengyihao 已提交
3636 3637
  // NOTE: not add ref count for super table
  SArray*         res = taosArrayInit(8, sizeof(STableKeyInfo));
H
Haojun Liao 已提交
3638
  SSchemaWrapper* pTagSchema = metaGetTableSchema(pMeta, uid, 0, true);
H
Haojun Liao 已提交
3639

weixin_48148422's avatar
weixin_48148422 已提交
3640 3641
  // no tags and tbname condition, all child tables of this stable are involved
  if (tbnameCond == NULL && (pTagCond == NULL || len == 0)) {
H
Haojun Liao 已提交
3642
    int32_t ret = getAllTableList(pMeta, uid, res);
3643 3644
    if (ret != TSDB_CODE_SUCCESS) {
      goto _error;
3645
    }
3646

dengyihao's avatar
dengyihao 已提交
3647 3648
    pGroupInfo->numOfTables = (uint32_t)taosArrayGetSize(res);
    pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols, skey);
H
Haojun Liao 已提交
3649

dengyihao's avatar
dengyihao 已提交
3650 3651 3652
    tsdbDebug("%p no table name/tag condition, all tables qualified, numOfTables:%u, group:%zu, TID:0x%" PRIx64
              " QID:0x%" PRIx64,
              pMeta, pGroupInfo->numOfTables, taosArrayGetSize(pGroupInfo->pGroupList), taskId, reqId);
3653

3654
    taosArrayDestroy(res);
3655 3656
    return ret;
  }
3657

H
hjxilinx 已提交
3658
  int32_t ret = TSDB_CODE_SUCCESS;
3659

dengyihao's avatar
dengyihao 已提交
3660 3661
  SFilterInfo* filterInfo = NULL;
  ret = filterInitFromNode((SNode*)pTagCond, &filterInfo, 0);
dengyihao's avatar
dengyihao 已提交
3662 3663 3664 3665 3666 3667 3668 3669
  if (ret != TSDB_CODE_SUCCESS) {
    terrno = ret;
    return ret;
  }
  ret = tsdbQueryTableList(pMeta, res, filterInfo);
  pGroupInfo->numOfTables = (uint32_t)taosArrayGetSize(res);
  pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols, skey);

dengyihao's avatar
dengyihao 已提交
3670 3671
  // tsdbDebug("%p stable tid:%d, uid:%" PRIu64 " query, numOfTables:%u, belong to %" PRIzu " groups", tsdb,
  //          pTable->tableId, pTable->uid, pGroupInfo->numOfTables, taosArrayGetSize(pGroupInfo->pGroupList));
dengyihao's avatar
dengyihao 已提交
3672 3673 3674 3675 3676

  taosArrayDestroy(res);
  return ret;

_error:
3677
  return terrno;
3678
}
3679

dengyihao's avatar
dengyihao 已提交
3680 3681 3682 3683 3684
int32_t tsdbQueryTableList(void* pMeta, SArray* pRes, void* filterInfo) {
  // impl later

  return TSDB_CODE_SUCCESS;
}
H
Haojun Liao 已提交
3685 3686
int32_t tsdbGetOneTableGroup(void* pMeta, uint64_t uid, TSKEY startKey, STableGroupInfo* pGroupInfo) {
  STbCfg* pTbCfg = metaGetTbInfoByUid(pMeta, uid);
3687
  if (pTbCfg == NULL) {
3688 3689
    terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
    goto _error;
3690
  }
3691

3692 3693
  pGroupInfo->numOfTables = 1;
  pGroupInfo->pGroupList = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3694

H
Haojun Liao 已提交
3695 3696
  SArray* group = taosArrayInit(1, sizeof(STableKeyInfo));

3697
  STableKeyInfo info = {.lastKey = startKey, .uid = uid};
H
Haojun Liao 已提交
3698
  taosArrayPush(group, &info);
H
Haojun Liao 已提交
3699

3700
  taosArrayPush(pGroupInfo->pGroupList, &group);
3701
  return TSDB_CODE_SUCCESS;
3702

dengyihao's avatar
dengyihao 已提交
3703
_error:
3704
  return terrno;
3705
}
3706

3707
#if 0
3708
int32_t tsdbGetTableGroupFromIdList(STsdb* tsdb, SArray* pTableIdList, STableGroupInfo* pGroupInfo) {
B
Bomin Zhang 已提交
3709 3710 3711
  if (tsdbRLockRepoMeta(tsdb) < 0) {
    return terrno;
  }
3712 3713 3714 3715

  assert(pTableIdList != NULL);
  size_t size = taosArrayGetSize(pTableIdList);
  pGroupInfo->pGroupList = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3716
  SArray* group = taosArrayInit(1, sizeof(STableKeyInfo));
3717

B
Bomin Zhang 已提交
3718
  for(int32_t i = 0; i < size; ++i) {
3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729
    STableIdInfo *id = taosArrayGet(pTableIdList, i);

    STable* pTable = tsdbGetTableByUid(tsdbGetMeta(tsdb), id->uid);
    if (pTable == NULL) {
      tsdbWarn("table uid:%"PRIu64", tid:%d has been drop already", id->uid, id->tid);
      continue;
    }

    if (pTable->type == TSDB_SUPER_TABLE) {
      tsdbError("direct query on super tale is not allowed, table uid:%"PRIu64", tid:%d", id->uid, id->tid);
      terrno = TSDB_CODE_QRY_INVALID_MSG;
D
fix bug  
dapan1121 已提交
3730 3731 3732
      tsdbUnlockRepoMeta(tsdb);
      taosArrayDestroy(group);
      return terrno;
3733 3734
    }

H
Haojun Liao 已提交
3735 3736
    STableKeyInfo info = {.pTable = pTable, .lastKey = id->key};
    taosArrayPush(group, &info);
3737 3738
  }

B
Bomin Zhang 已提交
3739 3740 3741 3742
  if (tsdbUnlockRepoMeta(tsdb) < 0) {
    taosArrayDestroy(group);
    return terrno;
  }
3743

sangshuduo's avatar
sangshuduo 已提交
3744
  pGroupInfo->numOfTables = (uint32_t) taosArrayGetSize(group);
B
Bomin Zhang 已提交
3745 3746 3747 3748 3749
  if (pGroupInfo->numOfTables > 0) {
    taosArrayPush(pGroupInfo->pGroupList, &group);
  } else {
    taosArrayDestroy(group);
  }
3750 3751 3752

  return TSDB_CODE_SUCCESS;
}
3753
#endif
3754 3755 3756 3757 3758 3759 3760 3761
static void* doFreeColumnInfoData(SArray* pColumnInfoData) {
  if (pColumnInfoData == NULL) {
    return NULL;
  }

  size_t cols = taosArrayGetSize(pColumnInfoData);
  for (int32_t i = 0; i < cols; ++i) {
    SColumnInfoData* pColInfo = taosArrayGet(pColumnInfoData, i);
wafwerar's avatar
wafwerar 已提交
3762
    taosMemoryFreeClear(pColInfo->pData);
3763 3764 3765 3766 3767 3768
  }

  taosArrayDestroy(pColumnInfoData);
  return NULL;
}

H
Haojun Liao 已提交
3769 3770 3771 3772 3773 3774
static void* destroyTableCheckInfo(SArray* pTableCheckInfo) {
  size_t size = taosArrayGetSize(pTableCheckInfo);
  for (int32_t i = 0; i < size; ++i) {
    STableCheckInfo* p = taosArrayGet(pTableCheckInfo, i);
    destroyTableMemIterator(p);

wafwerar's avatar
wafwerar 已提交
3775
    taosMemoryFreeClear(p->pCompInfo);
H
Haojun Liao 已提交
3776 3777 3778 3779 3780 3781
  }

  taosArrayDestroy(pTableCheckInfo);
  return NULL;
}

H
Haojun Liao 已提交
3782
void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
3783 3784
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
  if (pTsdbReadHandle == NULL) {
3785 3786
    return;
  }
3787

3788
  pTsdbReadHandle->pColumns = doFreeColumnInfoData(pTsdbReadHandle->pColumns);
3789

3790
  taosArrayDestroy(pTsdbReadHandle->defaultLoadColumn);
wafwerar's avatar
wafwerar 已提交
3791 3792
  taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
  taosMemoryFreeClear(pTsdbReadHandle->statis);
3793

3794
  if (!emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
3795
    //    tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
3796
  } else {
3797
    assert(pTsdbReadHandle->pTableCheckInfo == NULL);
3798 3799
  }

3800 3801
  if (pTsdbReadHandle->pTableCheckInfo != NULL) {
    pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
3802
  }
3803

3804
  tsdbDestroyReadH(&pTsdbReadHandle->rhelper);
H
Haojun Liao 已提交
3805

3806 3807
  tdFreeDataCols(pTsdbReadHandle->pDataCols);
  pTsdbReadHandle->pDataCols = NULL;
H
Haojun Liao 已提交
3808

3809 3810
  pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
  pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
3811

3812
  SIOCostSummary* pCost = &pTsdbReadHandle->cost;
3813

dengyihao's avatar
dengyihao 已提交
3814 3815 3816 3817
  tsdbDebug("%p :io-cost summary: head-file read cnt:%" PRIu64 ", head-file time:%" PRIu64 " us, statis-info:%" PRId64
            " us, datablock:%" PRId64 " us, check data:%" PRId64 " us, %s",
            pTsdbReadHandle, pCost->headFileLoad, pCost->headFileLoadTime, pCost->statisInfoLoadTime,
            pCost->blockLoadTime, pCost->checkForNextTime, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
3818

wafwerar's avatar
wafwerar 已提交
3819
  taosMemoryFreeClear(pTsdbReadHandle);
3820
}
3821

3822
#if 0
H
Haojun Liao 已提交
3823
void tsdbDestroyTableGroup(STableGroupInfo *pGroupList) {
3824 3825 3826 3827 3828 3829 3830 3831 3832 3833
  assert(pGroupList != NULL);

  size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);

  for(int32_t i = 0; i < numOfGroup; ++i) {
    SArray* p = taosArrayGetP(pGroupList->pGroupList, i);

    size_t numOfTables = taosArrayGetSize(p);
    for(int32_t j = 0; j < numOfTables; ++j) {
      STable* pTable = taosArrayGetP(p, j);
3834 3835 3836 3837
      if (pTable != NULL) { // in case of handling retrieve data from tsdb
        tsdbUnRefTable(pTable);
      }
      //assert(pTable != NULL);
3838 3839 3840 3841 3842
    }

    taosArrayDestroy(p);
  }

3843
  taosHashCleanup(pGroupList->map);
3844
  taosArrayDestroy(pGroupList->pGroupList);
H
Haojun Liao 已提交
3845
  pGroupList->numOfTables = 0;
3846
}
H
Haojun Liao 已提交
3847 3848 3849 3850 3851 3852 3853

static void applyFilterToSkipListNode(SSkipList *pSkipList, tExprNode *pExpr, SArray *pResult, SExprTraverseSupp *param) {
  SSkipListIterator* iter = tSkipListCreateIter(pSkipList);

  // Scan each node in the skiplist by using iterator
  while (tSkipListIterNext(iter)) {
    SSkipListNode *pNode = tSkipListIterGet(iter);
H
Haojun Liao 已提交
3854
    if (exprTreeApplyFilter(pExpr, pNode, param)) {
H
Haojun Liao 已提交
3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877
      taosArrayPush(pResult, &(SL_GET_NODE_DATA(pNode)));
    }
  }

  tSkipListDestroyIter(iter);
}

typedef struct {
  char*    v;
  int32_t  optr;
} SEndPoint;

typedef struct {
  SEndPoint* start;
  SEndPoint* end;
} SQueryCond;

// todo check for malloc failure
static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
  int32_t optr = queryColInfo->optr;

  if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL ||
      optr == TSDB_RELATION_EQUAL || optr == TSDB_RELATION_NOT_EQUAL) {
wafwerar's avatar
wafwerar 已提交
3878
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3879
    pCond->start->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3880
    pCond->start->v    = queryColInfo->q;
H
Haojun Liao 已提交
3881
  } else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
wafwerar's avatar
wafwerar 已提交
3882
    pCond->end       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3883
    pCond->end->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3884 3885
    pCond->end->v    = queryColInfo->q;
  } else if (optr == TSDB_RELATION_IN) {
wafwerar's avatar
wafwerar 已提交
3886
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
Y
yihaoDeng 已提交
3887 3888 3889
    pCond->start->optr = queryColInfo->optr;
    pCond->start->v    = queryColInfo->q; 
  } else if (optr == TSDB_RELATION_LIKE) {
H
Haojun Liao 已提交
3890
    assert(0);
3891 3892
  } else if (optr == TSDB_RELATION_MATCH) {
    assert(0);
3893 3894
  } else if (optr == TSDB_RELATION_NMATCH) {
    assert(0);
H
Haojun Liao 已提交
3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977
  }

  return TSDB_CODE_SUCCESS;
}

static void queryIndexedColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* result) {
  SSkipListIterator* iter = NULL;

  SQueryCond cond = {0};
  if (setQueryCond(pQueryInfo, &cond) != TSDB_CODE_SUCCESS) {
    //todo handle error
  }

  if (cond.start != NULL) {
    iter = tSkipListCreateIterFromVal(pSkipList, (char*) cond.start->v, pSkipList->type, TSDB_ORDER_ASC);
  } else {
    iter = tSkipListCreateIterFromVal(pSkipList, (char*)(cond.end ? cond.end->v: NULL), pSkipList->type, TSDB_ORDER_DESC);
  }

  if (cond.start != NULL) {
    int32_t optr = cond.start->optr;

    if (optr == TSDB_RELATION_EQUAL) {   // equals
      while(tSkipListIterNext(iter)) {
        SSkipListNode* pNode = tSkipListIterGet(iter);

        int32_t ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v);
        if (ret != 0) {
          break;
        }

        STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
        taosArrayPush(result, &info);
      }
    } else if (optr == TSDB_RELATION_GREATER || optr == TSDB_RELATION_GREATER_EQUAL) { // greater equal
      bool comp = true;
      int32_t ret = 0;

      while(tSkipListIterNext(iter)) {
        SSkipListNode* pNode = tSkipListIterGet(iter);

        if (comp) {
          ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v);
          assert(ret >= 0);
        }

        if (ret == 0 && optr == TSDB_RELATION_GREATER) {
          continue;
        } else {
          STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
          taosArrayPush(result, &info);
          comp = false;
        }
      }
    } else if (optr == TSDB_RELATION_NOT_EQUAL) {   // not equal
      bool comp = true;

      while(tSkipListIterNext(iter)) {
        SSkipListNode* pNode = tSkipListIterGet(iter);
        comp = comp && (pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v) == 0);
        if (comp) {
          continue;
        }

        STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
        taosArrayPush(result, &info);
      }

      tSkipListDestroyIter(iter);

      comp = true;
      iter = tSkipListCreateIterFromVal(pSkipList, (char*) cond.start->v, pSkipList->type, TSDB_ORDER_DESC);
      while(tSkipListIterNext(iter)) {
        SSkipListNode* pNode = tSkipListIterGet(iter);
        comp = comp && (pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v) == 0);
        if (comp) {
          continue;
        }

        STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
        taosArrayPush(result, &info);
      }

Y
yihaoDeng 已提交
3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990
    } else if (optr == TSDB_RELATION_IN) {
      while(tSkipListIterNext(iter)) {
        SSkipListNode* pNode = tSkipListIterGet(iter);

        int32_t ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.start->v);
        if (ret != 0) {
          break;
        }

        STableKeyInfo info = {.pTable = (void*)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
        taosArrayPush(result, &info);
      }
      
H
Haojun Liao 已提交
3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031
    } else {
      assert(0);
    }
  } else {
    int32_t optr = cond.end ? cond.end->optr : TSDB_RELATION_INVALID;
    if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
      bool    comp = true;
      int32_t ret = 0;

      while (tSkipListIterNext(iter)) {
        SSkipListNode *pNode = tSkipListIterGet(iter);

        if (comp) {
          ret = pQueryInfo->compare(SL_GET_NODE_KEY(pSkipList, pNode), cond.end->v);
          assert(ret <= 0);
        }

        if (ret == 0 && optr == TSDB_RELATION_LESS) {
          continue;
        } else {
          STableKeyInfo info = {.pTable = (void *)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
          taosArrayPush(result, &info);
          comp = false;  // no need to compare anymore
        }
      }
    } else {
      assert(pQueryInfo->optr == TSDB_RELATION_ISNULL || pQueryInfo->optr == TSDB_RELATION_NOTNULL);

      while (tSkipListIterNext(iter)) {
        SSkipListNode *pNode = tSkipListIterGet(iter);

        bool isnull = isNull(SL_GET_NODE_KEY(pSkipList, pNode), pQueryInfo->sch.type);
        if ((pQueryInfo->optr == TSDB_RELATION_ISNULL && isnull) ||
            (pQueryInfo->optr == TSDB_RELATION_NOTNULL && (!isnull))) {
          STableKeyInfo info = {.pTable = (void *)SL_GET_NODE_DATA(pNode), .lastKey = TSKEY_INITIAL_VAL};
          taosArrayPush(result, &info);
        }
      }
    }
  }

wafwerar's avatar
wafwerar 已提交
4032 4033
  taosMemoryFree(cond.start);
  taosMemoryFree(cond.end);
H
Haojun Liao 已提交
4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051
  tSkipListDestroyIter(iter);
}

static void queryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArray* res, __result_filter_fn_t filterFp) {
  SSkipListIterator* iter = tSkipListCreateIter(pSkipList);

  while (tSkipListIterNext(iter)) {
    bool addToResult = false;

    SSkipListNode *pNode = tSkipListIterGet(iter);

    char *pData = SL_GET_NODE_DATA(pNode);
    tstr *name = (tstr*) tsdbGetTableName((void*) pData);

    // todo speed up by using hash
    if (pQueryInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) {
      if (pQueryInfo->optr == TSDB_RELATION_IN) {
        addToResult = pQueryInfo->compare(name, pQueryInfo->q);
4052 4053 4054
      } else if (pQueryInfo->optr == TSDB_RELATION_LIKE ||
                 pQueryInfo->optr == TSDB_RELATION_MATCH ||
                 pQueryInfo->optr == TSDB_RELATION_NMATCH) {
H
Haojun Liao 已提交
4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070
        addToResult = !pQueryInfo->compare(name, pQueryInfo->q);
      }
    } else {
      addToResult = filterFp(pNode, pQueryInfo);
    }

    if (addToResult) {
      STableKeyInfo info = {.pTable = (void*)pData, .lastKey = TSKEY_INITIAL_VAL};
      taosArrayPush(res, &info);
    }
  }

  tSkipListDestroyIter(iter);
}

// Apply the filter expression to each node in the skiplist to acquire the qualified nodes in skip list
dengyihao's avatar
dengyihao 已提交
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103
//void getTableListfromSkipList(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, SExprTraverseSupp *param) {
//  if (pExpr == NULL) {
//    return;
//  }
//
//  tExprNode *pLeft  = pExpr->_node.pLeft;
//  tExprNode *pRight = pExpr->_node.pRight;
//
//  // column project
//  if (pLeft->nodeType != TSQL_NODE_EXPR && pRight->nodeType != TSQL_NODE_EXPR) {
//    assert(pLeft->nodeType == TSQL_NODE_COL && (pRight->nodeType == TSQL_NODE_VALUE || pRight->nodeType == TSQL_NODE_DUMMY));
//
//    param->setupInfoFn(pExpr, param->pExtInfo);
//
//    tQueryInfo *pQueryInfo = pExpr->_node.info;
//    if (pQueryInfo->indexed && (pQueryInfo->optr != TSDB_RELATION_LIKE
//                                && pQueryInfo->optr != TSDB_RELATION_MATCH && pQueryInfo->optr != TSDB_RELATION_NMATCH
//                                && pQueryInfo->optr != TSDB_RELATION_IN)) {
//      queryIndexedColumn(pSkipList, pQueryInfo, result);
//    } else {
//      queryIndexlessColumn(pSkipList, pQueryInfo, result, param->nodeFilterFn);
//    }
//
//    return;
//  }
//
//  // The value of hasPK is always 0.
//  uint8_t weight = pLeft->_node.hasPK + pRight->_node.hasPK;
//  assert(weight == 0 && pSkipList != NULL && taosArrayGetSize(result) == 0);
//
//  //apply the hierarchical filter expression to every node in skiplist to find the qualified nodes
//  applyFilterToSkipListNode(pSkipList, pExpr, result, param);
//}
L
Liu Jicong 已提交
4104
#endif