tsdbRead.c 140.7 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
        //        memmove(pData, (char*)src->pData + bytes * start, bytes * num);
1413 1414
        int32_t rowIndex = numOfRows;
        for (int32_t k = start; k <= end; ++k, ++rowIndex) {
1415
          SCellVal sVal = {0};
C
Cary Xu 已提交
1416
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
1417 1418
            TASSERT(0);
          }
1419

1420
          if (sVal.valType == TD_VTYPE_NULL) {
1421
            colDataAppendNULL(pColInfo, rowIndex);
1422
          } else {
1423
            colDataAppend(pColInfo, rowIndex, sVal.val, false);
1424 1425 1426
          }
        }
      } else {  // handle the var-string
1427 1428
        int32_t rowIndex = numOfRows;

1429
        // todo refactor, only copy one-by-one
1430
        for (int32_t k = start; k < num + start; ++k, ++rowIndex) {
1431
          SCellVal sVal = {0};
dengyihao's avatar
dengyihao 已提交
1432
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
H
Haojun Liao 已提交
1433 1434
            TASSERT(0);
          }
1435

1436
          if (sVal.valType == TD_VTYPE_NULL) {
1437
            colDataAppendNULL(pColInfo, rowIndex);
1438
          } else {
1439
            colDataAppend(pColInfo, rowIndex, sVal.val, false);
1440
          }
1441 1442
        }
      }
1443 1444 1445

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

dengyihao's avatar
dengyihao 已提交
1455
  while (i < requiredNumOfCols) {  // the remain columns are all null data
1456
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1457 1458 1459 1460
    int32_t rowIndex = numOfRows;

    for (int32_t k = start; k < num + start; ++k, ++rowIndex) {
      colDataAppend(pColInfo, rowIndex, NULL, true);  // TODO add a fast version to set a number of consecutive NULL value.
1461 1462
    }
    i++;
1463
  }
H
Haojun Liao 已提交
1464

1465 1466
  pTsdbReadHandle->cur.win.ekey = tsArray[end];
  pTsdbReadHandle->cur.lastKey = tsArray[end] + step;
1467

1468
  return numOfRows + num;
1469 1470
}

H
Haojun Liao 已提交
1471
// TODO fix bug for reverse copy data problem
1472
// Note: row1 always has high priority
H
Haojun Liao 已提交
1473 1474 1475 1476
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 已提交
1477 1478 1479 1480 1481 1482 1483 1484 1485
  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 已提交
1486
  SCellVal sVal = {0};
1487

H
Haojun Liao 已提交
1488
  // the schema version info is embeded in STSRow
1489 1490 1491
  int32_t numOfColsOfRow1 = 0;

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

dengyihao's avatar
dengyihao 已提交
1495
  if (isRow1DataRow) {
1496
    numOfColsOfRow1 = schemaNCols(pSchema1);
H
Haojun Liao 已提交
1497
  } else {
H
Haojun Liao 已提交
1498
    numOfColsOfRow1 = tdRowGetNCols(row1);
D
fix bug  
dapan1121 已提交
1499
  }
1500

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

1514
  int32_t i = 0, j = 0, k = 0;
dengyihao's avatar
dengyihao 已提交
1515
  while (i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) {
1516
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1517 1518

    int32_t colIdOfRow1;
dengyihao's avatar
dengyihao 已提交
1519
    if (j >= numOfColsOfRow1) {
1520
      colIdOfRow1 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1521
    } else if (isRow1DataRow) {
1522 1523
      colIdOfRow1 = pSchema1->columns[j].colId;
    } else {
dengyihao's avatar
dengyihao 已提交
1524
      SKvRowIdx* pColIdx = tdKvRowColIdxAt(row1, j);
1525 1526 1527 1528
      colIdOfRow1 = pColIdx->colId;
    }

    int32_t colIdOfRow2;
dengyihao's avatar
dengyihao 已提交
1529
    if (k >= numOfColsOfRow2) {
1530
      colIdOfRow2 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1531
    } else if (isRow2DataRow) {
1532 1533
      colIdOfRow2 = pSchema2->columns[k].colId;
    } else {
dengyihao's avatar
dengyihao 已提交
1534
      SKvRowIdx* pColIdx = tdKvRowColIdxAt(row2, k);
1535 1536 1537
      colIdOfRow2 = pColIdx->colId;
    }

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

    if (colId == pColInfo->info.colId) {
H
Haojun Liao 已提交
1586
      if (tdValTypeIsNorm(sVal.valType)) {
H
Haojun Liao 已提交
1587
        colDataAppend(pColInfo, numOfRows, sVal.val, false);
H
Haojun Liao 已提交
1588
      } else if (forceSetNull) {
H
Haojun Liao 已提交
1589
        colDataAppend(pColInfo, numOfRows, NULL, true);
1590
      }
H
Haojun Liao 已提交
1591

1592
      i++;
C
Cary Xu 已提交
1593

dengyihao's avatar
dengyihao 已提交
1594
      if (row == row1) {
C
Cary Xu 已提交
1595
        j++;
1596 1597 1598 1599
      } else {
        k++;
      }
    } else {
dengyihao's avatar
dengyihao 已提交
1600
      if (forceSetNull) {
H
Haojun Liao 已提交
1601
        colDataAppend(pColInfo, numOfRows, NULL, true);
C
Cary Xu 已提交
1602
      }
1603
      i++;
1604
    }
1605
  }
1606

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

1617 1618
static void moveDataToFront(STsdbReadHandle* pTsdbReadHandle, int32_t numOfRows, int32_t numOfCols) {
  if (numOfRows == 0 || ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1619 1620 1621 1622
    return;
  }

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

dengyihao's avatar
dengyihao 已提交
1633 1634
static void getQualifiedRowsPos(STsdbReadHandle* pTsdbReadHandle, int32_t startPos, int32_t endPos,
                                int32_t numOfExisted, int32_t* start, int32_t* end) {
1635 1636
  *start = -1;

1637
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1638
    int32_t remain = endPos - startPos + 1;
1639 1640
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = (pTsdbReadHandle->outputCapacity - numOfExisted) + startPos - 1;
H
Haojun Liao 已提交
1641 1642
    } else {
      *end = endPos;
1643 1644 1645 1646 1647
    }

    *start = startPos;
  } else {
    int32_t remain = (startPos - endPos) + 1;
1648 1649
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = startPos + 1 - (pTsdbReadHandle->outputCapacity - numOfExisted);
H
Haojun Liao 已提交
1650 1651
    } else {
      *end = endPos;
1652 1653 1654 1655 1656 1657 1658
    }

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

dengyihao's avatar
dengyihao 已提交
1659 1660
static void updateInfoAfterMerge(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, int32_t numOfRows,
                                 int32_t endPos) {
1661
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
1662 1663

  pCheckInfo->lastKey = cur->lastKey;
1664
  pTsdbReadHandle->realNumOfRows = numOfRows;
1665 1666 1667 1668
  cur->rows = numOfRows;
  cur->pos = endPos;
}

1669 1670
static void doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
1671 1672

  if (cur->rows > 0) {
1673 1674
    if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
      assert(cur->win.skey >= pTsdbReadHandle->window.skey && cur->win.ekey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1675
    } else {
1676
      assert(cur->win.skey >= pTsdbReadHandle->window.ekey && cur->win.ekey <= pTsdbReadHandle->window.skey);
H
Haojun Liao 已提交
1677 1678
    }

1679
    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, 0);
dengyihao's avatar
dengyihao 已提交
1680 1681
    assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] &&
           cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows - 1]);
H
Haojun Liao 已提交
1682
  } else {
1683
    cur->win = pTsdbReadHandle->window;
H
Haojun Liao 已提交
1684

dengyihao's avatar
dengyihao 已提交
1685
    int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1686
    cur->lastKey = pTsdbReadHandle->window.ekey + step;
H
Haojun Liao 已提交
1687 1688 1689
  }
}

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

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

dengyihao's avatar
dengyihao 已提交
1697
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1698
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
H
Haojun Liao 已提交
1699 1700 1701 1702 1703 1704

  int32_t pos = cur->pos;

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

1705
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1706
    TSWAP(start, end, int32_t);
H
Haojun Liao 已提交
1707 1708
  }

1709 1710
  assert(pTsdbReadHandle->outputCapacity >= (end - start + 1));
  int32_t numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, start, end);
H
Haojun Liao 已提交
1711 1712

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

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
1719
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
H
Haojun Liao 已提交
1720 1721 1722

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

dengyihao's avatar
dengyihao 已提交
1726 1727 1728
  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 已提交
1729 1730
}

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

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

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

  return endPos;
}

H
[td-32]  
hjxilinx 已提交
1754 1755
// 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
1756 1757
static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
1758
  SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
1759
  STsdbCfg*      pCfg = &pTsdbReadHandle->pTsdb->config;
H
Haojun Liao 已提交
1760

1761
  initTableMemIterator(pTsdbReadHandle, pCheckInfo);
1762

1763 1764
  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 已提交
1765
         cur->pos >= 0 && cur->pos < pBlock->numOfRows);
H
Haojun Liao 已提交
1766

1767
  TSKEY* tsArray = pCols->cols[0].pData;
dengyihao's avatar
dengyihao 已提交
1768 1769
  assert(pCols->numOfRows == pBlock->numOfRows && tsArray[0] == pBlock->keyFirst &&
         tsArray[pBlock->numOfRows - 1] == pBlock->keyLast);
1770 1771

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

dengyihao's avatar
dengyihao 已提交
1774
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1775
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
1776

H
Haojun Liao 已提交
1777
  STable* pTable = NULL;
1778
  int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &blockInfo);
H
Haojun Liao 已提交
1779

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

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

dengyihao's avatar
dengyihao 已提交
1787 1788
  int16_t   rv1 = -1;
  int16_t   rv2 = -1;
1789 1790
  STSchema* pSchema1 = NULL;
  STSchema* pSchema2 = NULL;
D
fix bug  
dapan1121 已提交
1791

H
Haojun Liao 已提交
1792 1793
  int32_t pos = cur->pos;
  cur->win = TSWINDOW_INITIALIZER;
1794

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

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

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

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

        mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                           pCheckInfo->tableId, pSchema1, pSchema2, true);
1834 1835 1836 1837
        numOfRows += 1;
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = key;
        }
1838

1839
        cur->win.ekey = key;
dengyihao's avatar
dengyihao 已提交
1840
        cur->lastKey = key + step;
1841 1842
        cur->mixBlock = true;

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

1858
          bool forceSetNull = pCfg->update != TD_ROW_PARTIAL_UPDATE;
dengyihao's avatar
dengyihao 已提交
1859 1860
          mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                             pCheckInfo->tableId, pSchema1, pSchema2, forceSetNull);
H
TD-1439  
Hongze Cheng 已提交
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874
          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);
        }
1875
      } else if ((key > tsArray[pos] && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
dengyihao's avatar
dengyihao 已提交
1876
                 (key < tsArray[pos] && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1877 1878 1879
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = tsArray[pos];
        }
1880

1881
        int32_t end = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, key, order);
1882 1883
        assert(end != -1);

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

1892
        int32_t qstart = 0, qend = 0;
1893
        getQualifiedRowsPos(pTsdbReadHandle, pos, end, numOfRows, &qstart, &qend);
1894

1895
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, qstart, qend);
1896 1897
        pos += (qend - qstart + 1) * step;

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

1903
    if (numOfRows < pTsdbReadHandle->outputCapacity) {
H
Haojun Liao 已提交
1904 1905 1906 1907
      /**
       * 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.
       */
1908
      if (node == NULL ||
H
Haojun Liao 已提交
1909
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) > pTsdbReadHandle->window.ekey) &&
1910
           ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
H
Haojun Liao 已提交
1911
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) < pTsdbReadHandle->window.ekey) &&
1912
           !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1913 1914 1915 1916 1917
        // 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];
        }

1918
        int32_t start = -1, end = -1;
1919
        getQualifiedRowsPos(pTsdbReadHandle, pos, endPos, numOfRows, &start, &end);
1920

1921
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, start, end);
1922
        pos += (end - start + 1) * step;
1923

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

  cur->blockCompleted =
1932 1933
      (((pos > endPos || cur->lastKey > pTsdbReadHandle->window.ekey) && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
       ((pos < endPos || cur->lastKey < pTsdbReadHandle->window.ekey) && !ASCENDING_TRAVERSE(pTsdbReadHandle->order)));
1934

1935
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1936
    TSWAP(cur->win.skey, cur->win.ekey, TSKEY);
1937
  }
1938

1939 1940 1941
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
  updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
  doCheckGeneratedBlockRange(pTsdbReadHandle);
H
Haojun Liao 已提交
1942

dengyihao's avatar
dengyihao 已提交
1943 1944 1945
  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);
1946 1947
}

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

H
[td-32]  
hjxilinx 已提交
1953
  if (num <= 0) return -1;
1954 1955

  keyList = (TSKEY*)pValue;
H
[td-32]  
hjxilinx 已提交
1956 1957
  firstPos = 0;
  lastPos = num - 1;
1958

1959
  if (order == TSDB_ORDER_DESC) {
H
[td-32]  
hjxilinx 已提交
1960 1961 1962 1963 1964
    // 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;
1965

H
Haojun Liao 已提交
1966 1967
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1968

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

H
[td-32]  
hjxilinx 已提交
1978 1979 1980 1981 1982
  } 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;
1983

H
[td-32]  
hjxilinx 已提交
1984 1985 1986 1987 1988 1989 1990
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
1991

H
Haojun Liao 已提交
1992 1993
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1994

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

H
[td-32]  
hjxilinx 已提交
2005 2006 2007
  return midPos;
}

2008
static void cleanBlockOrderSupporter(SBlockOrderSupporter* pSupporter, int32_t numOfTables) {
wafwerar's avatar
wafwerar 已提交
2009 2010
  taosMemoryFreeClear(pSupporter->numOfBlocksPerTable);
  taosMemoryFreeClear(pSupporter->blockIndexArray);
2011 2012

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

wafwerar's avatar
wafwerar 已提交
2017
  taosMemoryFreeClear(pSupporter->pDataBlockInfo);
2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028
}

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];

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

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

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

H
Haojun Liao 已提交
2048
  return pLeftBlockInfoEx->compBlock->offset > pRightBlockInfoEx->compBlock->offset ? 1 : -1;
2049 2050
}

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

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

dengyihao's avatar
dengyihao 已提交
2061
    pTsdbReadHandle->pDataBlockInfo = (STableBlockInfo*)tmp;
2062 2063
  }

2064
  memset(pTsdbReadHandle->pDataBlockInfo, 0, size);
2065 2066
  *numOfAllocBlocks = numOfBlocks;

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

2070 2071
  SBlockOrderSupporter sup = {0};
  sup.numOfTables = numOfTables;
wafwerar's avatar
wafwerar 已提交
2072 2073 2074
  sup.numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.blockIndexArray = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
2075

2076
  if (sup.numOfBlocksPerTable == NULL || sup.blockIndexArray == NULL || sup.pDataBlockInfo == NULL) {
2077
    cleanBlockOrderSupporter(&sup, 0);
2078
    return TSDB_CODE_TDB_OUT_OF_MEMORY;
2079
  }
H
Haojun Liao 已提交
2080

2081
  int32_t cnt = 0;
2082
  int32_t numOfQualTables = 0;
H
Haojun Liao 已提交
2083

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

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

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

2099
    sup.pDataBlockInfo[numOfQualTables] = (STableBlockInfo*)buf;
2100 2101

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

H
Haojun Liao 已提交
2104 2105
      pBlockInfo->compBlock = &pBlock[k];
      pBlockInfo->pTableCheckInfo = pTableCheck;
2106 2107 2108
      cnt++;
    }

2109
    numOfQualTables++;
2110 2111
  }

H
Haojun Liao 已提交
2112
  assert(numOfBlocks == cnt);
2113

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

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

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

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

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

  int32_t numOfTotal = 0;

  while (numOfTotal < cnt) {
2140
    int32_t pos = tMergeTreeGetChosenIndex(pTree);
2141 2142
    int32_t index = sup.blockIndexArray[pos]++;

H
Haojun Liao 已提交
2143
    STableBlockInfo* pBlocksInfo = sup.pDataBlockInfo[pos];
2144
    pTsdbReadHandle->pDataBlockInfo[numOfTotal++] = pBlocksInfo[index];
2145 2146

    // set data block index overflow, in order to disable the offset comparator
2147 2148
    if (sup.blockIndexArray[pos] >= sup.numOfBlocksPerTable[pos]) {
      sup.blockIndexArray[pos] = sup.numOfBlocksPerTable[pos] + 1;
2149
    }
2150

H
Haojun Liao 已提交
2151
    tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
2152 2153 2154 2155 2156
  }

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

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

  return TSDB_CODE_SUCCESS;
}

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

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

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

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

2193 2194 2195
static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  pTsdbReadHandle->numOfBlocks = 0;
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
2196 2197 2198

  int32_t code = TSDB_CODE_SUCCESS;

2199
  int32_t numOfBlocks = 0;
2200
  int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
2201

dengyihao's avatar
dengyihao 已提交
2202
  STsdbCfg*   pCfg = &pTsdbReadHandle->pTsdb->config;
2203 2204
  STimeWindow win = TSWINDOW_INITIALIZER;

H
Hongze Cheng 已提交
2205
  while (true) {
2206
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2207

2208 2209
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2210 2211 2212
      break;
    }

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

    // current file are not overlapped with query time window, ignore remain files
2216 2217 2218
    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 已提交
2219 2220
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
                pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
2221 2222
      pTsdbReadHandle->pFileGroup = NULL;
      assert(pTsdbReadHandle->numOfBlocks == 0);
2223 2224 2225
      break;
    }

2226 2227
    if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2228 2229 2230 2231
      code = terrno;
      break;
    }

2232
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2233

2234
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Hongze Cheng 已提交
2235 2236 2237 2238
      code = terrno;
      break;
    }

2239
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
2240 2241
      break;
    }
H
Haojun Liao 已提交
2242

H
Haojun Liao 已提交
2243 2244
    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 已提交
2245

2246 2247 2248 2249
    assert(numOfBlocks >= 0);
    if (numOfBlocks == 0) {
      continue;
    }
H
Haojun Liao 已提交
2250

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

2257 2258
    assert(numOfBlocks >= pTsdbReadHandle->numOfBlocks);
    if (pTsdbReadHandle->numOfBlocks > 0) {
2259 2260 2261
      break;
    }
  }
H
Haojun Liao 已提交
2262

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

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

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

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

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

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

2290 2291
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
  assert(cur->slot < pTsdbReadHandle->numOfBlocks && cur->slot >= 0);
H
Haojun Liao 已提交
2292 2293

  cur->slot += step;
dengyihao's avatar
dengyihao 已提交
2294
  cur->mixBlock = false;
H
Haojun Liao 已提交
2295
  cur->blockCompleted = false;
2296
}
H
Haojun Liao 已提交
2297 2298

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

H
Haojun Liao 已提交
2301
  pTableBlockInfo->totalSize = 0;
2302
  pTableBlockInfo->totalRows = 0;
H
Haojun Liao 已提交
2303

2304
  STsdbFS* pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
2305 2306

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

  tsdbRLockFS(pFileHandle);
2312 2313
  tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
  tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Haojun Liao 已提交
2314 2315
  tsdbUnLockFS(pFileHandle);

H
Haojun Liao 已提交
2316
  pTableBlockInfo->numOfFiles += 1;
H
Haojun Liao 已提交
2317

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

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

H
Haojun Liao 已提交
2326 2327
  while (true) {
    numOfBlocks = 0;
2328
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2329

2330 2331
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2332 2333 2334
      break;
    }

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

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

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

2354
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2355

2356
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Haojun Liao 已提交
2357 2358 2359 2360
      code = terrno;
      break;
    }

2361
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2362 2363 2364
      break;
    }

H
Haojun Liao 已提交
2365 2366
    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 已提交
2367 2368 2369 2370 2371 2372

    if (numOfBlocks == 0) {
      continue;
    }

    for (int32_t i = 0; i < numOfTables; ++i) {
2373
      STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2374 2375 2376

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

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

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

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

  return code;
}

2402 2403 2404
static int32_t getDataBlocksInFiles(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  STsdbFS*       pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2405 2406

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

H
Hongze Cheng 已提交
2412
    tsdbRLockFS(pFileHandle);
2413 2414
    tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
    tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Hongze Cheng 已提交
2415
    tsdbUnLockFS(pFileHandle);
2416

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

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

H
Haojun Liao 已提交
2432 2433 2434 2435 2436 2437 2438
      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
2439 2440
    if (isEndFileDataBlock(cur, pTsdbReadHandle->numOfBlocks, ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
      return getFirstFileDataBlock(pTsdbReadHandle, exists);
H
Haojun Liao 已提交
2441
    } else {
2442 2443 2444
      moveToNextDataBlockInCurrentFile(pTsdbReadHandle);
      STableBlockInfo* pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
      return getDataBlockRv(pTsdbReadHandle, pNext, exists);
2445 2446
    }
  }
2447 2448
}

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

2452 2453
  while (pTsdbReadHandle->activeIndex < numOfTables) {
    if (hasMoreDataInCache(pTsdbReadHandle)) {
2454 2455
      return true;
    }
H
Haojun Liao 已提交
2456

2457
    pTsdbReadHandle->activeIndex += 1;
2458
  }
H
Haojun Liao 已提交
2459

2460 2461 2462
  return false;
}

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

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

  int32_t i = 0;
dengyihao's avatar
dengyihao 已提交
2472
  while (i < numOfTables) {
2473
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2474 2475

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

    i++;
  }

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

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

2492 2493
  info.lastKey = pTsdbReadHandle->window.skey;
  taosArrayPush(pTsdbReadHandle->pTableCheckInfo, &info);
H
Haojun Liao 已提交
2494 2495 2496
}

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

dengyihao's avatar
dengyihao 已提交
2503 2504
  int64_t   st = taosGetTimestampUs();
  int16_t   rv = -1;
D
fix bug  
dapan1121 已提交
2505
  STSchema* pSchema = NULL;
H
Haojun Liao 已提交
2506 2507

  do {
H
Haojun Liao 已提交
2508
    STSRow* row = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, NULL);
H
Haojun Liao 已提交
2509 2510 2511 2512
    if (row == NULL) {
      break;
    }

H
Haojun Liao 已提交
2513
    TSKEY key = TD_ROW_KEY(row);
dengyihao's avatar
dengyihao 已提交
2514 2515 2516 2517
    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 已提交
2518 2519 2520 2521 2522 2523 2524 2525 2526

      break;
    }

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

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

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

dengyihao's avatar
dengyihao 已提交
2539
  } while (moveToNextRowInMem(pCheckInfo));
H
Haojun Liao 已提交
2540 2541 2542 2543

  assert(numOfRows <= maxRowsToRead);

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

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

  int64_t elapsedTime = taosGetTimestampUs() - st;
dengyihao's avatar
dengyihao 已提交
2555 2556
  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 已提交
2557 2558 2559 2560

  return numOfRows;
}

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

2564 2565 2566 2567 2568
  while (1) {
    tb_uid_t id = metaCtbCursorNext(pCur);
    if (id == 0) {
      break;
    }
H
Haojun Liao 已提交
2569

2570
    STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, uid = id};
H
Haojun Liao 已提交
2571 2572 2573
    taosArrayPush(list, &info);
  }

2574
  metaCloseCtbCurosr(pCur);
H
Haojun Liao 已提交
2575 2576 2577 2578 2579 2580 2581 2582
  return TSDB_CODE_SUCCESS;
}

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

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

wafwerar's avatar
wafwerar 已提交
2590
  taosMemoryFree(param);
H
Haojun Liao 已提交
2591 2592
}

dengyihao's avatar
dengyihao 已提交
2593 2594
#define TSDB_PREV_ROW 0x1
#define TSDB_NEXT_ROW 0x2
2595

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

2601
    int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
H
Haojun Liao 已提交
2602
    if (code != TSDB_CODE_SUCCESS) {
2603
      pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2604 2605
      return false;
    }
H
Haojun Liao 已提交
2606

H
Haojun Liao 已提交
2607
    if (exists) {
dengyihao's avatar
dengyihao 已提交
2608
      tsdbRetrieveDataBlock((tsdbReaderT*)pTsdbReadHandle, NULL);
2609 2610 2611
      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 已提交
2612 2613
      }

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

2618
    pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2619
  }
H
Haojun Liao 已提交
2620

2621 2622
  if (hasMoreDataInCache(pTsdbReadHandle)) {
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2623 2624
    return true;
  }
H
Haojun Liao 已提交
2625

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

dengyihao's avatar
dengyihao 已提交
2631 2632
    //    doGetExternalRow(pTsdbReadHandle, TSDB_PREV_ROW, pMemRef);
    //    doGetExternalRow(pTsdbReadHandle, TSDB_NEXT_ROW, pMemRef);
H
Haojun Liao 已提交
2633

2634
    bool result = tsdbGetExternalRow(pTsdbReadHandle);
H
Haojun Liao 已提交
2635

dengyihao's avatar
dengyihao 已提交
2636 2637
    //    pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
    //    pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
2638
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2639 2640

    return result;
2641
  }
H
Haojun Liao 已提交
2642

H
Haojun Liao 已提交
2643 2644
  return false;
}
2645

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

2653
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2654

dengyihao's avatar
dengyihao 已提交
2655 2656 2657
  STSRow* pRow = NULL;
  TSKEY   key = TSKEY_INITIAL_VAL;
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
2658 2659 2660

  if (++pTsdbReadHandle->activeIndex < numOfTables) {
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
dengyihao's avatar
dengyihao 已提交
2661 2662 2663 2664 2665 2666
    //    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 已提交
2667
    taosMemoryFreeClear(pRow);
H
Haojun Liao 已提交
2668

H
Haojun Liao 已提交
2669 2670 2671
    // update the last key value
    pCheckInfo->lastKey = key + step;

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

    return true;
2679
  }
H
Haojun Liao 已提交
2680

H
Haojun Liao 已提交
2681 2682 2683
  return false;
}

dengyihao's avatar
dengyihao 已提交
2684
// static bool loadCachedLast(STsdbReadHandle* pTsdbReadHandle) {
2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703
//  // 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 已提交
2704 2705
//      tsdbWarn("no last cached for table %s, uid:%" PRIu64 ",tid:%d", pTable->name->data, pTable->uid,
//      pTable->tableId); continue;
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 2832 2833 2834 2835
//    }
//
//    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 已提交
2836 2837 2838
  assert(numOfTables > 0);

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

dengyihao's avatar
dengyihao 已提交
2840
  while (pTsdbReadHandle->activeIndex < numOfTables) {
2841
    if (loadBlockOfActiveTable(pTsdbReadHandle)) {
H
Haojun Liao 已提交
2842 2843 2844
      return true;
    }

2845
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
H
Haojun Liao 已提交
2846 2847
    pCheckInfo->numOfBlocks = 0;

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

    terrno = TSDB_CODE_SUCCESS;

    int64_t elapsedTime = taosGetTimestampUs() - stime;
2857
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2858 2859 2860
  }

  return false;
2861 2862
}

H
Haojun Liao 已提交
2863
// handle data in cache situation
H
Haojun Liao 已提交
2864
bool tsdbNextDataBlock(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
2865
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
Y
yihaoDeng 已提交
2866

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

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

Y
yihaoDeng 已提交
2878 2879 2880
  int64_t stime = taosGetTimestampUs();
  int64_t elapsedTime = stime;

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

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

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

        return false;
      }

      if (exists) {
2906
        pTsdbReadHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime);
H
Haojun Liao 已提交
2907 2908
        return exists;
      }
Y
yihaoDeng 已提交
2909

2910 2911
      pTsdbReadHandle->activeIndex = 0;
      pTsdbReadHandle->checkFiles = false;
Y
yihaoDeng 已提交
2912 2913
    }

H
Haojun Liao 已提交
2914
    // TODO: opt by consider the scan order
2915
    bool ret = doHasDataInBuffer(pTsdbReadHandle);
H
Haojun Liao 已提交
2916
    terrno = TSDB_CODE_SUCCESS;
Y
yihaoDeng 已提交
2917

H
Haojun Liao 已提交
2918
    elapsedTime = taosGetTimestampUs() - stime;
2919
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2920
    return ret;
Y
yihaoDeng 已提交
2921 2922
  }
}
2923

dengyihao's avatar
dengyihao 已提交
2924
// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, STsdbMemTable* pMemRef) {
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 2955 2956 2957 2958
//  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 已提交
2959
//    colInfo.pData = taosMemoryCalloc(1, pCol->info.bytes);
2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977
//    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 已提交
2978
//  cond.colList = taosMemoryCalloc(cond.numOfCols, sizeof(SColumnInfo));
2979 2980 2981 2982 2983 2984 2985 2986 2987 2988
//  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 已提交
2989
//  pSecQueryHandle = tsdbQueryTablesImpl(pTsdbReadHandle->pTsdb, &cond, pTsdbReadHandle->idStr, pMemRef);
wafwerar's avatar
wafwerar 已提交
2990
//  taosMemoryFreeClear(cond.colList);
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 3025 3026 3027 3028
//
//  // 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 已提交
3029
// out_of_memory:
3030
//  tsdbCleanupReadHandle(pSecQueryHandle);
3031 3032 3033
//  return terrno;
//}

H
Haojun Liao 已提交
3034
bool tsdbGetExternalRow(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
3035 3036
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
  SQueryFilePos*   cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
3037

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

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

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

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

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

H
Haojun Liao 已提交
3061 3062
  cur->rows = 2;
  return true;
3063 3064
}

3065
/*
3066
 * if lastRow == NULL, return TSDB_CODE_TDB_NO_CACHE_LAST_ROW
3067
 * else set pRes and return TSDB_CODE_SUCCESS and save lastKey
3068
 */
H
Haojun Liao 已提交
3069
// int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey) {
3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085
//  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 已提交
3086
// out:
3087 3088 3089 3090
//  TSDB_RUNLOCK_TABLE(pTable);
//  return code;
//}

3091
bool isTsdbCacheLastRow(tsdbReaderT* pReader) {
dengyihao's avatar
dengyihao 已提交
3092
  return ((STsdbReadHandle*)pReader)->cachelastrow > TSDB_CACHED_TYPE_NONE;
D
fix bug  
dapan1121 已提交
3093 3094
}

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

dengyihao's avatar
dengyihao 已提交
3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121
  //  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 已提交
3122

3123
  return TSDB_CODE_SUCCESS;
3124 3125
}

3126 3127
int32_t checkForCachedLast(STsdbReadHandle* pTsdbReadHandle) {
  assert(pTsdbReadHandle != NULL);
D
update  
dapan1121 已提交
3128 3129

  int32_t code = 0;
dengyihao's avatar
dengyihao 已提交
3130 3131 3132
  //  if (pTsdbReadHandle->pTsdb && atomic_load_8(&pTsdbReadHandle->pTsdb->hasCachedLastColumn)){
  //    pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LAST;
  //  }
D
update  
dapan1121 已提交
3133 3134

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

  return code;
}

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

H
Haojun Liao 已提交
3146
  int32_t totalNumOfTable = 0;
3147
  SArray* emptyGroup = taosArrayInit(16, sizeof(int32_t));
H
Haojun Liao 已提交
3148

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

H
Haojun Liao 已提交
3155
    STableKeyInfo keyInfo = {0};
H
Haojun Liao 已提交
3156

H
Haojun Liao 已提交
3157
    size_t numOfTables = taosArrayGetSize(pGroup);
dengyihao's avatar
dengyihao 已提交
3158 3159
    for (int32_t i = 0; i < numOfTables; ++i) {
      STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i);
H
Haojun Liao 已提交
3160

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

dengyihao's avatar
dengyihao 已提交
3166
        //        keyInfo.pTable  = pInfo->pTable;
H
Haojun Liao 已提交
3167
        keyInfo.lastKey = key;
dengyihao's avatar
dengyihao 已提交
3168
        pInfo->lastKey = key;
H
Haojun Liao 已提交
3169

H
Haojun Liao 已提交
3170 3171 3172
        if (key < window.skey) {
          window.skey = key;
        }
3173

H
Haojun Liao 已提交
3174 3175 3176 3177
        if (key > window.ekey) {
          window.ekey = key;
        }
      }
3178
    }
H
Haojun Liao 已提交
3179

H
Haojun Liao 已提交
3180
    // more than one table in each group, only one table left for each group
dengyihao's avatar
dengyihao 已提交
3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192
    //    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);
    //    }
3193
  }
H
Haojun Liao 已提交
3194

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

dengyihao's avatar
dengyihao 已提交
3201
  taosArrayRemoveBatch(groupList->pGroupList, TARRAY_GET_START(emptyGroup), (int32_t)taosArrayGetSize(emptyGroup));
3202 3203
  taosArrayDestroy(emptyGroup);

H
Haojun Liao 已提交
3204
  groupList->numOfTables = totalNumOfTable;
H
Haojun Liao 已提交
3205
  return window;
H
hjxilinx 已提交
3206 3207
}

H
Haojun Liao 已提交
3208
void tsdbRetrieveDataBlockInfo(tsdbReaderT* pTsdbReadHandle, SDataBlockInfo* pDataBlockInfo) {
3209
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
dengyihao's avatar
dengyihao 已提交
3210
  SQueryFilePos*   cur = &pHandle->cur;
3211 3212

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

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

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

dengyihao's avatar
dengyihao 已提交
3226 3227 3228
  //  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 已提交
3229
  pDataBlockInfo->window = cur->win;
S
TD-1057  
Shengliang Guan 已提交
3230
  pDataBlockInfo->numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pHandle));
3231
}
H
hjxilinx 已提交
3232

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

H
Haojun Liao 已提交
3239 3240
  SQueryFilePos* c = &pHandle->cur;
  if (c->mixBlock) {
H
Haojun Liao 已提交
3241 3242 3243
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3244

H
Haojun Liao 已提交
3245 3246 3247 3248
  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 已提交
3249 3250 3251 3252
  if (pBlockInfo->compBlock->numOfSubBlocks > 1) {
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3253 3254

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

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

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

3271
  tsdbGetBlockStatis(&pHandle->rhelper, pHandle->statis, (int)numOfCols, pBlockInfo->compBlock);
H
Haojun Liao 已提交
3272 3273

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

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

dengyihao's avatar
dengyihao 已提交
3281 3282 3283
  // 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 已提交
3284 3285 3286
      pHandle->statis[i].numOfNull = pBlockInfo->compBlock->numOfRows;
    }
  }
H
Haojun Liao 已提交
3287 3288 3289 3290

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

H
Haojun Liao 已提交
3291
  *pBlockStatis = pHandle->statis;
3292
  return TSDB_CODE_SUCCESS;
H
hjxilinx 已提交
3293 3294
}

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

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

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

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

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

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

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

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

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

3354
  STSchema*   pTSSchema = (STSchema*) param;
H
hjxilinx 已提交
3355 3356 3357
  tQueryInfo* pInfo = pExpr->_node.info;
  tVariant*   pCond = pExpr->_node.pRight->pVal;
  SSchema*    pSchema = pExpr->_node.pLeft->pSchema;
3358

3359 3360
  pInfo->sch      = *pSchema;
  pInfo->optr     = pExpr->_node.optr;
Y
yihaoDeng 已提交
3361
  pInfo->compare  = getComparFunc(pInfo->sch.type, pInfo->optr);
H
Haojun Liao 已提交
3362
  pInfo->indexed  = pTSSchema->columns->colId == pInfo->sch.colId;
H
Haojun Liao 已提交
3363

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

3390
#endif
3391

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

3398 3399 3400
  for (int32_t i = 0; i < pTableGroupSupp->numOfCols; ++i) {
    SColIndex* pColIndex = &pTableGroupSupp->pCols[i];
    int32_t colIndex = pColIndex->colIndex;
H
Haojun Liao 已提交
3401

H
Haojun Liao 已提交
3402
    assert(colIndex >= TSDB_TBNAME_COLUMN_INDEX);
H
Haojun Liao 已提交
3403

3404 3405 3406 3407
    char *  f1 = NULL;
    char *  f2 = NULL;
    int32_t type = 0;
    int32_t bytes = 0;
H
Haojun Liao 已提交
3408

H
Haojun Liao 已提交
3409 3410 3411
    if (colIndex == TSDB_TBNAME_COLUMN_INDEX) {
      f1 = (char*) TABLE_NAME(pTable1);
      f2 = (char*) TABLE_NAME(pTable2);
3412
      type = TSDB_DATA_TYPE_BINARY;
3413
      bytes = tGetTbnameColumnSchema()->bytes;
3414
    } else {
Y
yihaoDeng 已提交
3415 3416 3417 3418 3419 3420 3421
      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);
      } 
3422
    }
H
Haojun Liao 已提交
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436

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

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

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

3437 3438 3439 3440 3441 3442 3443
    int32_t ret = doCompare(f1, f2, type, bytes);
    if (ret == 0) {
      continue;
    } else {
      return ret;
    }
  }
3444
#endif
3445 3446 3447
  return 0;
}

H
Haojun Liao 已提交
3448
static int tsdbCheckInfoCompar(const void* key1, const void* key2) {
3449
  if (((STableCheckInfo*)key1)->tableId < ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3450
    return -1;
3451
  } else if (((STableCheckInfo*)key1)->tableId > ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3452 3453 3454 3455 3456 3457 3458 3459 3460
    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) {
3461
  STable* pTable = taosArrayGetP(pTableList, 0);
H
Haojun Liao 已提交
3462 3463
  SArray* g = taosArrayInit(16, sizeof(STableKeyInfo));

3464
  STableKeyInfo info = {.lastKey = skey};
H
Haojun Liao 已提交
3465
  taosArrayPush(g, &info);
3466

3467
  for (int32_t i = 1; i < numOfTables; ++i) {
3468 3469
    STable** prev = taosArrayGet(pTableList, i - 1);
    STable** p = taosArrayGet(pTableList, i);
H
Haojun Liao 已提交
3470

H
hjxilinx 已提交
3471
    int32_t ret = compareFn(prev, p, pSupp);
3472
    assert(ret == 0 || ret == -1);
H
Haojun Liao 已提交
3473

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

3481
      STableKeyInfo info1 = {.lastKey = skey};
H
Haojun Liao 已提交
3482
      taosArrayPush(g, &info1);
3483 3484
    }
  }
H
Haojun Liao 已提交
3485

3486
  taosArrayPush(pGroups, &g);
3487 3488
}

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

3494 3495
  size_t size = taosArrayGetSize(pTableList);
  if (size == 0) {
S
Shengliang Guan 已提交
3496
    tsdbDebug("no qualified tables");
3497 3498
    return pTableGroup;
  }
H
Haojun Liao 已提交
3499

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

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

3515 3516
    taosqsort(pTableList->pData, size, sizeof(STableKeyInfo), &sup, tableGroupComparFn);
    createTableGroupImpl(pTableGroup, pTableList, size, skey, &sup, tableGroupComparFn);
3517
  }
H
Haojun Liao 已提交
3518

3519 3520 3521
  return pTableGroup;
}

dengyihao's avatar
dengyihao 已提交
3522
// static bool tableFilterFp(const void* pNode, void* param) {
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 3602 3603 3604 3605
//  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 已提交
3606

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

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

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

3633
  if (pTbCfg->type != META_SUPER_TABLE) {
dengyihao's avatar
dengyihao 已提交
3634 3635 3636
    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
3637
    goto _error;
H
hjxilinx 已提交
3638
  }
3639

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

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

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

dengyihao's avatar
dengyihao 已提交
3654 3655 3656
    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);
3657

3658
    taosArrayDestroy(res);
3659 3660
    return ret;
  }
3661

H
hjxilinx 已提交
3662
  int32_t ret = TSDB_CODE_SUCCESS;
3663

dengyihao's avatar
dengyihao 已提交
3664 3665
  SFilterInfo* filterInfo = NULL;
  ret = filterInitFromNode((SNode*)pTagCond, &filterInfo, 0);
dengyihao's avatar
dengyihao 已提交
3666 3667 3668 3669 3670 3671 3672 3673
  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 已提交
3674 3675
  // 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 已提交
3676 3677 3678 3679 3680

  taosArrayDestroy(res);
  return ret;

_error:
3681
  return terrno;
3682
}
3683

dengyihao's avatar
dengyihao 已提交
3684 3685 3686 3687 3688
int32_t tsdbQueryTableList(void* pMeta, SArray* pRes, void* filterInfo) {
  // impl later

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

3696 3697
  pGroupInfo->numOfTables = 1;
  pGroupInfo->pGroupList = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3698

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

3701
  STableKeyInfo info = {.lastKey = startKey, .uid = uid};
H
Haojun Liao 已提交
3702
  taosArrayPush(group, &info);
H
Haojun Liao 已提交
3703

3704
  taosArrayPush(pGroupInfo->pGroupList, &group);
3705
  return TSDB_CODE_SUCCESS;
3706

dengyihao's avatar
dengyihao 已提交
3707
_error:
3708
  return terrno;
3709
}
3710

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

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

B
Bomin Zhang 已提交
3722
  for(int32_t i = 0; i < size; ++i) {
3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733
    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 已提交
3734 3735 3736
      tsdbUnlockRepoMeta(tsdb);
      taosArrayDestroy(group);
      return terrno;
3737 3738
    }

H
Haojun Liao 已提交
3739 3740
    STableKeyInfo info = {.pTable = pTable, .lastKey = id->key};
    taosArrayPush(group, &info);
3741 3742
  }

B
Bomin Zhang 已提交
3743 3744 3745 3746
  if (tsdbUnlockRepoMeta(tsdb) < 0) {
    taosArrayDestroy(group);
    return terrno;
  }
3747

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

  return TSDB_CODE_SUCCESS;
}
3757
#endif
3758 3759 3760 3761 3762 3763 3764 3765
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 已提交
3766
    taosMemoryFreeClear(pColInfo->pData);
3767 3768 3769 3770 3771 3772
  }

  taosArrayDestroy(pColumnInfoData);
  return NULL;
}

H
Haojun Liao 已提交
3773 3774 3775 3776 3777 3778
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 已提交
3779
    taosMemoryFreeClear(p->pCompInfo);
H
Haojun Liao 已提交
3780 3781 3782 3783 3784 3785
  }

  taosArrayDestroy(pTableCheckInfo);
  return NULL;
}

H
Haojun Liao 已提交
3786
void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
3787 3788
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
  if (pTsdbReadHandle == NULL) {
3789 3790
    return;
  }
3791

3792
  pTsdbReadHandle->pColumns = doFreeColumnInfoData(pTsdbReadHandle->pColumns);
3793

3794
  taosArrayDestroy(pTsdbReadHandle->defaultLoadColumn);
wafwerar's avatar
wafwerar 已提交
3795 3796
  taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
  taosMemoryFreeClear(pTsdbReadHandle->statis);
3797

3798
  if (!emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
3799
    //    tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
3800
  } else {
3801
    assert(pTsdbReadHandle->pTableCheckInfo == NULL);
3802 3803
  }

3804 3805
  if (pTsdbReadHandle->pTableCheckInfo != NULL) {
    pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
3806
  }
3807

3808
  tsdbDestroyReadH(&pTsdbReadHandle->rhelper);
H
Haojun Liao 已提交
3809

3810 3811
  tdFreeDataCols(pTsdbReadHandle->pDataCols);
  pTsdbReadHandle->pDataCols = NULL;
H
Haojun Liao 已提交
3812

3813 3814
  pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
  pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
3815

3816
  SIOCostSummary* pCost = &pTsdbReadHandle->cost;
3817

dengyihao's avatar
dengyihao 已提交
3818 3819 3820 3821
  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 已提交
3822

wafwerar's avatar
wafwerar 已提交
3823
  taosMemoryFreeClear(pTsdbReadHandle);
3824
}
3825

3826
#if 0
H
Haojun Liao 已提交
3827
void tsdbDestroyTableGroup(STableGroupInfo *pGroupList) {
3828 3829 3830 3831 3832 3833 3834 3835 3836 3837
  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);
3838 3839 3840 3841
      if (pTable != NULL) { // in case of handling retrieve data from tsdb
        tsdbUnRefTable(pTable);
      }
      //assert(pTable != NULL);
3842 3843 3844 3845 3846
    }

    taosArrayDestroy(p);
  }

3847
  taosHashCleanup(pGroupList->map);
3848
  taosArrayDestroy(pGroupList->pGroupList);
H
Haojun Liao 已提交
3849
  pGroupList->numOfTables = 0;
3850
}
H
Haojun Liao 已提交
3851 3852 3853 3854 3855 3856 3857

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 已提交
3858
    if (exprTreeApplyFilter(pExpr, pNode, param)) {
H
Haojun Liao 已提交
3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881
      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 已提交
3882
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3883
    pCond->start->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3884
    pCond->start->v    = queryColInfo->q;
H
Haojun Liao 已提交
3885
  } else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
wafwerar's avatar
wafwerar 已提交
3886
    pCond->end       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3887
    pCond->end->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3888 3889
    pCond->end->v    = queryColInfo->q;
  } else if (optr == TSDB_RELATION_IN) {
wafwerar's avatar
wafwerar 已提交
3890
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
Y
yihaoDeng 已提交
3891 3892 3893
    pCond->start->optr = queryColInfo->optr;
    pCond->start->v    = queryColInfo->q; 
  } else if (optr == TSDB_RELATION_LIKE) {
H
Haojun Liao 已提交
3894
    assert(0);
3895 3896
  } else if (optr == TSDB_RELATION_MATCH) {
    assert(0);
3897 3898
  } else if (optr == TSDB_RELATION_NMATCH) {
    assert(0);
H
Haojun Liao 已提交
3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981
  }

  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 已提交
3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994
    } 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 已提交
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 4032 4033 4034 4035
    } 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 已提交
4036 4037
  taosMemoryFree(cond.start);
  taosMemoryFree(cond.end);
H
Haojun Liao 已提交
4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055
  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);
4056 4057 4058
      } else if (pQueryInfo->optr == TSDB_RELATION_LIKE ||
                 pQueryInfo->optr == TSDB_RELATION_MATCH ||
                 pQueryInfo->optr == TSDB_RELATION_NMATCH) {
H
Haojun Liao 已提交
4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074
        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 已提交
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 4104 4105 4106 4107
//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 已提交
4108
#endif