tsdbRead.c 142.4 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/>.
 */

H
Hongze Cheng 已提交
16
#include "tsdb.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 101 102 103 104 105 106
typedef struct SBlockLoadSuppInfo {
  SColumnDataAgg  *pstatis;
  SColumnDataAgg **plist;
  SArray          *defaultLoadColumn;  // default load column
  int32_t         *slotIds;            // colId to slotId
} SBlockLoadSuppInfo;

107
typedef struct STsdbReadHandle {
H
Hongze Cheng 已提交
108 109 110 111
  STsdb*          pTsdb;
  SQueryFilePos   cur;  // current position
  int16_t         order;
  STimeWindow     window;  // the primary query time window that applies to all queries
112 113
//  SColumnDataAgg* statis;  // query level statistics, only one table block statistics info exists at any time
//  SColumnDataAgg** pstatis;// the ptr array list to return to caller
H
Hongze Cheng 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126
  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
dengyihao's avatar
dengyihao 已提交
127 128 129 130 131 132 133 134 135
  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
  SDataBlockLoadInfo dataBlockLoadInfo;  /* record current block load information */
  SLoadCompBlockInfo compBlockLoadInfo;  /* record current compblock information in SQueryAttr */
136
  SBlockLoadSuppInfo suppInfo;
dengyihao's avatar
dengyihao 已提交
137 138
  SArray*        prev;  // previous row which is before than time window
  SArray*        next;  // next row which is after the query time window
H
Haojun Liao 已提交
139
  SIOCostSummary cost;
140
  STSchema*      pSchema;
141
} STsdbReadHandle;
142

H
Haojun Liao 已提交
143 144 145
typedef struct STableGroupSupporter {
  int32_t    numOfCols;
  SColIndex* pCols;
146
  SSchema*   pTagSchema;
H
Haojun Liao 已提交
147 148
} STableGroupSupporter;

dengyihao's avatar
dengyihao 已提交
149 150 151 152 153
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 已提交
154
// static int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey);
H
Haojun Liao 已提交
155

H
Haojun Liao 已提交
156
static void    changeQueryHandleForInterpQuery(tsdbReaderT pHandle);
157
static void    doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock);
dengyihao's avatar
dengyihao 已提交
158 159
static int32_t tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
                                     STsdbReadHandle* pTsdbReadHandle);
160
static int32_t tsdbCheckInfoCompar(const void* key1, const void* key2);
dengyihao's avatar
dengyihao 已提交
161 162 163 164
// 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 已提交
165

166
static void tsdbInitDataBlockLoadInfo(SDataBlockLoadInfo* pBlockLoadInfo) {
H
hjxilinx 已提交
167
  pBlockLoadInfo->slot = -1;
dengyihao's avatar
dengyihao 已提交
168
  pBlockLoadInfo->uid = 0;
H
hjxilinx 已提交
169
  pBlockLoadInfo->fileGroup = NULL;
H
hjxilinx 已提交
170 171
}

172
static void tsdbInitCompBlockLoadInfo(SLoadCompBlockInfo* pCompBlockLoadInfo) {
H
hjLiao 已提交
173
  pCompBlockLoadInfo->tid = -1;
174 175
  pCompBlockLoadInfo->fileId = -1;
}
H
hjxilinx 已提交
176

177 178
static SArray* getColumnIdList(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfCols = QH_GET_NUM_OF_COLS(pTsdbReadHandle);
H
Haojun Liao 已提交
179 180 181 182
  assert(numOfCols <= TSDB_MAX_COLUMNS);

  SArray* pIdList = taosArrayInit(numOfCols, sizeof(int16_t));
  for (int32_t i = 0; i < numOfCols; ++i) {
183
    SColumnInfoData* pCol = taosArrayGet(pTsdbReadHandle->pColumns, i);
H
Haojun Liao 已提交
184 185 186 187 188 189
    taosArrayPush(pIdList, &pCol->info.colId);
  }

  return pIdList;
}

190 191
static SArray* getDefaultLoadColumns(STsdbReadHandle* pTsdbReadHandle, bool loadTS) {
  SArray* pLocalIdList = getColumnIdList(pTsdbReadHandle);
H
Haojun Liao 已提交
192 193 194 195 196

  // 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 已提交
197 198
  if (loadTS && colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
    int16_t columnId = PRIMARYKEY_TIMESTAMP_COL_ID;
H
Haojun Liao 已提交
199 200 201 202 203 204
    taosArrayInsert(pLocalIdList, 0, &columnId);
  }

  return pLocalIdList;
}

H
Haojun Liao 已提交
205
int64_t tsdbGetNumOfRowsInMemTable(tsdbReaderT* pHandle) {
dengyihao's avatar
dengyihao 已提交
206
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
H
Haojun Liao 已提交
207

dengyihao's avatar
dengyihao 已提交
208 209 210 211 212
  int64_t        rows = 0;
  STsdbMemTable* pMemTable = NULL;  // pTsdbReadHandle->pMemTable;
  if (pMemTable == NULL) {
    return rows;
  }
H
Haojun Liao 已提交
213

dengyihao's avatar
dengyihao 已提交
214 215
  //  STableData* pMem  = NULL;
  //  STableData* pIMem = NULL;
H
Haojun Liao 已提交
216

dengyihao's avatar
dengyihao 已提交
217 218
  //  SMemTable* pMemT = pMemRef->snapshot.mem;
  //  SMemTable* pIMemT = pMemRef->snapshot.imem;
H
Haojun Liao 已提交
219 220 221 222 223

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

dengyihao's avatar
dengyihao 已提交
224 225 226 227 228 229 230 231
    //    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 已提交
232 233 234
  }
  return rows;
}
235

236 237 238
static SArray* createCheckInfoFromTableGroup(STsdbReadHandle* pTsdbReadHandle, STableGroupInfo* pGroupList) {
  size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);
  assert(numOfGroup >= 1);
H
Haojun Liao 已提交
239 240 241 242 243 244 245 246

  // 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
247
  for (int32_t i = 0; i < numOfGroup; ++i) {
dengyihao's avatar
dengyihao 已提交
248
    SArray* group = *(SArray**)taosArrayGet(pGroupList->pGroupList, i);
H
Haojun Liao 已提交
249 250 251 252 253

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

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

dengyihao's avatar
dengyihao 已提交
256
      STableCheckInfo info = {.lastKey = pKeyInfo->lastKey, .tableId = pKeyInfo->uid};
257 258 259
      if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
        if (info.lastKey == INT64_MIN || info.lastKey < pTsdbReadHandle->window.skey) {
          info.lastKey = pTsdbReadHandle->window.skey;
260 261
        }

262
        assert(info.lastKey >= pTsdbReadHandle->window.skey && info.lastKey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
263
      } else {
264
        info.lastKey = pTsdbReadHandle->window.skey;
H
Haojun Liao 已提交
265 266 267
      }

      taosArrayPush(pTableCheckInfo, &info);
dengyihao's avatar
dengyihao 已提交
268 269
      tsdbDebug("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pTsdbReadHandle, info.tableId,
                info.lastKey, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
270 271 272
    }
  }

273
  // TODO  group table according to the tag value.
274
  taosArraySort(pTableCheckInfo, tsdbCheckInfoCompar);
H
Haojun Liao 已提交
275 276 277
  return pTableCheckInfo;
}

278 279
static void resetCheckInfo(STsdbReadHandle* pTsdbReadHandle) {
  size_t numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
280 281 282 283
  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 已提交
284
    STableCheckInfo* pCheckInfo = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
285
    pCheckInfo->lastKey = pTsdbReadHandle->window.skey;
dengyihao's avatar
dengyihao 已提交
286 287
    pCheckInfo->iter = tSkipListDestroyIter(pCheckInfo->iter);
    pCheckInfo->iiter = tSkipListDestroyIter(pCheckInfo->iiter);
288
    pCheckInfo->initBuf = false;
H
Haojun Liao 已提交
289

290 291
    if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
      assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.skey);
292
    } else {
293
      assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.skey);
294
    }
H
Haojun Liao 已提交
295 296 297
  }
}

H
Haojun Liao 已提交
298 299 300
// 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 已提交
301

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

H
Haojun Liao 已提交
304 305
  info.tableId = pCheckInfo->tableId;
  taosArrayPush(pNew, &info);
H
Haojun Liao 已提交
306 307 308
  return pNew;
}

309 310
static bool emptyQueryTimewindow(STsdbReadHandle* pTsdbReadHandle) {
  assert(pTsdbReadHandle != NULL);
311

312
  STimeWindow* w = &pTsdbReadHandle->window;
dengyihao's avatar
dengyihao 已提交
313
  bool         asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
314 315 316 317

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

318 319
// 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.
320
static int64_t getEarliestValidTimestamp(STsdb* pTsdb) {
H
Hongze Cheng 已提交
321
  STsdbCfg* pCfg = REPO_CFG(pTsdb);
322 323

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

327
static void setQueryTimewindow(STsdbReadHandle* pTsdbReadHandle, SQueryTableDataCond* pCond) {
328
  pTsdbReadHandle->window = pCond->twindow;
329

330
  bool    updateTs = false;
331 332 333 334
  int64_t startTs = getEarliestValidTimestamp(pTsdbReadHandle->pTsdb);
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
    if (startTs > pTsdbReadHandle->window.skey) {
      pTsdbReadHandle->window.skey = startTs;
335 336
      pCond->twindow.skey = startTs;
      updateTs = true;
337 338
    }
  } else {
339 340
    if (startTs > pTsdbReadHandle->window.ekey) {
      pTsdbReadHandle->window.ekey = startTs;
341 342
      pCond->twindow.ekey = startTs;
      updateTs = true;
343 344 345
    }
  }

346
  if (updateTs) {
H
Haojun Liao 已提交
347 348 349
    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);
350
  }
351 352
}

C
Cary Xu 已提交
353 354 355 356 357 358 359 360 361
static STsdb* getTsdbByRetentions(SVnode* pVnode, TSKEY winSKey, SRetention* retentions) {
  if (vnodeIsRollup(pVnode)) {
    // for(int32_t i=0; i< TSDB_; ) {
      
    // }
  }
  return pVnode->pTsdb;
}

362
static STsdbReadHandle* tsdbQueryTablesImpl(SVnode* pVnode, SQueryTableDataCond* pCond, uint64_t qId, uint64_t taskId) {
wafwerar's avatar
wafwerar 已提交
363
  STsdbReadHandle* pReadHandle = taosMemoryCalloc(1, sizeof(STsdbReadHandle));
364
  if (pReadHandle == NULL) {
365
    goto _end;
366
  }
H
Haojun Liao 已提交
367

C
Cary Xu 已提交
368 369
  STsdb* pTsdb = getTsdbByRetentions(pVnode, pCond->twindow.skey, pVnode->config.tsdbCfg.retentions);

dengyihao's avatar
dengyihao 已提交
370
  pReadHandle->order = pCond->order;
C
Cary Xu 已提交
371
  pReadHandle->pTsdb = pTsdb;
dengyihao's avatar
dengyihao 已提交
372 373 374 375 376 377
  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;
378
  pReadHandle->locateStart = false;
dengyihao's avatar
dengyihao 已提交
379
  pReadHandle->loadType = pCond->type;
380

dengyihao's avatar
dengyihao 已提交
381
  pReadHandle->outputCapacity = 4096;  //((STsdb*)tsdb)->config.maxRowsPerFileBlock;
382 383 384
  pReadHandle->loadExternalRow = pCond->loadExternalRows;
  pReadHandle->currentLoadExternalRows = pCond->loadExternalRows;

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

C
Cary Xu 已提交
389
  if (tsdbInitReadH(&pReadHandle->rhelper, pReadHandle->pTsdb) != 0) {
390
    goto _end;
B
Bomin Zhang 已提交
391
  }
H
Haojun Liao 已提交
392

393 394
  assert(pCond != NULL);
  setQueryTimewindow(pReadHandle, pCond);
395

396 397
  if (pCond->numOfCols > 0) {
    // allocate buffer in order to load data blocks from file
398 399
    pReadHandle->suppInfo.pstatis = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnDataAgg));
    if (pReadHandle->suppInfo.pstatis == NULL) {
400
      goto _end;
401
    }
H
Haojun Liao 已提交
402

403
    // todo: use list instead of array?
404 405
    pReadHandle->pColumns = taosArrayInit(pCond->numOfCols, sizeof(SColumnInfoData));
    if (pReadHandle->pColumns == NULL) {
406
      goto _end;
407
    }
H
Haojun Liao 已提交
408

409 410 411
    for (int32_t i = 0; i < pCond->numOfCols; ++i) {
      SColumnInfoData colInfo = {{0}, 0};
      colInfo.info = pCond->colList[i];
H
Haojun Liao 已提交
412

413
      int32_t code = colInfoDataEnsureCapacity(&colInfo, 0, pReadHandle->outputCapacity);
414
      if (code != TSDB_CODE_SUCCESS) {
415
        goto _end;
416
      }
417

418
      taosArrayPush(pReadHandle->pColumns, &colInfo);
B
Bomin Zhang 已提交
419
    }
H
Haojun Liao 已提交
420

421 422 423
    pReadHandle->suppInfo.defaultLoadColumn = getDefaultLoadColumns(pReadHandle, true);
    pReadHandle->suppInfo.slotIds = taosMemoryMalloc(sizeof(int32_t) * taosArrayGetSize(pReadHandle->suppInfo.defaultLoadColumn));
    pReadHandle->suppInfo.plist = taosMemoryCalloc(taosArrayGetSize(pReadHandle->suppInfo.defaultLoadColumn), POINTER_BYTES);
H
Haojun Liao 已提交
424
  }
425

C
Cary Xu 已提交
426
  pReadHandle->pDataCols = tdNewDataCols(1000, pVnode->config.tsdbCfg.maxRows);
427
  if (pReadHandle->pDataCols == NULL) {
H
Haojun Liao 已提交
428
    tsdbError("%p failed to malloc buf for pDataCols, %s", pReadHandle, pReadHandle->idStr);
H
Haojun Liao 已提交
429
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
430
    goto _end;
H
hjxilinx 已提交
431
  }
432

433 434
  tsdbInitDataBlockLoadInfo(&pReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pReadHandle->compBlockLoadInfo);
435

H
Haojun Liao 已提交
436
  return (tsdbReaderT)pReadHandle;
437

dengyihao's avatar
dengyihao 已提交
438
_end:
439
  tsdbCleanupReadHandle(pReadHandle);
440
  terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
441
  return NULL;
H
hjxilinx 已提交
442 443
}

444
tsdbReaderT* tsdbQueryTables(SVnode* pVnode, SQueryTableDataCond* pCond, STableGroupInfo* groupList, uint64_t qId,
dengyihao's avatar
dengyihao 已提交
445
                             uint64_t taskId) {
446 447

  STsdbReadHandle* pTsdbReadHandle = tsdbQueryTablesImpl(pVnode, pCond, qId, taskId);
448
  if (pTsdbReadHandle == NULL) {
449 450 451
    return NULL;
  }

452
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
453
    return (tsdbReaderT*)pTsdbReadHandle;
454
  }
H
Haojun Liao 已提交
455 456

  // todo apply the lastkey of table check to avoid to load header file
457
  pTsdbReadHandle->pTableCheckInfo = createCheckInfoFromTableGroup(pTsdbReadHandle, groupList);
458
  if (pTsdbReadHandle->pTableCheckInfo == NULL) {
dengyihao's avatar
dengyihao 已提交
459
    //    tsdbCleanupReadHandle(pTsdbReadHandle);
H
Haojun Liao 已提交
460 461 462 463
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    return NULL;
  }

464
  STableCheckInfo *pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, 0);
465

466
  pTsdbReadHandle->pSchema = metaGetTbTSchema(pVnode->pMeta, pCheckInfo->tableId, 0);
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
  int32_t numOfCols = taosArrayGetSize(pTsdbReadHandle->suppInfo.defaultLoadColumn);
  int16_t* ids = pTsdbReadHandle->suppInfo.defaultLoadColumn->pData;

  STSchema* pSchema = pTsdbReadHandle->pSchema;

  int32_t i = 0, j = 0;
  while(i < numOfCols && j < pSchema->numOfCols) {
    if (ids[i] == pSchema->columns[j].colId) {
      pTsdbReadHandle->suppInfo.slotIds[i] = j;
      i++;
      j++;
    } else if (ids[i] > pSchema->columns[j].colId) {
      j++;
    } else {
      //    tsdbCleanupReadHandle(pTsdbReadHandle);
      terrno = TSDB_CODE_INVALID_PARA;
      return NULL;
    }
  }
486

dengyihao's avatar
dengyihao 已提交
487 488 489
  tsdbDebug("%p total numOfTable:%" PRIzu " in this query, group %" PRIzu " %s", pTsdbReadHandle,
            taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo), taosArrayGetSize(groupList->pGroupList),
            pTsdbReadHandle->idStr);
490

dengyihao's avatar
dengyihao 已提交
491
  return (tsdbReaderT)pTsdbReadHandle;
H
Haojun Liao 已提交
492 493
}

494
void tsdbResetReadHandle(tsdbReaderT queryHandle, SQueryTableDataCond* pCond) {
495
  STsdbReadHandle* pTsdbReadHandle = queryHandle;
H
Haojun Liao 已提交
496

497 498 499
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
    if (pCond->order != pTsdbReadHandle->order) {
      pTsdbReadHandle->order = pCond->order;
wafwerar's avatar
wafwerar 已提交
500
      TSWAP(pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey);
501 502 503 504 505
    }

    return;
  }

dengyihao's avatar
dengyihao 已提交
506 507 508 509 510 511 512
  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
513 514
  pTsdbReadHandle->locateStart = false;
  pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
H
Haojun Liao 已提交
515 516

  if (ASCENDING_TRAVERSE(pCond->order)) {
517
    assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
518
  } else {
519
    assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
520 521 522
  }

  // allocate buffer in order to load data blocks from file
523 524
  memset(pTsdbReadHandle->suppInfo.pstatis, 0, sizeof(SColumnDataAgg));
  memset(pTsdbReadHandle->suppInfo.plist, 0, POINTER_BYTES);
H
Haojun Liao 已提交
525

526 527
  tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
H
Haojun Liao 已提交
528

529
  resetCheckInfo(pTsdbReadHandle);
H
Haojun Liao 已提交
530 531
}

532
void tsdbResetQueryHandleForNewTable(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, STableGroupInfo* groupList) {
533
  STsdbReadHandle* pTsdbReadHandle = queryHandle;
H
Haojun Liao 已提交
534

dengyihao's avatar
dengyihao 已提交
535 536 537 538 539 540 541
  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
542 543
  pTsdbReadHandle->locateStart = false;
  pTsdbReadHandle->loadExternalRow = pCond->loadExternalRows;
H
Haojun Liao 已提交
544 545

  if (ASCENDING_TRAVERSE(pCond->order)) {
546
    assert(pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
547
  } else {
548
    assert(pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
549 550 551
  }

  // allocate buffer in order to load data blocks from file
552 553
  memset(pTsdbReadHandle->suppInfo.pstatis, 0, sizeof(SColumnDataAgg));
  memset(pTsdbReadHandle->suppInfo.plist, 0, POINTER_BYTES);
H
Haojun Liao 已提交
554

555 556
  tsdbInitDataBlockLoadInfo(&pTsdbReadHandle->dataBlockLoadInfo);
  tsdbInitCompBlockLoadInfo(&pTsdbReadHandle->compBlockLoadInfo);
H
Haojun Liao 已提交
557

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

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

dengyihao's avatar
dengyihao 已提交
563 564
  pTsdbReadHandle->pTableCheckInfo = NULL;  // createCheckInfoFromTableGroup(pTsdbReadHandle, groupList, pMeta,
                                            // &pTable);
565
  if (pTsdbReadHandle->pTableCheckInfo == NULL) {
dengyihao's avatar
dengyihao 已提交
566
    //    tsdbCleanupReadHandle(pTsdbReadHandle);
H
Haojun Liao 已提交
567 568
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
  }
H
Haojun Liao 已提交
569

dengyihao's avatar
dengyihao 已提交
570 571
  //  pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
  //  pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
H
Haojun Liao 已提交
572 573
}

574
tsdbReaderT tsdbQueryLastRow(SVnode* pVnode, SQueryTableDataCond* pCond, STableGroupInfo* groupList, uint64_t qId,
dengyihao's avatar
dengyihao 已提交
575
                             uint64_t taskId) {
576
  pCond->twindow = updateLastrowForEachGroup(groupList);
H
Haojun Liao 已提交
577 578 579 580 581 582

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

583
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbQueryTables(pVnode, pCond, groupList, qId, taskId);
584
  if (pTsdbReadHandle == NULL) {
585 586 587
    return NULL;
  }

588
  int32_t code = checkForCachedLastRow(pTsdbReadHandle, groupList);
dengyihao's avatar
dengyihao 已提交
589
  if (code != TSDB_CODE_SUCCESS) {  // set the numOfTables to be 0
H
Haojun Liao 已提交
590 591 592
    terrno = code;
    return NULL;
  }
H
Haojun Liao 已提交
593 594

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

599
  return pTsdbReadHandle;
D
init  
dapan1121 已提交
600 601
}

602
#if 0
603 604
tsdbReaderT tsdbQueryCacheLastT(STsdb *tsdb, SQueryTableDataCond *pCond, STableGroupInfo *groupList, uint64_t qId, STsdbMemTable* pMemRef) {
  STsdbReadHandle *pTsdbReadHandle = (STsdbReadHandle*) tsdbQueryTablesT(tsdb, pCond, groupList, qId, pMemRef);
605
  if (pTsdbReadHandle == NULL) {
606 607 608
    return NULL;
  }

609
  int32_t code = checkForCachedLast(pTsdbReadHandle);
D
init  
dapan1121 已提交
610 611 612 613 614
  if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0
    terrno = code;
    return NULL;
  }

615 616
  if (pTsdbReadHandle->cachelastrow) {
    pTsdbReadHandle->type = TSDB_QUERY_TYPE_LAST;
D
fix bug  
dapan1121 已提交
617
  }
D
init  
dapan1121 已提交
618
  
619
  return pTsdbReadHandle;
H
hjxilinx 已提交
620 621
}

622
#endif
dengyihao's avatar
dengyihao 已提交
623
SArray* tsdbGetQueriedTableList(tsdbReaderT* pHandle) {
624
  assert(pHandle != NULL);
H
Haojun Liao 已提交
625

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

dengyihao's avatar
dengyihao 已提交
628
  size_t  size = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
629
  SArray* res = taosArrayInit(size, POINTER_BYTES);
630 631 632
  return res;
}

H
Haojun Liao 已提交
633 634 635 636 637
// 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 已提交
638
  STableGroupInfo* pNew = taosMemoryCalloc(1, sizeof(STableGroupInfo));
Y
yihaoDeng 已提交
639
  pNew->pGroupList = taosArrayInit(numOfGroup, POINTER_BYTES);
H
Haojun Liao 已提交
640

dengyihao's avatar
dengyihao 已提交
641
  for (int32_t i = 0; i < numOfGroup; ++i) {
H
Haojun Liao 已提交
642
    SArray* oneGroup = taosArrayGetP(pGroupList->pGroupList, i);
dengyihao's avatar
dengyihao 已提交
643
    size_t  numOfTables = taosArrayGetSize(oneGroup);
H
Haojun Liao 已提交
644 645 646 647

    SArray* px = taosArrayInit(4, sizeof(STableKeyInfo));
    for (int32_t j = 0; j < numOfTables; ++j) {
      STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(oneGroup, j);
dengyihao's avatar
dengyihao 已提交
648 649 650 651 652
      //      if (window->skey <= pInfo->lastKey && ((STable*)pInfo->pTable)->lastKey != TSKEY_INITIAL_VAL) {
      //        taosArrayPush(px, pInfo);
      //        pNew->numOfTables += 1;
      //        break;
      //      }
H
Haojun Liao 已提交
653 654 655 656 657 658 659 660 661 662 663 664 665
    }

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

  return pNew;
}

666
tsdbReaderT tsdbQueryRowsInExternalWindow(SVnode* pVnode, SQueryTableDataCond* pCond, STableGroupInfo* groupList,
667
                                          uint64_t qId, uint64_t taskId) {
H
Haojun Liao 已提交
668 669
  STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);

670 671 672 673 674 675 676 677 678 679 680 681
  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;
    }
  }

682
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)tsdbQueryTables(pVnode, pCond, pNew, qId, taskId);
683 684
  pTsdbReadHandle->loadExternalRow = true;
  pTsdbReadHandle->currentLoadExternalRows = true;
685

686
  return pTsdbReadHandle;
687 688
}

689
static bool initTableMemIterator(STsdbReadHandle* pHandle, STableCheckInfo* pCheckInfo) {
690
  if (pCheckInfo->initBuf) {
691 692
    return true;
  }
H
Haojun Liao 已提交
693

694
  pCheckInfo->initBuf = true;
695
  int32_t order = pHandle->order;
H
Haojun Liao 已提交
696

697 698 699
  STbData** pMem = NULL;
  STbData** pIMem = NULL;

700
  TSKEY tLastKey = keyToTkey(pCheckInfo->lastKey);
701 702 703
  if (pHandle->pTsdb->mem != NULL) {
    pMem = taosHashGet(pHandle->pTsdb->mem->pHashIdx, &pCheckInfo->tableId, sizeof(pCheckInfo->tableId));
    if (pMem != NULL) {
H
Haojun Liao 已提交
704
      pCheckInfo->iter =
705
          tSkipListCreateIterFromVal((*pMem)->pData, (const char*)&tLastKey, TSDB_DATA_TYPE_TIMESTAMP, order);
H
Haojun Liao 已提交
706
    }
707
  }
H
Haojun Liao 已提交
708

709 710 711
  if (pHandle->pTsdb->imem != NULL) {
    pIMem = taosHashGet(pHandle->pTsdb->imem->pHashIdx, &pCheckInfo->tableId, sizeof(pCheckInfo->tableId));
    if (pIMem != NULL) {
H
Haojun Liao 已提交
712
      pCheckInfo->iiter =
713
          tSkipListCreateIterFromVal((*pIMem)->pData, (const char*)&tLastKey, TSDB_DATA_TYPE_TIMESTAMP, order);
H
Haojun Liao 已提交
714
    }
715
  }
H
Haojun Liao 已提交
716

717 718 719 720
  // both iterators are NULL, no data in buffer right now
  if (pCheckInfo->iter == NULL && pCheckInfo->iiter == NULL) {
    return false;
  }
H
Haojun Liao 已提交
721

dengyihao's avatar
dengyihao 已提交
722
  bool memEmpty = (pCheckInfo->iter == NULL) || (pCheckInfo->iter != NULL && !tSkipListIterNext(pCheckInfo->iter));
723
  bool imemEmpty = (pCheckInfo->iiter == NULL) || (pCheckInfo->iiter != NULL && !tSkipListIterNext(pCheckInfo->iiter));
dengyihao's avatar
dengyihao 已提交
724
  if (memEmpty && imemEmpty) {  // buffer is empty
725 726
    return false;
  }
H
Haojun Liao 已提交
727

728 729 730
  if (!memEmpty) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    assert(node != NULL);
H
Haojun Liao 已提交
731

H
Haojun Liao 已提交
732 733
    STSRow* row = (STSRow*)SL_GET_NODE_DATA(node);
    TSKEY   key = TD_ROW_KEY(row);  // first timestamp in buffer
734
    tsdbDebug("%p uid:%" PRId64 ", check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
dengyihao's avatar
dengyihao 已提交
735 736 737
              "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
              pHandle, pCheckInfo->tableId, key, order, (*pMem)->keyMin, (*pMem)->keyMax, pCheckInfo->lastKey,
              (*pMem)->nrows, pHandle->idStr);
H
Haojun Liao 已提交
738 739 740 741 742 743 744

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

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

749 750 751
  if (!imemEmpty) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
    assert(node != NULL);
H
Haojun Liao 已提交
752

H
Haojun Liao 已提交
753 754
    STSRow* row = (STSRow*)SL_GET_NODE_DATA(node);
    TSKEY   key = TD_ROW_KEY(row);  // first timestamp in buffer
755
    tsdbDebug("%p uid:%" PRId64 ", check data in imem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
dengyihao's avatar
dengyihao 已提交
756 757 758
              "-%" PRId64 ", lastKey:%" PRId64 ", numOfRows:%" PRId64 ", %s",
              pHandle, pCheckInfo->tableId, key, order, (*pIMem)->keyMin, (*pIMem)->keyMax, pCheckInfo->lastKey,
              (*pIMem)->nrows, pHandle->idStr);
H
Haojun Liao 已提交
759 760 761 762 763 764

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

769 770 771
  return true;
}

H
Haojun Liao 已提交
772 773 774 775 776
static void destroyTableMemIterator(STableCheckInfo* pCheckInfo) {
  tSkipListDestroyIter(pCheckInfo->iter);
  tSkipListDestroyIter(pCheckInfo->iiter);
}

777
static TSKEY extractFirstTraverseKey(STableCheckInfo* pCheckInfo, int32_t order, int32_t update) {
H
Haojun Liao 已提交
778
  STSRow *rmem = NULL, *rimem = NULL;
779 780 781
  if (pCheckInfo->iter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    if (node != NULL) {
H
Haojun Liao 已提交
782
      rmem = (STSRow*)SL_GET_NODE_DATA(node);
783 784 785 786 787 788
    }
  }

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

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

  if (rmem != NULL && rimem == NULL) {
    pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
H
Haojun Liao 已提交
799
    return TD_ROW_KEY(rmem);
800 801 802 803
  }

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

H
Haojun Liao 已提交
807 808
  TSKEY r1 = TD_ROW_KEY(rmem);
  TSKEY r2 = TD_ROW_KEY(rimem);
809 810

  if (r1 == r2) {
dengyihao's avatar
dengyihao 已提交
811
    if (update == TD_ROW_DISCARD_UPDATE) {
812 813
      pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
      tSkipListIterNext(pCheckInfo->iter);
dengyihao's avatar
dengyihao 已提交
814
    } else if (update == TD_ROW_OVERWRITE_UPDATE) {
815 816 817 818 819 820 821 822 823
      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 已提交
824
  } else {
825 826 827 828 829
    pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
    return r2;
  }
}

H
Haojun Liao 已提交
830 831
static STSRow* getSRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order, int32_t update, STSRow** extraRow) {
  STSRow *rmem = NULL, *rimem = NULL;
H
Haojun Liao 已提交
832 833 834
  if (pCheckInfo->iter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
    if (node != NULL) {
H
Haojun Liao 已提交
835
      rmem = (STSRow*)SL_GET_NODE_DATA(node);
H
Haojun Liao 已提交
836 837
    }
  }
838

H
Haojun Liao 已提交
839 840 841
  if (pCheckInfo->iiter) {
    SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
    if (node != NULL) {
H
Haojun Liao 已提交
842
      rimem = (STSRow*)SL_GET_NODE_DATA(node);
H
Haojun Liao 已提交
843 844
    }
  }
845

H
Haojun Liao 已提交
846 847
  if (rmem == NULL && rimem == NULL) {
    return NULL;
H
Haojun Liao 已提交
848
  }
849

H
Haojun Liao 已提交
850
  if (rmem != NULL && rimem == NULL) {
H
Haojun Liao 已提交
851 852 853
    pCheckInfo->chosen = 0;
    return rmem;
  }
854

H
Haojun Liao 已提交
855
  if (rmem == NULL && rimem != NULL) {
H
Haojun Liao 已提交
856 857 858
    pCheckInfo->chosen = 1;
    return rimem;
  }
859

H
Haojun Liao 已提交
860 861
  TSKEY r1 = TD_ROW_KEY(rmem);
  TSKEY r2 = TD_ROW_KEY(rimem);
H
Haojun Liao 已提交
862

863 864
  if (r1 == r2) {
    if (update == TD_ROW_DISCARD_UPDATE) {
H
TD-1439  
Hongze Cheng 已提交
865
      tSkipListIterNext(pCheckInfo->iter);
866
      pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
TD-1439  
Hongze Cheng 已提交
867
      return rimem;
dengyihao's avatar
dengyihao 已提交
868
    } else if (update == TD_ROW_OVERWRITE_UPDATE) {
H
TD-1439  
Hongze Cheng 已提交
869
      tSkipListIterNext(pCheckInfo->iiter);
870 871 872 873
      pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
      return rmem;
    } else {
      pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
H
Haojun Liao 已提交
874
      *extraRow = rimem;
H
TD-1439  
Hongze Cheng 已提交
875 876
      return rmem;
    }
H
Haojun Liao 已提交
877 878 879
  } else {
    if (ASCENDING_TRAVERSE(order)) {
      if (r1 < r2) {
880
        pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
H
Haojun Liao 已提交
881 882
        return rmem;
      } else {
883
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
884 885 886 887
        return rimem;
      }
    } else {
      if (r1 < r2) {
888
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
889 890
        return rimem;
      } else {
891
        pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
H
Haojun Liao 已提交
892 893 894 895
        return rmem;
      }
    }
  }
H
Haojun Liao 已提交
896 897
}

898
static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
H
Haojun Liao 已提交
899
  bool hasNext = false;
900
  if (pCheckInfo->chosen == CHECKINFO_CHOSEN_MEM) {
H
Haojun Liao 已提交
901 902 903
    if (pCheckInfo->iter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iter);
    }
904

H
Haojun Liao 已提交
905 906 907
    if (hasNext) {
      return hasNext;
    }
908

H
Haojun Liao 已提交
909 910 911
    if (pCheckInfo->iiter != NULL) {
      return tSkipListIterGet(pCheckInfo->iiter) != NULL;
    }
dengyihao's avatar
dengyihao 已提交
912
  } else if (pCheckInfo->chosen == CHECKINFO_CHOSEN_IMEM) {
913 914 915
    if (pCheckInfo->iiter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iiter);
    }
916

917 918 919
    if (hasNext) {
      return hasNext;
    }
920

921 922
    if (pCheckInfo->iter != NULL) {
      return tSkipListIterGet(pCheckInfo->iter) != NULL;
H
Haojun Liao 已提交
923
    }
924 925 926 927 928 929 930
  } else {
    if (pCheckInfo->iter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iter);
    }
    if (pCheckInfo->iiter != NULL) {
      hasNext = tSkipListIterNext(pCheckInfo->iiter) || hasNext;
    }
H
Haojun Liao 已提交
931
  }
932

H
Haojun Liao 已提交
933 934 935
  return hasNext;
}

936
static bool hasMoreDataInCache(STsdbReadHandle* pHandle) {
H
Hongze Cheng 已提交
937
  STsdbCfg* pCfg = REPO_CFG(pHandle->pTsdb);
dengyihao's avatar
dengyihao 已提交
938
  size_t    size = taosArrayGetSize(pHandle->pTableCheckInfo);
939
  assert(pHandle->activeIndex < size && pHandle->activeIndex >= 0 && size >= 1);
D
dapan1121 已提交
940
  pHandle->cur.fid = INT32_MIN;
H
Haojun Liao 已提交
941

942
  STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
H
Haojun Liao 已提交
943 944 945 946
  if (!pCheckInfo->initBuf) {
    initTableMemIterator(pHandle, pCheckInfo);
  }

H
Haojun Liao 已提交
947
  STSRow* row = getSRowInTableMem(pCheckInfo, pHandle->order, pCfg->update, NULL);
H
Haojun Liao 已提交
948
  if (row == NULL) {
949 950
    return false;
  }
951

H
Haojun Liao 已提交
952
  pCheckInfo->lastKey = TD_ROW_KEY(row);  // first timestamp in buffer
dengyihao's avatar
dengyihao 已提交
953 954
  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 已提交
955

956
  // all data in mem are checked already.
957 958
  if ((pCheckInfo->lastKey > pHandle->window.ekey && ASCENDING_TRAVERSE(pHandle->order)) ||
      (pCheckInfo->lastKey < pHandle->window.ekey && !ASCENDING_TRAVERSE(pHandle->order))) {
959 960
    return false;
  }
H
Haojun Liao 已提交
961

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

966 967 968 969
  // update the last key value
  pCheckInfo->lastKey = win->ekey + step;
  pHandle->cur.lastKey = win->ekey + step;
  pHandle->cur.mixBlock = true;
970

971
  if (!ASCENDING_TRAVERSE(pHandle->order)) {
wafwerar's avatar
wafwerar 已提交
972
    TSWAP(win->skey, win->ekey);
973
  }
H
Haojun Liao 已提交
974

975
  return true;
976
}
H
hjxilinx 已提交
977

978 979
static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precision) {
  assert(precision >= TSDB_TIME_PRECISION_MICRO || precision <= TSDB_TIME_PRECISION_NANO);
980 981 982
  if (key == TSKEY_INITIAL_VAL) {
    return INT32_MIN;
  }
H
Haojun Liao 已提交
983

D
dapan1121 已提交
984
  if (key < 0) {
985
    key -= (daysPerFile * tsTickPerDay[precision]);
D
dapan1121 已提交
986
  }
dengyihao's avatar
dengyihao 已提交
987

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

993
  if (fid > 0L && fid > INT32_MAX) {
994 995
    fid = INT32_MAX;
  }
H
Haojun Liao 已提交
996

S
TD-1057  
Shengliang Guan 已提交
997
  return (int32_t)fid;
998 999
}

H
refact  
Hongze Cheng 已提交
1000
static int32_t binarySearchForBlock(SBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) {
1001 1002
  int32_t firstSlot = 0;
  int32_t lastSlot = numOfBlocks - 1;
H
Haojun Liao 已提交
1003

1004
  int32_t midSlot = firstSlot;
H
Haojun Liao 已提交
1005

1006 1007 1008
  while (1) {
    numOfBlocks = lastSlot - firstSlot + 1;
    midSlot = (firstSlot + (numOfBlocks >> 1));
H
Haojun Liao 已提交
1009

1010
    if (numOfBlocks == 1) break;
H
Haojun Liao 已提交
1011

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
    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 已提交
1023

1024 1025
  return midSlot;
}
1026

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

1030
  STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, index);
H
Haojun Liao 已提交
1031
  pCheckInfo->numOfBlocks = 0;
1032

H
Haojun Liao 已提交
1033
  STable table = {.uid = pCheckInfo->tableId, .tid = pCheckInfo->tableId};
1034
  table.pSchema = pTsdbReadHandle->pSchema;
H
Haojun Liao 已提交
1035 1036

  if (tsdbSetReadTable(&pTsdbReadHandle->rhelper, &table) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1037 1038 1039
    code = terrno;
    return code;
  }
1040

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

H
Haojun Liao 已提交
1043
  // no data block in this file, try next file
1044
  if (compIndex == NULL || compIndex->uid != pCheckInfo->tableId) {
H
Haojun Liao 已提交
1045 1046
    return 0;  // no data blocks in the file belongs to pCheckInfo->pTable
  }
1047

H
Haojun Liao 已提交
1048 1049 1050
  if (pCheckInfo->compSize < (int32_t)compIndex->len) {
    assert(compIndex->len > 0);

wafwerar's avatar
wafwerar 已提交
1051
    char* t = taosMemoryRealloc(pCheckInfo->pCompInfo, compIndex->len);
H
Haojun Liao 已提交
1052 1053 1054 1055
    if (t == NULL) {
      terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
      code = TSDB_CODE_TDB_OUT_OF_MEMORY;
      return code;
1056 1057
    }

H
Haojun Liao 已提交
1058 1059 1060
    pCheckInfo->pCompInfo = (SBlockInfo*)t;
    pCheckInfo->compSize = compIndex->len;
  }
1061

1062
  if (tsdbLoadBlockInfo(&(pTsdbReadHandle->rhelper), (void*)(pCheckInfo->pCompInfo)) < 0) {
H
Hongze Cheng 已提交
1063 1064
    return terrno;
  }
H
Haojun Liao 已提交
1065
  SBlockInfo* pCompInfo = pCheckInfo->pCompInfo;
1066

H
Haojun Liao 已提交
1067
  TSKEY s = TSKEY_INITIAL_VAL, e = TSKEY_INITIAL_VAL;
1068

1069
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
dengyihao's avatar
dengyihao 已提交
1070 1071
    assert(pCheckInfo->lastKey <= pTsdbReadHandle->window.ekey &&
           pTsdbReadHandle->window.skey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1072
  } else {
dengyihao's avatar
dengyihao 已提交
1073 1074
    assert(pCheckInfo->lastKey >= pTsdbReadHandle->window.ekey &&
           pTsdbReadHandle->window.skey >= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1075
  }
1076

dengyihao's avatar
dengyihao 已提交
1077 1078
  s = TMIN(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
  e = TMAX(pCheckInfo->lastKey, pTsdbReadHandle->window.ekey);
1079

H
Haojun Liao 已提交
1080 1081 1082
  // 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 已提交
1083

H
Haojun Liao 已提交
1084 1085 1086
  if (s > pCompInfo->blocks[start].keyLast) {
    return 0;
  }
1087

H
Haojun Liao 已提交
1088 1089 1090 1091
  // todo speedup the procedure of located end block
  while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) {
    end += 1;
  }
1092

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

H
Haojun Liao 已提交
1095 1096 1097
  if (start > 0) {
    memmove(pCompInfo->blocks, &pCompInfo->blocks[start], pCheckInfo->numOfBlocks * sizeof(SBlock));
  }
1098

H
Haojun Liao 已提交
1099 1100 1101
  (*numOfBlocks) += pCheckInfo->numOfBlocks;
  return 0;
}
1102

1103
static int32_t getFileCompInfo(STsdbReadHandle* pTsdbReadHandle, int32_t* numOfBlocks) {
H
Haojun Liao 已提交
1104 1105 1106 1107
  // load all the comp offset value for all tables in this file
  int32_t code = TSDB_CODE_SUCCESS;
  *numOfBlocks = 0;

1108
  pTsdbReadHandle->cost.headFileLoad += 1;
1109 1110
  int64_t s = taosGetTimestampUs();

H
Haojun Liao 已提交
1111
  size_t numOfTables = 0;
1112 1113 1114 1115
  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);
1116

H
Haojun Liao 已提交
1117
    for (int32_t i = 0; i < numOfTables; ++i) {
1118
      code = loadBlockInfo(pTsdbReadHandle, i, numOfBlocks);
H
Haojun Liao 已提交
1119
      if (code != TSDB_CODE_SUCCESS) {
1120 1121
        int64_t e = taosGetTimestampUs();

1122
        pTsdbReadHandle->cost.headFileLoadTime += (e - s);
H
Haojun Liao 已提交
1123 1124 1125 1126 1127
        return code;
      }
    }
  } else {
    assert(0);
1128
  }
1129

1130
  int64_t e = taosGetTimestampUs();
1131
  pTsdbReadHandle->cost.headFileLoadTime += (e - s);
H
Haojun Liao 已提交
1132
  return code;
1133 1134
}

dengyihao's avatar
dengyihao 已提交
1135 1136
static int32_t doLoadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
                                   int32_t slotIndex) {
H
Haojun Liao 已提交
1137
  int64_t st = taosGetTimestampUs();
1138

1139
  int32_t   code = tdInitDataCols(pTsdbReadHandle->pDataCols, pTsdbReadHandle->pSchema);
H
Haojun Liao 已提交
1140
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1141
    tsdbError("%p failed to malloc buf for pDataCols, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1142 1143 1144 1145
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }

1146
  code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[0], pTsdbReadHandle->pSchema);
H
Haojun Liao 已提交
1147
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1148
    tsdbError("%p failed to malloc buf for rhelper.pDataCols[0], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1149 1150 1151 1152
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }

1153
  code = tdInitDataCols(pTsdbReadHandle->rhelper.pDCols[1], pTsdbReadHandle->pSchema);
H
Haojun Liao 已提交
1154
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1155
    tsdbError("%p failed to malloc buf for rhelper.pDataCols[1], %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1156 1157 1158
    terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
    goto _error;
  }
1159

1160
  int16_t* colIds = pTsdbReadHandle->suppInfo.defaultLoadColumn->pData;
H
Haojun Liao 已提交
1161

dengyihao's avatar
dengyihao 已提交
1162 1163
  int32_t ret = tsdbLoadBlockDataCols(&(pTsdbReadHandle->rhelper), pBlock, pCheckInfo->pCompInfo, colIds,
                                      (int)(QH_GET_NUM_OF_COLS(pTsdbReadHandle)), true);
H
Haojun Liao 已提交
1164
  if (ret != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1165 1166 1167
    int32_t c = terrno;
    assert(c != TSDB_CODE_SUCCESS);
    goto _error;
H
Haojun Liao 已提交
1168
  }
1169

1170
  SDataBlockLoadInfo* pBlockLoadInfo = &pTsdbReadHandle->dataBlockLoadInfo;
1171

1172 1173
  pBlockLoadInfo->fileGroup = pTsdbReadHandle->pFileGroup;
  pBlockLoadInfo->slot = pTsdbReadHandle->cur.slot;
H
Haojun Liao 已提交
1174
  pBlockLoadInfo->uid = pCheckInfo->tableId;
1175

1176
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
1177
  assert(pCols->numOfRows != 0 && pCols->numOfRows <= pBlock->numOfRows);
1178

1179
  pBlock->numOfRows = pCols->numOfRows;
H
Haojun Liao 已提交
1180

1181
  // Convert from TKEY to TSKEY for primary timestamp column if current block has timestamp before 1970-01-01T00:00:00Z
dengyihao's avatar
dengyihao 已提交
1182
  if (pBlock->keyFirst < 0 && colIds[0] == PRIMARYKEY_TIMESTAMP_COL_ID) {
1183
    int64_t* src = pCols->cols[0].pData;
dengyihao's avatar
dengyihao 已提交
1184
    for (int32_t i = 0; i < pBlock->numOfRows; ++i) {
1185 1186 1187 1188
      src[i] = tdGetKey(src[i]);
    }
  }

H
Haojun Liao 已提交
1189
  int64_t elapsedTime = (taosGetTimestampUs() - st);
1190
  pTsdbReadHandle->cost.blockLoadTime += elapsedTime;
1191

dengyihao's avatar
dengyihao 已提交
1192 1193 1194 1195
  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 已提交
1196
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
1197 1198 1199 1200

_error:
  pBlock->numOfRows = 0;

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

1206
static int32_t getEndPosInDataBlock(STsdbReadHandle* pTsdbReadHandle, SDataBlockInfo* pBlockInfo);
dengyihao's avatar
dengyihao 已提交
1207 1208 1209 1210 1211 1212 1213 1214
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) {
1215
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Hongze Cheng 已提交
1216
  STsdbCfg*      pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
1217
  SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
1218
  TSKEY          key;
dengyihao's avatar
dengyihao 已提交
1219
  int32_t        code = TSDB_CODE_SUCCESS;
1220

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

1224
  key = extractFirstTraverseKey(pCheckInfo, pTsdbReadHandle->order, pCfg->update);
1225

H
Haojun Liao 已提交
1226
  if (key != TSKEY_INITIAL_VAL) {
dengyihao's avatar
dengyihao 已提交
1227
    tsdbDebug("%p key in mem:%" PRId64 ", %s", pTsdbReadHandle, key, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1228
  } else {
H
Haojun Liao 已提交
1229
    tsdbDebug("%p no data in mem, %s", pTsdbReadHandle, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1230
  }
H
Haojun Liao 已提交
1231

1232 1233
  bool ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);

1234 1235 1236 1237
  if ((ascScan && (key != TSKEY_INITIAL_VAL && key <= binfo.window.ekey)) ||
      (!ascScan && (key != TSKEY_INITIAL_VAL && key >= binfo.window.skey))) {
    if ((ascScan && (key != TSKEY_INITIAL_VAL && key < binfo.window.skey)) ||
        (!ascScan && (key != TSKEY_INITIAL_VAL && key > binfo.window.ekey))) {
H
Haojun Liao 已提交
1238
      // do not load file block into buffer
1239
      int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
H
Haojun Liao 已提交
1240

dengyihao's avatar
dengyihao 已提交
1241 1242 1243 1244
      TSKEY maxKey =
          ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? (binfo.window.skey - step) : (binfo.window.ekey - step);
      cur->rows =
          tsdbReadRowsFromCache(pCheckInfo, maxKey, pTsdbReadHandle->outputCapacity, &cur->win, pTsdbReadHandle);
1245
      pTsdbReadHandle->realNumOfRows = cur->rows;
H
Haojun Liao 已提交
1246 1247 1248

      // update the last key value
      pCheckInfo->lastKey = cur->win.ekey + step;
1249
      if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
wafwerar's avatar
wafwerar 已提交
1250
        TSWAP(cur->win.skey, cur->win.ekey);
H
Haojun Liao 已提交
1251
      }
H
Haojun Liao 已提交
1252

H
Haojun Liao 已提交
1253 1254
      cur->mixBlock = true;
      cur->blockCompleted = false;
H
Haojun Liao 已提交
1255
      return code;
H
Haojun Liao 已提交
1256
    }
H
Haojun Liao 已提交
1257

1258
    // return error, add test cases
1259
    if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1260
      return code;
1261 1262
    }

1263
    doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1264
  } else {
1265 1266 1267 1268 1269 1270
    /*
     * 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
     */
1271 1272
    assert(pTsdbReadHandle->outputCapacity >= binfo.rows);
    int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &binfo);
1273

1274 1275
    if ((cur->pos == 0 && endPos == binfo.rows - 1 && ascScan) ||
        (cur->pos == (binfo.rows - 1) && endPos == 0 && (!ascScan))) {
1276
      pTsdbReadHandle->realNumOfRows = binfo.rows;
1277 1278

      cur->rows = binfo.rows;
dengyihao's avatar
dengyihao 已提交
1279
      cur->win = binfo.window;
1280
      cur->mixBlock = false;
H
Haojun Liao 已提交
1281 1282
      cur->blockCompleted = true;

1283
      if (ascScan) {
H
Haojun Liao 已提交
1284 1285 1286 1287 1288 1289
        cur->lastKey = binfo.window.ekey + 1;
        cur->pos = binfo.rows;
      } else {
        cur->lastKey = binfo.window.skey - 1;
        cur->pos = -1;
      }
dengyihao's avatar
dengyihao 已提交
1290
    } else {  // partially copy to dest buffer
1291
      copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &binfo, endPos);
1292 1293
      cur->mixBlock = true;
    }
1294

H
Haojun Liao 已提交
1295
    assert(cur->blockCompleted);
H
Haojun Liao 已提交
1296
    if (cur->rows == binfo.rows) {
dengyihao's avatar
dengyihao 已提交
1297
      tsdbDebug("%p whole file block qualified, brange:%" PRId64 "-%" PRId64 ", rows:%d, lastKey:%" PRId64 ", %s",
H
Haojun Liao 已提交
1298
                pTsdbReadHandle, cur->win.skey, cur->win.ekey, cur->rows, cur->lastKey, pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
1299
    } else {
dengyihao's avatar
dengyihao 已提交
1300 1301 1302 1303
      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 已提交
1304
    }
1305
  }
H
Haojun Liao 已提交
1306 1307

  return code;
1308 1309
}

1310 1311
static int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);

dengyihao's avatar
dengyihao 已提交
1312 1313
static int32_t loadFileDataBlock(STsdbReadHandle* pTsdbReadHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo,
                                 bool* exists) {
1314
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
dengyihao's avatar
dengyihao 已提交
1315 1316
  int32_t        code = TSDB_CODE_SUCCESS;
  bool           asc = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
1317

1318
  if (asc) {
H
Haojun Liao 已提交
1319
    // query ended in/started from current block
1320 1321
    if (pTsdbReadHandle->window.ekey < pBlock->keyLast || pCheckInfo->lastKey > pBlock->keyFirst) {
      if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1322 1323
        *exists = false;
        return code;
1324
      }
1325

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

1329 1330
      if (pCheckInfo->lastKey > pBlock->keyFirst) {
        cur->pos =
1331
            binarySearchForKey(pTSCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
1332 1333 1334
      } else {
        cur->pos = 0;
      }
H
Haojun Liao 已提交
1335

H
Haojun Liao 已提交
1336
      assert(pCheckInfo->lastKey <= pBlock->keyLast);
1337
      doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1338
    } else {  // the whole block is loaded in to buffer
dengyihao's avatar
dengyihao 已提交
1339
      cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
1340
      code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
H
[td-32]  
hjxilinx 已提交
1341
    }
dengyihao's avatar
dengyihao 已提交
1342
  } else {  // desc order, query ended in current block
1343 1344
    if (pTsdbReadHandle->window.ekey > pBlock->keyFirst || pCheckInfo->lastKey < pBlock->keyLast) {
      if ((code = doLoadFileDataBlock(pTsdbReadHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1345 1346
        *exists = false;
        return code;
1347
      }
H
Haojun Liao 已提交
1348

1349
      SDataCols* pTsCol = pTsdbReadHandle->rhelper.pDCols[0];
1350
      if (pCheckInfo->lastKey < pBlock->keyLast) {
dengyihao's avatar
dengyihao 已提交
1351 1352
        cur->pos =
            binarySearchForKey(pTsCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pTsdbReadHandle->order);
1353
      } else {
H
Haojun Liao 已提交
1354
        cur->pos = pBlock->numOfRows - 1;
1355
      }
H
Haojun Liao 已提交
1356

H
Haojun Liao 已提交
1357
      assert(pCheckInfo->lastKey >= pBlock->keyFirst);
1358
      doMergeTwoLevelData(pTsdbReadHandle, pCheckInfo, pBlock);
1359
    } else {
dengyihao's avatar
dengyihao 已提交
1360
      cur->pos = asc ? 0 : (pBlock->numOfRows - 1);
1361
      code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlock, pCheckInfo);
H
[td-32]  
hjxilinx 已提交
1362
    }
1363
  }
1364

1365
  *exists = pTsdbReadHandle->realNumOfRows > 0;
H
Haojun Liao 已提交
1366
  return code;
H
[td-32]  
hjxilinx 已提交
1367 1368
}

1369
static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
1370
  int    firstPos, lastPos, midPos = -1;
H
Haojun Liao 已提交
1371
  int    numOfRows;
1372 1373
  TSKEY* keyList;

1374
  assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC);
H
Haojun Liao 已提交
1375

1376
  if (num <= 0) return -1;
1377 1378

  keyList = (TSKEY*)pValue;
1379 1380
  firstPos = 0;
  lastPos = num - 1;
1381

1382
  if (order == TSDB_ORDER_DESC) {
1383 1384 1385 1386 1387
    // 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;
1388

H
Haojun Liao 已提交
1389 1390
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1391

1392 1393 1394 1395 1396 1397 1398 1399
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
1400

1401 1402 1403 1404 1405
  } 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;
1406

1407 1408 1409 1410 1411 1412 1413
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
1414

H
Haojun Liao 已提交
1415 1416
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
1417

1418 1419 1420 1421 1422 1423 1424 1425 1426
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
1427

1428 1429 1430
  return midPos;
}

dengyihao's avatar
dengyihao 已提交
1431 1432
static int32_t doCopyRowsFromFileBlock(STsdbReadHandle* pTsdbReadHandle, int32_t capacity, int32_t numOfRows,
                                       int32_t start, int32_t end) {
1433
  SDataCols* pCols = pTsdbReadHandle->rhelper.pDCols[0];
dengyihao's avatar
dengyihao 已提交
1434
  TSKEY*     tsArray = pCols->cols[0].pData;
H
Haojun Liao 已提交
1435

1436
  int32_t num = end - start + 1;
H
Haojun Liao 已提交
1437 1438 1439 1440 1441 1442
  assert(num >= 0);

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

1443 1444
  bool    ascScan = ASCENDING_TRAVERSE(pTsdbReadHandle->order);
  int32_t trueStart = ascScan ? start : end;
1445
  int32_t trueEnd = ascScan ? end : start;
1446 1447
  int32_t step = ascScan ? 1 : -1;

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

dengyihao's avatar
dengyihao 已提交
1450
  // data in buffer has greater timestamp, copy data in file block
1451
  int32_t i = 0, j = 0;
dengyihao's avatar
dengyihao 已提交
1452
  while (i < requiredNumOfCols && j < pCols->numOfCols) {
1453
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1454 1455 1456 1457 1458 1459 1460

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

L
Liu Jicong 已提交
1461
    if (!isAllRowsNull(src) && pColInfo->info.colId == src->colId) {
1462
      if (!IS_VAR_DATA_TYPE(pColInfo->info.type)) {  // todo opt performance
dengyihao's avatar
dengyihao 已提交
1463
        //        memmove(pData, (char*)src->pData + bytes * start, bytes * num);
1464
        int32_t rowIndex = numOfRows;
1465
        for (int32_t k = trueStart; ((ascScan && k <= trueEnd) || (!ascScan && k >= trueEnd)); k += step, ++rowIndex) {
1466
          SCellVal sVal = {0};
C
Cary Xu 已提交
1467
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
1468 1469
            TASSERT(0);
          }
1470

1471
          if (sVal.valType == TD_VTYPE_NULL) {
1472
            colDataAppendNULL(pColInfo, rowIndex);
1473
          } else {
1474
            colDataAppend(pColInfo, rowIndex, sVal.val, false);
1475 1476 1477
          }
        }
      } else {  // handle the var-string
1478 1479
        int32_t rowIndex = numOfRows;

1480
        // todo refactor, only copy one-by-one
1481
        for (int32_t k = trueStart; ((ascScan && k <= trueEnd) || (!ascScan && k >= trueEnd)); k += step, ++rowIndex) {
1482
          SCellVal sVal = {0};
dengyihao's avatar
dengyihao 已提交
1483
          if (tdGetColDataOfRow(&sVal, src, k, pCols->bitmapMode) < 0) {
H
Haojun Liao 已提交
1484 1485
            TASSERT(0);
          }
1486

1487
          if (sVal.valType == TD_VTYPE_NULL) {
1488
            colDataAppendNULL(pColInfo, rowIndex);
1489
          } else {
1490
            colDataAppend(pColInfo, rowIndex, sVal.val, false);
1491
          }
1492 1493
        }
      }
1494 1495 1496

      j++;
      i++;
H
Hongze Cheng 已提交
1497
    } else {  // pColInfo->info.colId < src->colId, it is a NULL data
1498
      colDataAppendNNULL(pColInfo, numOfRows, num);
1499
      i++;
1500 1501
    }
  }
1502

dengyihao's avatar
dengyihao 已提交
1503
  while (i < requiredNumOfCols) {  // the remain columns are all null data
1504
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1505
    colDataAppendNNULL(pColInfo, numOfRows, num);
1506
    i++;
1507
  }
H
Haojun Liao 已提交
1508

1509 1510
  pTsdbReadHandle->cur.win.ekey = tsArray[trueEnd];
  pTsdbReadHandle->cur.lastKey = tsArray[trueEnd] + step;
1511

1512
  return numOfRows + num;
1513 1514
}

H
Haojun Liao 已提交
1515
// TODO fix bug for reverse copy data problem
1516
// Note: row1 always has high priority
H
Haojun Liao 已提交
1517 1518 1519 1520
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 已提交
1521 1522 1523 1524 1525 1526 1527 1528 1529
  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 已提交
1530
  SCellVal sVal = {0};
1531

H
Haojun Liao 已提交
1532
  // the schema version info is embeded in STSRow
1533 1534 1535
  int32_t numOfColsOfRow1 = 0;

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

C
Cary Xu 已提交
1539 1540 1541 1542
#ifdef TD_DEBUG_PRINT_ROW
  tdSRowPrint(row1, pSchema1, __func__);
#endif

dengyihao's avatar
dengyihao 已提交
1543
  if (isRow1DataRow) {
1544
    numOfColsOfRow1 = schemaNCols(pSchema1);
H
Haojun Liao 已提交
1545
  } else {
H
Haojun Liao 已提交
1546
    numOfColsOfRow1 = tdRowGetNCols(row1);
D
fix bug  
dapan1121 已提交
1547
  }
1548

1549
  int32_t numOfColsOfRow2 = 0;
dengyihao's avatar
dengyihao 已提交
1550
  if (row2) {
H
Haojun Liao 已提交
1551
    isRow2DataRow = TD_IS_TP_ROW(row2);
1552
    if (pSchema2 == NULL) {
H
Hongze Cheng 已提交
1553
      pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row2));
1554
    }
dengyihao's avatar
dengyihao 已提交
1555
    if (isRow2DataRow) {
1556 1557
      numOfColsOfRow2 = schemaNCols(pSchema2);
    } else {
H
Haojun Liao 已提交
1558
      numOfColsOfRow2 = tdRowGetNCols(row2);
1559 1560
    }
  }
C
Cary Xu 已提交
1561

1562
  int32_t i = 0, j = 0, k = 0;
dengyihao's avatar
dengyihao 已提交
1563
  while (i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) {
1564
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
1565 1566

    int32_t colIdOfRow1;
dengyihao's avatar
dengyihao 已提交
1567
    if (j >= numOfColsOfRow1) {
1568
      colIdOfRow1 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1569
    } else if (isRow1DataRow) {
1570 1571
      colIdOfRow1 = pSchema1->columns[j].colId;
    } else {
C
Cary Xu 已提交
1572
      colIdOfRow1 = tdKvRowColIdAt(row1, j);
1573 1574 1575
    }

    int32_t colIdOfRow2;
dengyihao's avatar
dengyihao 已提交
1576
    if (k >= numOfColsOfRow2) {
1577
      colIdOfRow2 = INT32_MAX;
dengyihao's avatar
dengyihao 已提交
1578
    } else if (isRow2DataRow) {
1579 1580
      colIdOfRow2 = pSchema2->columns[k].colId;
    } else {
C
Cary Xu 已提交
1581
      colIdOfRow2 = tdKvRowColIdAt(row2, k);
1582 1583
    }

dengyihao's avatar
dengyihao 已提交
1584 1585
    if (colIdOfRow1 == colIdOfRow2) {
      if (colIdOfRow1 < pColInfo->info.colId) {
C
Cary Xu 已提交
1586
        j++;
1587
        k++;
C
Cary Xu 已提交
1588 1589
        continue;
      }
1590 1591 1592 1593
      row = row1;
      pSchema = pSchema1;
      isChosenRowDataRow = isRow1DataRow;
      chosen_itr = j;
dengyihao's avatar
dengyihao 已提交
1594 1595
    } else if (colIdOfRow1 < colIdOfRow2) {
      if (colIdOfRow1 < pColInfo->info.colId) {
1596 1597
        j++;
        continue;
C
Cary Xu 已提交
1598
      }
1599 1600 1601 1602 1603
      row = row1;
      pSchema = pSchema1;
      isChosenRowDataRow = isRow1DataRow;
      chosen_itr = j;
    } else {
dengyihao's avatar
dengyihao 已提交
1604
      if (colIdOfRow2 < pColInfo->info.colId) {
1605 1606 1607 1608 1609 1610 1611 1612
        k++;
        continue;
      }
      row = row2;
      pSchema = pSchema2;
      chosen_itr = k;
      isChosenRowDataRow = isRow2DataRow;
    }
dengyihao's avatar
dengyihao 已提交
1613
    if (isChosenRowDataRow) {
1614 1615
      colId = pSchema->columns[chosen_itr].colId;
      offset = pSchema->columns[chosen_itr].offset;
C
Cary Xu 已提交
1616 1617
      // TODO: use STSRowIter
      tdSTpRowGetVal(row, colId, pSchema->columns[chosen_itr].type, pSchema->flen, offset, chosen_itr - 1, &sVal);
1618
    } else {
C
Cary Xu 已提交
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
      // 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);
      }
1629 1630 1631
    }

    if (colId == pColInfo->info.colId) {
H
Haojun Liao 已提交
1632
      if (tdValTypeIsNorm(sVal.valType)) {
H
Haojun Liao 已提交
1633
        colDataAppend(pColInfo, numOfRows, sVal.val, false);
H
Haojun Liao 已提交
1634
      } else if (forceSetNull) {
H
Haojun Liao 已提交
1635
        colDataAppend(pColInfo, numOfRows, NULL, true);
1636
      }
H
Haojun Liao 已提交
1637

1638
      i++;
C
Cary Xu 已提交
1639

dengyihao's avatar
dengyihao 已提交
1640
      if (row == row1) {
C
Cary Xu 已提交
1641
        j++;
1642 1643 1644 1645
      } else {
        k++;
      }
    } else {
dengyihao's avatar
dengyihao 已提交
1646
      if (forceSetNull) {
H
Haojun Liao 已提交
1647
        colDataAppend(pColInfo, numOfRows, NULL, true);
C
Cary Xu 已提交
1648
      }
1649
      i++;
1650
    }
1651
  }
1652

dengyihao's avatar
dengyihao 已提交
1653 1654
  if (forceSetNull) {
    while (i < numOfCols) {  // the remain columns are all null data
1655
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
H
Haojun Liao 已提交
1656
      colDataAppend(pColInfo, numOfRows, NULL, true);
1657
      i++;
1658 1659
    }
  }
H
Haojun Liao 已提交
1660
#endif
1661
}
1662

1663 1664
static void moveDataToFront(STsdbReadHandle* pTsdbReadHandle, int32_t numOfRows, int32_t numOfCols) {
  if (numOfRows == 0 || ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1665 1666 1667 1668
    return;
  }

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
1669 1670
  if (numOfRows < pTsdbReadHandle->outputCapacity) {
    int32_t emptySize = pTsdbReadHandle->outputCapacity - numOfRows;
dengyihao's avatar
dengyihao 已提交
1671
    for (int32_t i = 0; i < numOfCols; ++i) {
1672
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
1673 1674
      memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes,
              numOfRows * pColInfo->info.bytes);
1675 1676 1677 1678
    }
  }
}

dengyihao's avatar
dengyihao 已提交
1679 1680
static void getQualifiedRowsPos(STsdbReadHandle* pTsdbReadHandle, int32_t startPos, int32_t endPos,
                                int32_t numOfExisted, int32_t* start, int32_t* end) {
1681 1682
  *start = -1;

1683
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
1684
    int32_t remain = endPos - startPos + 1;
1685 1686
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = (pTsdbReadHandle->outputCapacity - numOfExisted) + startPos - 1;
H
Haojun Liao 已提交
1687 1688
    } else {
      *end = endPos;
1689 1690 1691 1692 1693
    }

    *start = startPos;
  } else {
    int32_t remain = (startPos - endPos) + 1;
1694 1695
    if (remain + numOfExisted > pTsdbReadHandle->outputCapacity) {
      *end = startPos + 1 - (pTsdbReadHandle->outputCapacity - numOfExisted);
H
Haojun Liao 已提交
1696 1697
    } else {
      *end = endPos;
1698 1699 1700 1701 1702 1703 1704
    }

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

dengyihao's avatar
dengyihao 已提交
1705 1706
static void updateInfoAfterMerge(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, int32_t numOfRows,
                                 int32_t endPos) {
1707
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
1708 1709

  pCheckInfo->lastKey = cur->lastKey;
1710
  pTsdbReadHandle->realNumOfRows = numOfRows;
1711 1712 1713 1714
  cur->rows = numOfRows;
  cur->pos = endPos;
}

1715 1716
static void doCheckGeneratedBlockRange(STsdbReadHandle* pTsdbReadHandle) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
1717 1718

  if (cur->rows > 0) {
1719 1720
    if (ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
      assert(cur->win.skey >= pTsdbReadHandle->window.skey && cur->win.ekey <= pTsdbReadHandle->window.ekey);
H
Haojun Liao 已提交
1721
    } else {
1722
      assert(cur->win.skey >= pTsdbReadHandle->window.ekey && cur->win.ekey <= pTsdbReadHandle->window.skey);
H
Haojun Liao 已提交
1723 1724
    }

1725
    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, 0);
dengyihao's avatar
dengyihao 已提交
1726 1727
    assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] &&
           cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows - 1]);
H
Haojun Liao 已提交
1728
  } else {
1729
    cur->win = pTsdbReadHandle->window;
H
Haojun Liao 已提交
1730

dengyihao's avatar
dengyihao 已提交
1731
    int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1732
    cur->lastKey = pTsdbReadHandle->window.ekey + step;
H
Haojun Liao 已提交
1733 1734 1735
  }
}

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

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

dengyihao's avatar
dengyihao 已提交
1743
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1744
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
H
Haojun Liao 已提交
1745 1746 1747 1748 1749 1750

  int32_t pos = cur->pos;

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

1751
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
wafwerar's avatar
wafwerar 已提交
1752
    TSWAP(start, end);
H
Haojun Liao 已提交
1753 1754
  }

1755 1756
  assert(pTsdbReadHandle->outputCapacity >= (end - start + 1));
  int32_t numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, 0, start, end);
H
Haojun Liao 已提交
1757 1758

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

  // if the buffer is not full in case of descending order query, move the data in the front of the buffer
1765
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
H
Haojun Liao 已提交
1766 1767 1768

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

dengyihao's avatar
dengyihao 已提交
1772 1773 1774
  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 已提交
1775 1776
}

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

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

1785
  if (ASCENDING_TRAVERSE(pTsdbReadHandle->order) && pTsdbReadHandle->window.ekey >= pBlockInfo->window.ekey) {
H
Haojun Liao 已提交
1786 1787
    endPos = pBlockInfo->rows - 1;
    cur->mixBlock = (cur->pos != 0);
1788
  } else if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order) && pTsdbReadHandle->window.ekey <= pBlockInfo->window.skey) {
H
Haojun Liao 已提交
1789 1790 1791 1792
    endPos = 0;
    cur->mixBlock = (cur->pos != pBlockInfo->rows - 1);
  } else {
    assert(pCols->numOfRows > 0);
1793
    endPos = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, pTsdbReadHandle->window.ekey, order);
H
Haojun Liao 已提交
1794 1795 1796 1797 1798 1799
    cur->mixBlock = true;
  }

  return endPos;
}

H
[td-32]  
hjxilinx 已提交
1800 1801
// 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
1802 1803
static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInfo* pCheckInfo, SBlock* pBlock) {
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
1804
  SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
H
Hongze Cheng 已提交
1805
  STsdbCfg*      pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
1806

1807
  initTableMemIterator(pTsdbReadHandle, pCheckInfo);
1808

1809 1810
  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 已提交
1811
         cur->pos >= 0 && cur->pos < pBlock->numOfRows);
H
Haojun Liao 已提交
1812

1813
  TSKEY* tsArray = pCols->cols[0].pData;
dengyihao's avatar
dengyihao 已提交
1814 1815
  assert(pCols->numOfRows == pBlock->numOfRows && tsArray[0] == pBlock->keyFirst &&
         tsArray[pBlock->numOfRows - 1] == pBlock->keyLast);
1816 1817

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

dengyihao's avatar
dengyihao 已提交
1820
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
1821
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
1822

H
Haojun Liao 已提交
1823
  STable* pTable = NULL;
1824
  int32_t endPos = getEndPosInDataBlock(pTsdbReadHandle, &blockInfo);
H
Haojun Liao 已提交
1825

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

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

dengyihao's avatar
dengyihao 已提交
1834 1835
  int16_t   rv1 = -1;
  int16_t   rv2 = -1;
1836 1837
  STSchema* pSchema1 = NULL;
  STSchema* pSchema2 = NULL;
D
fix bug  
dapan1121 已提交
1838

H
Haojun Liao 已提交
1839 1840
  int32_t pos = cur->pos;
  cur->win = TSWINDOW_INITIALIZER;
1841

1842 1843
  // no data in buffer, load data from file directly
  if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) {
1844
    copyAllRemainRowsFromFileBlock(pTsdbReadHandle, pCheckInfo, &blockInfo, endPos);
1845
    return;
1846
  } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) {
1847 1848
    SSkipListNode* node = NULL;
    do {
H
Haojun Liao 已提交
1849 1850
      STSRow* row2 = NULL;
      STSRow* row1 = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, &row2);
1851
      if (row1 == NULL) {
H
[td-32]  
hjxilinx 已提交
1852
        break;
1853
      }
1854

H
Haojun Liao 已提交
1855
      TSKEY key = TD_ROW_KEY(row1);
1856 1857
      if ((key > pTsdbReadHandle->window.ekey && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          (key < pTsdbReadHandle->window.ekey && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1858 1859 1860
        break;
      }

dengyihao's avatar
dengyihao 已提交
1861 1862 1863 1864
      if (((pos > endPos || tsArray[pos] > pTsdbReadHandle->window.ekey) &&
           ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          ((pos < endPos || tsArray[pos] < pTsdbReadHandle->window.ekey) &&
           !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1865 1866 1867
        break;
      }

1868 1869
      if ((key < tsArray[pos] && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
          (key > tsArray[pos] && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
H
Haojun Liao 已提交
1870
        if (rv1 != TD_ROW_SVER(row1)) {
dengyihao's avatar
dengyihao 已提交
1871
          //          pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
H
Haojun Liao 已提交
1872
          rv1 = TD_ROW_SVER(row1);
C
Cary Xu 已提交
1873
        }
dengyihao's avatar
dengyihao 已提交
1874 1875
        if (row2 && rv2 != TD_ROW_SVER(row2)) {
          //          pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
H
Haojun Liao 已提交
1876
          rv2 = TD_ROW_SVER(row2);
1877
        }
dengyihao's avatar
dengyihao 已提交
1878 1879 1880

        mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                           pCheckInfo->tableId, pSchema1, pSchema2, true);
1881 1882 1883 1884
        numOfRows += 1;
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = key;
        }
1885

1886
        cur->win.ekey = key;
dengyihao's avatar
dengyihao 已提交
1887
        cur->lastKey = key + step;
1888 1889
        cur->mixBlock = true;

1890
        moveToNextRowInMem(pCheckInfo);
1891
      } else if (key == tsArray[pos]) {  // data in buffer has the same timestamp of data in file block, ignore it
H
TD-1439  
Hongze Cheng 已提交
1892
        if (pCfg->update) {
dengyihao's avatar
dengyihao 已提交
1893
          if (pCfg->update == TD_ROW_PARTIAL_UPDATE) {
1894
            doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, pos, pos);
D
fix bug  
dapan1121 已提交
1895
          }
H
Haojun Liao 已提交
1896
          if (rv1 != TD_ROW_SVER(row1)) {
dengyihao's avatar
dengyihao 已提交
1897
            //            pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
H
Haojun Liao 已提交
1898
            rv1 = TD_ROW_SVER(row1);
1899
          }
dengyihao's avatar
dengyihao 已提交
1900 1901
          if (row2 && rv2 != TD_ROW_SVER(row2)) {
            //            pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
H
Haojun Liao 已提交
1902
            rv2 = TD_ROW_SVER(row2);
1903
          }
dengyihao's avatar
dengyihao 已提交
1904

1905
          bool forceSetNull = pCfg->update != TD_ROW_PARTIAL_UPDATE;
dengyihao's avatar
dengyihao 已提交
1906 1907
          mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, row1, row2, numOfCols,
                             pCheckInfo->tableId, pSchema1, pSchema2, forceSetNull);
H
TD-1439  
Hongze Cheng 已提交
1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921
          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);
        }
1922
      } else if ((key > tsArray[pos] && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
dengyihao's avatar
dengyihao 已提交
1923
                 (key < tsArray[pos] && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1924 1925 1926
        if (cur->win.skey == TSKEY_INITIAL_VAL) {
          cur->win.skey = tsArray[pos];
        }
1927

1928
        int32_t end = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, key, order);
1929 1930
        assert(end != -1);

dengyihao's avatar
dengyihao 已提交
1931
        if (tsArray[end] == key) {  // the value of key in cache equals to the end timestamp value, ignore it
1932
          if (pCfg->update == TD_ROW_DISCARD_UPDATE) {
H
Hongze Cheng 已提交
1933 1934 1935 1936
            moveToNextRowInMem(pCheckInfo);
          } else {
            end -= step;
          }
H
Haojun Liao 已提交
1937
        }
1938

1939
        int32_t qstart = 0, qend = 0;
1940
        getQualifiedRowsPos(pTsdbReadHandle, pos, end, numOfRows, &qstart, &qend);
1941

1942
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, qstart, qend);
1943 1944
        pos += (qend - qstart + 1) * step;

dengyihao's avatar
dengyihao 已提交
1945 1946
        cur->win.ekey = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? tsArray[qend] : tsArray[qstart];
        cur->lastKey = cur->win.ekey + step;
1947
      }
1948
    } while (numOfRows < pTsdbReadHandle->outputCapacity);
H
Haojun Liao 已提交
1949

1950
    if (numOfRows < pTsdbReadHandle->outputCapacity) {
H
Haojun Liao 已提交
1951 1952 1953 1954
      /**
       * 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.
       */
1955
      if (node == NULL ||
H
Haojun Liao 已提交
1956
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) > pTsdbReadHandle->window.ekey) &&
1957
           ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
H
Haojun Liao 已提交
1958
          ((TD_ROW_KEY((STSRow*)SL_GET_NODE_DATA(node)) < pTsdbReadHandle->window.ekey) &&
1959
           !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
1960 1961 1962 1963 1964
        // 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];
        }

1965
        int32_t start = -1, end = -1;
1966
        getQualifiedRowsPos(pTsdbReadHandle, pos, endPos, numOfRows, &start, &end);
1967

1968
        numOfRows = doCopyRowsFromFileBlock(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, numOfRows, start, end);
1969
        pos += (end - start + 1) * step;
1970

dengyihao's avatar
dengyihao 已提交
1971 1972
        cur->win.ekey = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? tsArray[end] : tsArray[start];
        cur->lastKey = cur->win.ekey + step;
H
Haojun Liao 已提交
1973
        cur->mixBlock = true;
1974
      }
1975 1976
    }
  }
H
Haojun Liao 已提交
1977 1978

  cur->blockCompleted =
1979 1980
      (((pos > endPos || cur->lastKey > pTsdbReadHandle->window.ekey) && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
       ((pos < endPos || cur->lastKey < pTsdbReadHandle->window.ekey) && !ASCENDING_TRAVERSE(pTsdbReadHandle->order)));
1981

1982
  if (!ASCENDING_TRAVERSE(pTsdbReadHandle->order)) {
wafwerar's avatar
wafwerar 已提交
1983
    TSWAP(cur->win.skey, cur->win.ekey);
1984
  }
1985

1986 1987 1988
  moveDataToFront(pTsdbReadHandle, numOfRows, numOfCols);
  updateInfoAfterMerge(pTsdbReadHandle, pCheckInfo, numOfRows, pos);
  doCheckGeneratedBlockRange(pTsdbReadHandle);
H
Haojun Liao 已提交
1989

dengyihao's avatar
dengyihao 已提交
1990 1991 1992
  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);
1993 1994
}

1995
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
H
[td-32]  
hjxilinx 已提交
1996
  int    firstPos, lastPos, midPos = -1;
H
Haojun Liao 已提交
1997
  int    numOfRows;
1998 1999
  TSKEY* keyList;

H
[td-32]  
hjxilinx 已提交
2000
  if (num <= 0) return -1;
2001 2002

  keyList = (TSKEY*)pValue;
H
[td-32]  
hjxilinx 已提交
2003 2004
  firstPos = 0;
  lastPos = num - 1;
2005

2006
  if (order == TSDB_ORDER_DESC) {
H
[td-32]  
hjxilinx 已提交
2007 2008 2009 2010 2011
    // 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;
2012

H
Haojun Liao 已提交
2013 2014
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2015

H
[td-32]  
hjxilinx 已提交
2016 2017 2018 2019 2020 2021 2022 2023
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
2024

H
[td-32]  
hjxilinx 已提交
2025 2026 2027 2028 2029
  } 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;
2030

H
[td-32]  
hjxilinx 已提交
2031 2032 2033 2034 2035 2036 2037
      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }
2038

H
Haojun Liao 已提交
2039 2040
      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;
2041

H
[td-32]  
hjxilinx 已提交
2042 2043 2044 2045 2046 2047 2048 2049 2050
      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }
2051

H
[td-32]  
hjxilinx 已提交
2052 2053 2054
  return midPos;
}

2055
static void cleanBlockOrderSupporter(SBlockOrderSupporter* pSupporter, int32_t numOfTables) {
wafwerar's avatar
wafwerar 已提交
2056 2057
  taosMemoryFreeClear(pSupporter->numOfBlocksPerTable);
  taosMemoryFreeClear(pSupporter->blockIndexArray);
2058 2059

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

wafwerar's avatar
wafwerar 已提交
2064
  taosMemoryFreeClear(pSupporter->pDataBlockInfo);
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075
}

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

2076
  if (leftTableBlockIndex > pSupporter->numOfBlocksPerTable[leftTableIndex]) {
2077 2078
    /* left block is empty */
    return 1;
2079
  } else if (rightTableBlockIndex > pSupporter->numOfBlocksPerTable[rightTableIndex]) {
2080 2081 2082 2083 2084 2085 2086
    /* right block is empty */
    return -1;
  }

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

H
Haojun Liao 已提交
2087
  //    assert(pLeftBlockInfoEx->compBlock->offset != pRightBlockInfoEx->compBlock->offset);
dengyihao's avatar
dengyihao 已提交
2088
#if 0  // TODO: temporarily comment off requested by Dr. Liao
H
Haojun Liao 已提交
2089 2090
  if (pLeftBlockInfoEx->compBlock->offset == pRightBlockInfoEx->compBlock->offset &&
      pLeftBlockInfoEx->compBlock->last == pRightBlockInfoEx->compBlock->last) {
B
Bomin Zhang 已提交
2091
    tsdbError("error in header file, two block with same offset:%" PRId64, (int64_t)pLeftBlockInfoEx->compBlock->offset);
2092
  }
H
Haojun Liao 已提交
2093
#endif
2094

H
Haojun Liao 已提交
2095
  return pLeftBlockInfoEx->compBlock->offset > pRightBlockInfoEx->compBlock->offset ? 1 : -1;
2096 2097
}

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

2101 2102
  if (pTsdbReadHandle->allocSize < size) {
    pTsdbReadHandle->allocSize = (int32_t)size;
wafwerar's avatar
wafwerar 已提交
2103
    char* tmp = taosMemoryRealloc(pTsdbReadHandle->pDataBlockInfo, pTsdbReadHandle->allocSize);
H
Haojun Liao 已提交
2104 2105 2106 2107
    if (tmp == NULL) {
      return TSDB_CODE_TDB_OUT_OF_MEMORY;
    }

dengyihao's avatar
dengyihao 已提交
2108
    pTsdbReadHandle->pDataBlockInfo = (STableBlockInfo*)tmp;
2109 2110
  }

2111
  memset(pTsdbReadHandle->pDataBlockInfo, 0, size);
2112 2113
  *numOfAllocBlocks = numOfBlocks;

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

2117 2118
  SBlockOrderSupporter sup = {0};
  sup.numOfTables = numOfTables;
wafwerar's avatar
wafwerar 已提交
2119 2120 2121
  sup.numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.blockIndexArray = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
  sup.pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
2122

2123
  if (sup.numOfBlocksPerTable == NULL || sup.blockIndexArray == NULL || sup.pDataBlockInfo == NULL) {
2124
    cleanBlockOrderSupporter(&sup, 0);
2125
    return TSDB_CODE_TDB_OUT_OF_MEMORY;
2126
  }
H
Haojun Liao 已提交
2127

2128
  int32_t cnt = 0;
2129
  int32_t numOfQualTables = 0;
H
Haojun Liao 已提交
2130

2131
  for (int32_t j = 0; j < numOfTables; ++j) {
2132
    STableCheckInfo* pTableCheck = (STableCheckInfo*)taosArrayGet(pTsdbReadHandle->pTableCheckInfo, j);
2133 2134 2135
    if (pTableCheck->numOfBlocks <= 0) {
      continue;
    }
H
Haojun Liao 已提交
2136

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

wafwerar's avatar
wafwerar 已提交
2140
    char* buf = taosMemoryMalloc(sizeof(STableBlockInfo) * pTableCheck->numOfBlocks);
2141
    if (buf == NULL) {
2142
      cleanBlockOrderSupporter(&sup, numOfQualTables);
2143
      return TSDB_CODE_TDB_OUT_OF_MEMORY;
2144 2145
    }

2146
    sup.pDataBlockInfo[numOfQualTables] = (STableBlockInfo*)buf;
2147 2148

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

H
Haojun Liao 已提交
2151 2152
      pBlockInfo->compBlock = &pBlock[k];
      pBlockInfo->pTableCheckInfo = pTableCheck;
2153 2154 2155
      cnt++;
    }

2156
    numOfQualTables++;
2157 2158
  }

H
Haojun Liao 已提交
2159
  assert(numOfBlocks == cnt);
2160

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

H
Haojun Liao 已提交
2166
    tsdbDebug("%p create data blocks info struct completed for 1 table, %d blocks not sorted %s", pTsdbReadHandle, cnt,
dengyihao's avatar
dengyihao 已提交
2167
              pTsdbReadHandle->idStr);
H
Haojun Liao 已提交
2168 2169
    return TSDB_CODE_SUCCESS;
  }
2170

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

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

2177
  SMultiwayMergeTreeInfo* pTree = NULL;
dengyihao's avatar
dengyihao 已提交
2178
  uint8_t                 ret = tMergeTreeCreate(&pTree, sup.numOfTables, &sup, dataBlockOrderCompar);
2179 2180
  if (ret != TSDB_CODE_SUCCESS) {
    cleanBlockOrderSupporter(&sup, numOfTables);
2181
    return TSDB_CODE_TDB_OUT_OF_MEMORY;
2182 2183 2184 2185 2186
  }

  int32_t numOfTotal = 0;

  while (numOfTotal < cnt) {
2187
    int32_t pos = tMergeTreeGetChosenIndex(pTree);
2188 2189
    int32_t index = sup.blockIndexArray[pos]++;

H
Haojun Liao 已提交
2190
    STableBlockInfo* pBlocksInfo = sup.pDataBlockInfo[pos];
2191
    pTsdbReadHandle->pDataBlockInfo[numOfTotal++] = pBlocksInfo[index];
2192 2193

    // set data block index overflow, in order to disable the offset comparator
2194 2195
    if (sup.blockIndexArray[pos] >= sup.numOfBlocksPerTable[pos]) {
      sup.blockIndexArray[pos] = sup.numOfBlocksPerTable[pos] + 1;
2196
    }
2197

H
Haojun Liao 已提交
2198
    tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
2199 2200 2201 2202 2203
  }

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

H
Haojun Liao 已提交
2208
  tsdbDebug("%p %d data blocks sort completed, %s", pTsdbReadHandle, cnt, pTsdbReadHandle->idStr);
2209
  cleanBlockOrderSupporter(&sup, numOfTables);
wafwerar's avatar
wafwerar 已提交
2210
  taosMemoryFree(pTree);
2211 2212 2213 2214

  return TSDB_CODE_SUCCESS;
}

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

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

dengyihao's avatar
dengyihao 已提交
2221
  while (1) {
2222
    int32_t code = loadFileDataBlock(pTsdbReadHandle, pNext->compBlock, pNext->pTableCheckInfo, exists);
H
Haojun Liao 已提交
2223 2224 2225 2226
    if (code != TSDB_CODE_SUCCESS || *exists) {
      return code;
    }

2227 2228
    if ((cur->slot == pTsdbReadHandle->numOfBlocks - 1 && ASCENDING_TRAVERSE(pTsdbReadHandle->order)) ||
        (cur->slot == 0 && !ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
H
Haojun Liao 已提交
2229
      // all data blocks in current file has been checked already, try next file if exists
2230
      return getFirstFileDataBlock(pTsdbReadHandle, exists);
H
Haojun Liao 已提交
2231 2232 2233 2234
    } else {  // next block of the same file
      cur->slot += step;
      cur->mixBlock = false;
      cur->blockCompleted = false;
2235
      pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
H
Haojun Liao 已提交
2236 2237 2238 2239
    }
  }
}

2240 2241 2242
static int32_t getFirstFileDataBlock(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  pTsdbReadHandle->numOfBlocks = 0;
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
2243 2244 2245

  int32_t code = TSDB_CODE_SUCCESS;

2246
  int32_t numOfBlocks = 0;
2247
  int32_t numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
2248

H
Hongze Cheng 已提交
2249
  STsdbCfg*   pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
2250 2251
  STimeWindow win = TSWINDOW_INITIALIZER;

H
Hongze Cheng 已提交
2252
  while (true) {
2253
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2254

2255 2256
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2257 2258 2259
      break;
    }

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

    // current file are not overlapped with query time window, ignore remain files
2263 2264 2265
    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 已提交
2266 2267
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
                pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
2268 2269
      pTsdbReadHandle->pFileGroup = NULL;
      assert(pTsdbReadHandle->numOfBlocks == 0);
2270 2271 2272
      break;
    }

2273 2274
    if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2275 2276 2277 2278
      code = terrno;
      break;
    }

2279
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Hongze Cheng 已提交
2280

2281
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Hongze Cheng 已提交
2282 2283 2284 2285
      code = terrno;
      break;
    }

2286
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
2287 2288
      break;
    }
H
Haojun Liao 已提交
2289

H
Haojun Liao 已提交
2290 2291
    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 已提交
2292

2293 2294 2295 2296
    assert(numOfBlocks >= 0);
    if (numOfBlocks == 0) {
      continue;
    }
H
Haojun Liao 已提交
2297

2298
    // todo return error code to query engine
dengyihao's avatar
dengyihao 已提交
2299 2300
    if ((code = createDataBlocksInfo(pTsdbReadHandle, numOfBlocks, &pTsdbReadHandle->numOfBlocks)) !=
        TSDB_CODE_SUCCESS) {
2301 2302
      break;
    }
H
Haojun Liao 已提交
2303

2304 2305
    assert(numOfBlocks >= pTsdbReadHandle->numOfBlocks);
    if (pTsdbReadHandle->numOfBlocks > 0) {
2306 2307 2308
      break;
    }
  }
H
Haojun Liao 已提交
2309

2310
  // no data in file anymore
2311
  if (pTsdbReadHandle->numOfBlocks <= 0 || code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2312
    if (code == TSDB_CODE_SUCCESS) {
2313
      assert(pTsdbReadHandle->pFileGroup == NULL);
H
Haojun Liao 已提交
2314 2315
    }

D
dapan1121 已提交
2316
    cur->fid = INT32_MIN;  // denote that there are no data in file anymore
H
Haojun Liao 已提交
2317 2318
    *exists = false;
    return code;
2319
  }
H
Haojun Liao 已提交
2320

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

2325 2326
  STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
  return getDataBlockRv(pTsdbReadHandle, pBlockInfo, exists);
H
Haojun Liao 已提交
2327 2328 2329 2330 2331 2332 2333
}

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

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

2337 2338
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
  assert(cur->slot < pTsdbReadHandle->numOfBlocks && cur->slot >= 0);
H
Haojun Liao 已提交
2339 2340

  cur->slot += step;
dengyihao's avatar
dengyihao 已提交
2341
  cur->mixBlock = false;
H
Haojun Liao 已提交
2342
  cur->blockCompleted = false;
2343
}
H
Haojun Liao 已提交
2344 2345

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

H
Haojun Liao 已提交
2348
  pTableBlockInfo->totalSize = 0;
2349
  pTableBlockInfo->totalRows = 0;
H
Haojun Liao 已提交
2350

2351
  STsdbFS* pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
2352 2353

  // find the start data block in file
2354
  pTsdbReadHandle->locateStart = true;
H
Hongze Cheng 已提交
2355
  STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
H
refact  
Hongze Cheng 已提交
2356
  int32_t   fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
H
Haojun Liao 已提交
2357 2358

  tsdbRLockFS(pFileHandle);
2359 2360
  tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
  tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Haojun Liao 已提交
2361 2362
  tsdbUnLockFS(pFileHandle);

H
Haojun Liao 已提交
2363
  pTableBlockInfo->numOfFiles += 1;
H
Haojun Liao 已提交
2364

H
Haojun Liao 已提交
2365
  int32_t     code = TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2366
  int32_t     numOfBlocks = 0;
2367
  int32_t     numOfTables = (int32_t)taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
dengyihao's avatar
dengyihao 已提交
2368
  int         defaultRows = 4096;  // TSDB_DEFAULT_BLOCK_ROWS(pCfg->maxRowsPerFileBlock);
H
Haojun Liao 已提交
2369 2370
  STimeWindow win = TSWINDOW_INITIALIZER;

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

H
Haojun Liao 已提交
2373 2374
  while (true) {
    numOfBlocks = 0;
2375
    tsdbRLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2376

2377 2378
    if ((pTsdbReadHandle->pFileGroup = tsdbFSIterNext(&pTsdbReadHandle->fileIter)) == NULL) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2379 2380 2381
      break;
    }

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

    // current file are not overlapped with query time window, ignore remain files
dengyihao's avatar
dengyihao 已提交
2385 2386
    if ((ascTraverse && win.skey > pTsdbReadHandle->window.ekey) ||
        (!ascTraverse && win.ekey < pTsdbReadHandle->window.ekey)) {
2387
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2388 2389
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pTsdbReadHandle,
                pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
2390
      pTsdbReadHandle->pFileGroup = NULL;
H
Haojun Liao 已提交
2391 2392 2393
      break;
    }

H
Haojun Liao 已提交
2394
    pTableBlockInfo->numOfFiles += 1;
2395 2396
    if (tsdbSetAndOpenReadFSet(&pTsdbReadHandle->rhelper, pTsdbReadHandle->pFileGroup) < 0) {
      tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2397 2398 2399 2400
      code = terrno;
      break;
    }

2401
    tsdbUnLockFS(REPO_FS(pTsdbReadHandle->pTsdb));
H
Haojun Liao 已提交
2402

2403
    if (tsdbLoadBlockIdx(&pTsdbReadHandle->rhelper) < 0) {
H
Haojun Liao 已提交
2404 2405 2406 2407
      code = terrno;
      break;
    }

2408
    if ((code = getFileCompInfo(pTsdbReadHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
2409 2410 2411
      break;
    }

H
Haojun Liao 已提交
2412 2413
    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 已提交
2414 2415 2416 2417 2418 2419

    if (numOfBlocks == 0) {
      continue;
    }

    for (int32_t i = 0; i < numOfTables; ++i) {
2420
      STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2421 2422 2423

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

H
Haojun Liao 已提交
2426
        int32_t numOfRows = pBlock[j].numOfRows;
2427
        pTableBlockInfo->totalRows += numOfRows;
H
Haojun Liao 已提交
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
        if (numOfRows > pTableBlockInfo->maxRows) {
          pTableBlockInfo->maxRows = numOfRows;
        }

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

        if (numOfRows < defaultRows) {
          pTableBlockInfo->numOfSmallBlocks += 1;
        }
dengyihao's avatar
dengyihao 已提交
2439 2440 2441
        //        int32_t  stepIndex = (numOfRows-1)/TSDB_BLOCK_DIST_STEP_ROWS;
        //        SFileBlockInfo *blockInfo = (SFileBlockInfo*)taosArrayGet(pTableBlockInfo->dataBlockInfos, stepIndex);
        //        blockInfo->numBlocksOfStep++;
H
Haojun Liao 已提交
2442 2443 2444 2445 2446 2447 2448
      }
    }
  }

  return code;
}

2449 2450 2451
static int32_t getDataBlocksInFiles(STsdbReadHandle* pTsdbReadHandle, bool* exists) {
  STsdbFS*       pFileHandle = REPO_FS(pTsdbReadHandle->pTsdb);
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2452 2453

  // find the start data block in file
2454 2455
  if (!pTsdbReadHandle->locateStart) {
    pTsdbReadHandle->locateStart = true;
H
Hongze Cheng 已提交
2456
    STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
H
refact  
Hongze Cheng 已提交
2457
    int32_t   fid = getFileIdFromKey(pTsdbReadHandle->window.skey, pCfg->days, pCfg->precision);
H
Haojun Liao 已提交
2458

H
Hongze Cheng 已提交
2459
    tsdbRLockFS(pFileHandle);
2460 2461
    tsdbFSIterInit(&pTsdbReadHandle->fileIter, pFileHandle, pTsdbReadHandle->order);
    tsdbFSIterSeek(&pTsdbReadHandle->fileIter, fid);
H
Hongze Cheng 已提交
2462
    tsdbUnLockFS(pFileHandle);
2463

2464
    return getFirstFileDataBlock(pTsdbReadHandle, exists);
2465
  } else {
2466
    // check if current file block is all consumed
2467
    STableBlockInfo* pBlockInfo = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
2468
    STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
H
Haojun Liao 已提交
2469

2470
    // current block is done, try next
H
Haojun Liao 已提交
2471
    if ((!cur->mixBlock) || cur->blockCompleted) {
H
Haojun Liao 已提交
2472
      // all data blocks in current file has been checked already, try next file if exists
2473
    } else {
H
Haojun Liao 已提交
2474 2475
      tsdbDebug("%p continue in current data block, index:%d, pos:%d, %s", pTsdbReadHandle, cur->slot, cur->pos,
                pTsdbReadHandle->idStr);
2476 2477
      int32_t code = handleDataMergeIfNeeded(pTsdbReadHandle, pBlockInfo->compBlock, pCheckInfo);
      *exists = (pTsdbReadHandle->realNumOfRows > 0);
H
Haojun Liao 已提交
2478

H
Haojun Liao 已提交
2479 2480 2481 2482 2483 2484 2485
      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
2486 2487
    if (isEndFileDataBlock(cur, pTsdbReadHandle->numOfBlocks, ASCENDING_TRAVERSE(pTsdbReadHandle->order))) {
      return getFirstFileDataBlock(pTsdbReadHandle, exists);
H
Haojun Liao 已提交
2488
    } else {
2489 2490 2491
      moveToNextDataBlockInCurrentFile(pTsdbReadHandle);
      STableBlockInfo* pNext = &pTsdbReadHandle->pDataBlockInfo[cur->slot];
      return getDataBlockRv(pTsdbReadHandle, pNext, exists);
2492 2493
    }
  }
2494 2495
}

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

2499 2500
  while (pTsdbReadHandle->activeIndex < numOfTables) {
    if (hasMoreDataInCache(pTsdbReadHandle)) {
2501 2502
      return true;
    }
H
Haojun Liao 已提交
2503

2504
    pTsdbReadHandle->activeIndex += 1;
2505
  }
H
Haojun Liao 已提交
2506

2507 2508 2509
  return false;
}

dengyihao's avatar
dengyihao 已提交
2510
// todo not unref yet, since it is not support multi-group interpolation query
H
Haojun Liao 已提交
2511
static UNUSED_FUNC void changeQueryHandleForInterpQuery(tsdbReaderT pHandle) {
H
Haojun Liao 已提交
2512
  // filter the queried time stamp in the first place
dengyihao's avatar
dengyihao 已提交
2513
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
H
Haojun Liao 已提交
2514 2515

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

  int32_t i = 0;
dengyihao's avatar
dengyihao 已提交
2519
  while (i < numOfTables) {
2520
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, i);
H
Haojun Liao 已提交
2521 2522

    // the first qualified table for interpolation query
dengyihao's avatar
dengyihao 已提交
2523 2524 2525 2526
    //    if ((pTsdbReadHandle->window.skey <= pCheckInfo->pTableObj->lastKey) &&
    //        (pCheckInfo->pTableObj->lastKey != TSKEY_INITIAL_VAL)) {
    //      break;
    //    }
H
Haojun Liao 已提交
2527 2528 2529 2530 2531 2532 2533 2534 2535

    i++;
  }

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

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

2539 2540
  info.lastKey = pTsdbReadHandle->window.skey;
  taosArrayPush(pTsdbReadHandle->pTableCheckInfo, &info);
H
Haojun Liao 已提交
2541 2542 2543
}

static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
2544
                                 STsdbReadHandle* pTsdbReadHandle) {
dengyihao's avatar
dengyihao 已提交
2545 2546
  int       numOfRows = 0;
  int32_t   numOfCols = (int32_t)taosArrayGetSize(pTsdbReadHandle->pColumns);
H
Hongze Cheng 已提交
2547
  STsdbCfg* pCfg = REPO_CFG(pTsdbReadHandle->pTsdb);
H
Haojun Liao 已提交
2548 2549
  win->skey = TSKEY_INITIAL_VAL;

dengyihao's avatar
dengyihao 已提交
2550 2551
  int64_t   st = taosGetTimestampUs();
  int16_t   rv = -1;
D
fix bug  
dapan1121 已提交
2552
  STSchema* pSchema = NULL;
H
Haojun Liao 已提交
2553 2554

  do {
H
Haojun Liao 已提交
2555
    STSRow* row = getSRowInTableMem(pCheckInfo, pTsdbReadHandle->order, pCfg->update, NULL);
H
Haojun Liao 已提交
2556 2557 2558 2559
    if (row == NULL) {
      break;
    }

H
Haojun Liao 已提交
2560
    TSKEY key = TD_ROW_KEY(row);
dengyihao's avatar
dengyihao 已提交
2561 2562 2563 2564
    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 已提交
2565 2566 2567 2568 2569 2570 2571 2572 2573

      break;
    }

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

    win->ekey = key;
H
Haojun Liao 已提交
2574
    if (rv != TD_ROW_SVER(row)) {
H
Hongze Cheng 已提交
2575
      pSchema = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), pCheckInfo->tableId, 0);
H
Haojun Liao 已提交
2576
      rv = TD_ROW_SVER(row);
D
fix bug  
dapan1121 已提交
2577
    }
dengyihao's avatar
dengyihao 已提交
2578 2579
    mergeTwoRowFromMem(pTsdbReadHandle, maxRowsToRead, numOfRows, row, NULL, numOfCols, pCheckInfo->tableId, pSchema,
                       NULL, true);
H
Haojun Liao 已提交
2580 2581 2582 2583 2584 2585

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

dengyihao's avatar
dengyihao 已提交
2586
  } while (moveToNextRowInMem(pCheckInfo));
H
Haojun Liao 已提交
2587 2588 2589 2590

  assert(numOfRows <= maxRowsToRead);

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

dengyihao's avatar
dengyihao 已提交
2594
    for (int32_t i = 0; i < numOfCols; ++i) {
2595
      SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
dengyihao's avatar
dengyihao 已提交
2596 2597
      memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes,
              numOfRows * pColInfo->info.bytes);
H
Haojun Liao 已提交
2598 2599 2600 2601
    }
  }

  int64_t elapsedTime = taosGetTimestampUs() - st;
dengyihao's avatar
dengyihao 已提交
2602 2603
  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 已提交
2604 2605 2606 2607

  return numOfRows;
}

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

2611 2612 2613 2614 2615
  while (1) {
    tb_uid_t id = metaCtbCursorNext(pCur);
    if (id == 0) {
      break;
    }
H
Haojun Liao 已提交
2616

2617
    STableKeyInfo info = {.lastKey = TSKEY_INITIAL_VAL, uid = id};
H
Haojun Liao 已提交
2618 2619 2620
    taosArrayPush(list, &info);
  }

2621
  metaCloseCtbCurosr(pCur);
H
Haojun Liao 已提交
2622 2623 2624 2625 2626 2627 2628 2629
  return TSDB_CODE_SUCCESS;
}

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

dengyihao's avatar
dengyihao 已提交
2630 2631 2632 2633 2634 2635
  //  tQueryInfo* pInfo = (tQueryInfo*)param;
  //  if (pInfo->optr != TSDB_RELATION_IN) {
  //    taosMemoryFreeClear(pInfo->q);
  //  } else {
  //    taosHashCleanup((SHashObj *)(pInfo->q));
  //  }
H
Haojun Liao 已提交
2636

wafwerar's avatar
wafwerar 已提交
2637
  taosMemoryFree(param);
H
Haojun Liao 已提交
2638 2639
}

dengyihao's avatar
dengyihao 已提交
2640 2641
#define TSDB_PREV_ROW 0x1
#define TSDB_NEXT_ROW 0x2
2642

dengyihao's avatar
dengyihao 已提交
2643
static bool loadBlockOfActiveTable(STsdbReadHandle* pTsdbReadHandle) {
2644
  if (pTsdbReadHandle->checkFiles) {
H
Haojun Liao 已提交
2645 2646
    // check if the query range overlaps with the file data block
    bool exists = true;
H
Haojun Liao 已提交
2647

2648
    int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
H
Haojun Liao 已提交
2649
    if (code != TSDB_CODE_SUCCESS) {
2650
      pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2651 2652
      return false;
    }
H
Haojun Liao 已提交
2653

H
Haojun Liao 已提交
2654
    if (exists) {
dengyihao's avatar
dengyihao 已提交
2655
      tsdbRetrieveDataBlock((tsdbReaderT*)pTsdbReadHandle, NULL);
2656 2657 2658
      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 已提交
2659 2660
      }

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

2665
    pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2666
  }
H
Haojun Liao 已提交
2667

2668 2669
  if (hasMoreDataInCache(pTsdbReadHandle)) {
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2670 2671
    return true;
  }
H
Haojun Liao 已提交
2672

H
Haojun Liao 已提交
2673
  // current result is empty
dengyihao's avatar
dengyihao 已提交
2674 2675 2676
  if (pTsdbReadHandle->currentLoadExternalRows && pTsdbReadHandle->window.skey == pTsdbReadHandle->window.ekey &&
      pTsdbReadHandle->cur.rows == 0) {
    //    STsdbMemTable* pMemRef = pTsdbReadHandle->pMemTable;
H
Haojun Liao 已提交
2677

dengyihao's avatar
dengyihao 已提交
2678 2679
    //    doGetExternalRow(pTsdbReadHandle, TSDB_PREV_ROW, pMemRef);
    //    doGetExternalRow(pTsdbReadHandle, TSDB_NEXT_ROW, pMemRef);
H
Haojun Liao 已提交
2680

2681
    bool result = tsdbGetExternalRow(pTsdbReadHandle);
H
Haojun Liao 已提交
2682

dengyihao's avatar
dengyihao 已提交
2683 2684
    //    pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
    //    pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
2685
    pTsdbReadHandle->currentLoadExternalRows = false;
H
Haojun Liao 已提交
2686 2687

    return result;
2688
  }
H
Haojun Liao 已提交
2689

H
Haojun Liao 已提交
2690 2691
  return false;
}
2692

2693
static bool loadCachedLastRow(STsdbReadHandle* pTsdbReadHandle) {
H
Haojun Liao 已提交
2694
  // the last row is cached in buffer, return it directly.
2695
  // here note that the pTsdbReadHandle->window must be the TS_INITIALIZER
dengyihao's avatar
dengyihao 已提交
2696
  int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pTsdbReadHandle));
2697
  size_t  numOfTables = taosArrayGetSize(pTsdbReadHandle->pTableCheckInfo);
H
Haojun Liao 已提交
2698 2699
  assert(numOfTables > 0 && numOfCols > 0);

2700
  SQueryFilePos* cur = &pTsdbReadHandle->cur;
2701

dengyihao's avatar
dengyihao 已提交
2702 2703 2704
  STSRow* pRow = NULL;
  TSKEY   key = TSKEY_INITIAL_VAL;
  int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
2705 2706 2707

  if (++pTsdbReadHandle->activeIndex < numOfTables) {
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
dengyihao's avatar
dengyihao 已提交
2708 2709 2710 2711 2712 2713
    //    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 已提交
2714
    taosMemoryFreeClear(pRow);
H
Haojun Liao 已提交
2715

H
Haojun Liao 已提交
2716 2717 2718
    // update the last key value
    pCheckInfo->lastKey = key + step;

dengyihao's avatar
dengyihao 已提交
2719 2720
    cur->rows = 1;  // only one row
    cur->lastKey = key + step;
H
Haojun Liao 已提交
2721 2722 2723 2724 2725
    cur->mixBlock = true;
    cur->win.skey = key;
    cur->win.ekey = key;

    return true;
2726
  }
H
Haojun Liao 已提交
2727

H
Haojun Liao 已提交
2728 2729 2730
  return false;
}

dengyihao's avatar
dengyihao 已提交
2731
// static bool loadCachedLast(STsdbReadHandle* pTsdbReadHandle) {
2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750
//  // 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 已提交
2751 2752
//      tsdbWarn("no last cached for table %s, uid:%" PRIu64 ",tid:%d", pTable->name->data, pTable->uid,
//      pTable->tableId); continue;
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 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882
//    }
//
//    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 已提交
2883 2884 2885
  assert(numOfTables > 0);

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

dengyihao's avatar
dengyihao 已提交
2887
  while (pTsdbReadHandle->activeIndex < numOfTables) {
2888
    if (loadBlockOfActiveTable(pTsdbReadHandle)) {
H
Haojun Liao 已提交
2889 2890 2891
      return true;
    }

2892
    STableCheckInfo* pCheckInfo = taosArrayGet(pTsdbReadHandle->pTableCheckInfo, pTsdbReadHandle->activeIndex);
H
Haojun Liao 已提交
2893 2894
    pCheckInfo->numOfBlocks = 0;

2895 2896
    pTsdbReadHandle->activeIndex += 1;
    pTsdbReadHandle->locateStart = false;
dengyihao's avatar
dengyihao 已提交
2897 2898
    pTsdbReadHandle->checkFiles = true;
    pTsdbReadHandle->cur.rows = 0;
2899
    pTsdbReadHandle->currentLoadExternalRows = pTsdbReadHandle->loadExternalRow;
H
Haojun Liao 已提交
2900 2901 2902 2903

    terrno = TSDB_CODE_SUCCESS;

    int64_t elapsedTime = taosGetTimestampUs() - stime;
2904
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2905 2906 2907
  }

  return false;
2908 2909
}

H
Haojun Liao 已提交
2910
// handle data in cache situation
H
Haojun Liao 已提交
2911
bool tsdbNextDataBlock(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
2912
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
Y
yihaoDeng 已提交
2913

dengyihao's avatar
dengyihao 已提交
2914
  for (int32_t i = 0; i < taosArrayGetSize(pTsdbReadHandle->pColumns); ++i) {
2915 2916 2917 2918
    SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i);
    colInfoDataCleanup(pColInfo, pTsdbReadHandle->outputCapacity);
  }

2919
  if (emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
2920 2921
    tsdbDebug("%p query window not overlaps with the data set, no result returned, %s", pTsdbReadHandle,
              pTsdbReadHandle->idStr);
2922 2923 2924
    return false;
  }

Y
yihaoDeng 已提交
2925 2926 2927
  int64_t stime = taosGetTimestampUs();
  int64_t elapsedTime = stime;

2928
  // TODO refactor: remove "type"
2929 2930
  if (pTsdbReadHandle->type == TSDB_QUERY_TYPE_LAST) {
    if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LASTROW) {
dengyihao's avatar
dengyihao 已提交
2931
      //      return loadCachedLastRow(pTsdbReadHandle);
2932
    } else if (pTsdbReadHandle->cachelastrow == TSDB_CACHED_TYPE_LAST) {
dengyihao's avatar
dengyihao 已提交
2933
      //      return loadCachedLast(pTsdbReadHandle);
D
init  
dapan1121 已提交
2934
    }
H
Haojun Liao 已提交
2935
  }
Y
yihaoDeng 已提交
2936

2937 2938
  if (pTsdbReadHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) {
    return loadDataBlockFromTableSeq(pTsdbReadHandle);
dengyihao's avatar
dengyihao 已提交
2939
  } else {  // loadType == RR and Offset Order
2940
    if (pTsdbReadHandle->checkFiles) {
H
Haojun Liao 已提交
2941 2942 2943
      // check if the query range overlaps with the file data block
      bool exists = true;

2944
      int32_t code = getDataBlocksInFiles(pTsdbReadHandle, &exists);
H
Haojun Liao 已提交
2945
      if (code != TSDB_CODE_SUCCESS) {
2946 2947
        pTsdbReadHandle->activeIndex = 0;
        pTsdbReadHandle->checkFiles = false;
H
Haojun Liao 已提交
2948 2949 2950 2951 2952

        return false;
      }

      if (exists) {
2953
        pTsdbReadHandle->cost.checkForNextTime += (taosGetTimestampUs() - stime);
H
Haojun Liao 已提交
2954 2955
        return exists;
      }
Y
yihaoDeng 已提交
2956

2957 2958
      pTsdbReadHandle->activeIndex = 0;
      pTsdbReadHandle->checkFiles = false;
Y
yihaoDeng 已提交
2959 2960
    }

H
Haojun Liao 已提交
2961
    // TODO: opt by consider the scan order
2962
    bool ret = doHasDataInBuffer(pTsdbReadHandle);
H
Haojun Liao 已提交
2963
    terrno = TSDB_CODE_SUCCESS;
Y
yihaoDeng 已提交
2964

H
Haojun Liao 已提交
2965
    elapsedTime = taosGetTimestampUs() - stime;
2966
    pTsdbReadHandle->cost.checkForNextTime += elapsedTime;
H
Haojun Liao 已提交
2967
    return ret;
Y
yihaoDeng 已提交
2968 2969
  }
}
2970

dengyihao's avatar
dengyihao 已提交
2971
// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, STsdbMemTable* pMemRef) {
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005
//  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 已提交
3006
//    colInfo.pData = taosMemoryCalloc(1, pCol->info.bytes);
3007 3008 3009 3010 3011 3012 3013 3014 3015
//    if (colInfo.pData == NULL) {
//      terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//      goto out_of_memory;
//    }
//
//    taosArrayPush(row, &colInfo);
//  }
//
//  // load the previous row
3016
//  SQueryTableDataCond cond = {.numOfCols = numOfCols, .loadExternalRows = false, .type = BLOCK_LOAD_OFFSET_SEQ_ORDER};
3017 3018 3019 3020 3021 3022 3023 3024
//  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 已提交
3025
//  cond.colList = taosMemoryCalloc(cond.numOfCols, sizeof(SColumnInfo));
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035
//  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 已提交
3036
//  pSecQueryHandle = tsdbQueryTablesImpl(pTsdbReadHandle->pTsdb, &cond, pTsdbReadHandle->idStr, pMemRef);
wafwerar's avatar
wafwerar 已提交
3037
//  taosMemoryFreeClear(cond.colList);
3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075
//
//  // 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 已提交
3076
// out_of_memory:
3077
//  tsdbCleanupReadHandle(pSecQueryHandle);
3078 3079 3080
//  return terrno;
//}

H
Haojun Liao 已提交
3081
bool tsdbGetExternalRow(tsdbReaderT pHandle) {
dengyihao's avatar
dengyihao 已提交
3082 3083
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)pHandle;
  SQueryFilePos*   cur = &pTsdbReadHandle->cur;
H
Haojun Liao 已提交
3084

H
Haojun Liao 已提交
3085 3086
  cur->fid = INT32_MIN;
  cur->mixBlock = true;
3087
  if (pTsdbReadHandle->prev == NULL || pTsdbReadHandle->next == NULL) {
H
Haojun Liao 已提交
3088 3089
    cur->rows = 0;
    return false;
H
Haojun Liao 已提交
3090 3091
  }

dengyihao's avatar
dengyihao 已提交
3092
  int32_t numOfCols = (int32_t)QH_GET_NUM_OF_COLS(pTsdbReadHandle);
H
Haojun Liao 已提交
3093
  for (int32_t i = 0; i < numOfCols; ++i) {
3094 3095
    SColumnInfoData* pColInfoData = taosArrayGet(pTsdbReadHandle->pColumns, i);
    SColumnInfoData* first = taosArrayGet(pTsdbReadHandle->prev, i);
H
Haojun Liao 已提交
3096 3097 3098

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

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

    if (i == 0 && pColInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
H
Haojun Liao 已提交
3103
      cur->win.skey = *(TSKEY*)pColInfoData->pData;
sangshuduo's avatar
sangshuduo 已提交
3104
      cur->win.ekey = *(TSKEY*)(((char*)pColInfoData->pData) + TSDB_KEYSIZE);
H
Haojun Liao 已提交
3105 3106 3107
    }
  }

H
Haojun Liao 已提交
3108 3109
  cur->rows = 2;
  return true;
3110 3111
}

3112
/*
3113
 * if lastRow == NULL, return TSDB_CODE_TDB_NO_CACHE_LAST_ROW
3114
 * else set pRes and return TSDB_CODE_SUCCESS and save lastKey
3115
 */
H
Haojun Liao 已提交
3116
// int32_t tsdbGetCachedLastRow(STable* pTable, STSRow** pRes, TSKEY* lastKey) {
3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132
//  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 已提交
3133
// out:
3134 3135 3136 3137
//  TSDB_RUNLOCK_TABLE(pTable);
//  return code;
//}

3138
bool isTsdbCacheLastRow(tsdbReaderT* pReader) {
dengyihao's avatar
dengyihao 已提交
3139
  return ((STsdbReadHandle*)pReader)->cachelastrow > TSDB_CACHED_TYPE_NONE;
D
fix bug  
dapan1121 已提交
3140 3141
}

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

dengyihao's avatar
dengyihao 已提交
3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168
  //  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 已提交
3169

3170
  return TSDB_CODE_SUCCESS;
3171 3172
}

3173 3174
int32_t checkForCachedLast(STsdbReadHandle* pTsdbReadHandle) {
  assert(pTsdbReadHandle != NULL);
D
update  
dapan1121 已提交
3175 3176

  int32_t code = 0;
dengyihao's avatar
dengyihao 已提交
3177 3178 3179
  //  if (pTsdbReadHandle->pTsdb && atomic_load_8(&pTsdbReadHandle->pTsdb->hasCachedLastColumn)){
  //    pTsdbReadHandle->cachelastrow = TSDB_CACHED_TYPE_LAST;
  //  }
D
update  
dapan1121 已提交
3180 3181

  // update the tsdb query time range
3182
  if (pTsdbReadHandle->cachelastrow) {
dengyihao's avatar
dengyihao 已提交
3183
    pTsdbReadHandle->checkFiles = false;
3184
    pTsdbReadHandle->activeIndex = -1;  // start from -1
D
update  
dapan1121 已提交
3185 3186 3187 3188 3189
  }

  return code;
}

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

H
Haojun Liao 已提交
3193
  int32_t totalNumOfTable = 0;
3194
  SArray* emptyGroup = taosArrayInit(16, sizeof(int32_t));
H
Haojun Liao 已提交
3195

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

H
Haojun Liao 已提交
3202
    STableKeyInfo keyInfo = {0};
H
Haojun Liao 已提交
3203

H
Haojun Liao 已提交
3204
    size_t numOfTables = taosArrayGetSize(pGroup);
dengyihao's avatar
dengyihao 已提交
3205 3206
    for (int32_t i = 0; i < numOfTables; ++i) {
      STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i);
H
Haojun Liao 已提交
3207

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

dengyihao's avatar
dengyihao 已提交
3213
        //        keyInfo.pTable  = pInfo->pTable;
H
Haojun Liao 已提交
3214
        keyInfo.lastKey = key;
dengyihao's avatar
dengyihao 已提交
3215
        pInfo->lastKey = key;
H
Haojun Liao 已提交
3216

H
Haojun Liao 已提交
3217 3218 3219
        if (key < window.skey) {
          window.skey = key;
        }
3220

H
Haojun Liao 已提交
3221 3222 3223 3224
        if (key > window.ekey) {
          window.ekey = key;
        }
      }
3225
    }
H
Haojun Liao 已提交
3226

H
Haojun Liao 已提交
3227
    // more than one table in each group, only one table left for each group
dengyihao's avatar
dengyihao 已提交
3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239
    //    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);
    //    }
3240
  }
H
Haojun Liao 已提交
3241

H
Haojun Liao 已提交
3242 3243 3244
  // window does not being updated, so set the original
  if (window.skey == INT64_MAX && window.ekey == INT64_MIN) {
    window = TSWINDOW_INITIALIZER;
H
Haojun Liao 已提交
3245
    assert(totalNumOfTable == 0 && taosArrayGetSize(groupList->pGroupList) == numOfGroups);
H
Haojun Liao 已提交
3246 3247
  }

dengyihao's avatar
dengyihao 已提交
3248
  taosArrayRemoveBatch(groupList->pGroupList, TARRAY_GET_START(emptyGroup), (int32_t)taosArrayGetSize(emptyGroup));
3249 3250
  taosArrayDestroy(emptyGroup);

H
Haojun Liao 已提交
3251
  groupList->numOfTables = totalNumOfTable;
H
Haojun Liao 已提交
3252
  return window;
H
hjxilinx 已提交
3253 3254
}

H
Haojun Liao 已提交
3255
void tsdbRetrieveDataBlockInfo(tsdbReaderT* pTsdbReadHandle, SDataBlockInfo* pDataBlockInfo) {
3256
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
dengyihao's avatar
dengyihao 已提交
3257
  SQueryFilePos*   cur = &pHandle->cur;
3258 3259

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

3261
  // there are data in file
D
dapan1121 已提交
3262
  if (pHandle->cur.fid != INT32_MIN) {
3263
    STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[cur->slot];
3264
    uid = pBlockInfo->pTableCheckInfo->tableId;
H
[td-32]  
hjxilinx 已提交
3265
  } else {
3266
    STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
3267
    uid = pCheckInfo->tableId;
3268
  }
3269

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

3273
  pDataBlockInfo->uid = uid;
3274 3275 3276 3277 3278 3279

#if 0
  // for multi-group data query processing test purpose
  pDataBlockInfo->groupId = uid;
#endif

dengyihao's avatar
dengyihao 已提交
3280
  pDataBlockInfo->rows = cur->rows;
H
Haojun Liao 已提交
3281
  pDataBlockInfo->window = cur->win;
S
TD-1057  
Shengliang Guan 已提交
3282
  pDataBlockInfo->numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pHandle));
3283
}
H
hjxilinx 已提交
3284

H
Haojun Liao 已提交
3285 3286 3287
/*
 * return null for mixed data block, if not a complete file data block, the statistics value will always return NULL
 */
3288
int32_t tsdbRetrieveDataBlockStatisInfo(tsdbReaderT* pTsdbReadHandle, SColumnDataAgg*** pBlockStatis, bool* allHave) {
dengyihao's avatar
dengyihao 已提交
3289
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
3290
  *allHave = false;
H
Haojun Liao 已提交
3291

H
Haojun Liao 已提交
3292 3293
  SQueryFilePos* c = &pHandle->cur;
  if (c->mixBlock) {
H
Haojun Liao 已提交
3294 3295 3296
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3297

H
Haojun Liao 已提交
3298 3299 3300 3301
  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 已提交
3302 3303 3304 3305
  if (pBlockInfo->compBlock->numOfSubBlocks > 1) {
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
  }
H
Haojun Liao 已提交
3306 3307

  int64_t stime = taosGetTimestampUs();
3308 3309
  int     statisStatus = tsdbLoadBlockStatis(&pHandle->rhelper, pBlockInfo->compBlock);
  if (statisStatus < TSDB_STATIS_OK) {
H
Hongze Cheng 已提交
3310
    return terrno;
3311 3312 3313
  } else if (statisStatus > TSDB_STATIS_OK) {
    *pBlockStatis = NULL;
    return TSDB_CODE_SUCCESS;
H
Hongze Cheng 已提交
3314
  }
H
Haojun Liao 已提交
3315

C
Cary Xu 已提交
3316 3317 3318
  tsdbDebug("vgId:%d succeed to load block statis part for uid %" PRIu64, REPO_ID(pHandle->pTsdb),
            TSDB_READ_TABLE_UID(&pHandle->rhelper));

3319
  int16_t* colIds = pHandle->suppInfo.defaultLoadColumn->pData;
H
Haojun Liao 已提交
3320

H
Haojun Liao 已提交
3321
  size_t numOfCols = QH_GET_NUM_OF_COLS(pHandle);
3322 3323 3324
  memset(pHandle->suppInfo.plist, 0, numOfCols * POINTER_BYTES);
  memset(pHandle->suppInfo.pstatis, 0, numOfCols * sizeof(SColumnDataAgg));

dengyihao's avatar
dengyihao 已提交
3325
  for (int32_t i = 0; i < numOfCols; ++i) {
3326
    pHandle->suppInfo.pstatis[i].colId = colIds[i];
3327
  }
H
Haojun Liao 已提交
3328

3329 3330
  *allHave = true;
  tsdbGetBlockStatis(&pHandle->rhelper, pHandle->suppInfo.pstatis, (int)numOfCols, pBlockInfo->compBlock);
H
Haojun Liao 已提交
3331 3332

  // always load the first primary timestamp column data
3333
  SColumnDataAgg* pPrimaryColStatis = &pHandle->suppInfo.pstatis[0];
3334
  assert(pPrimaryColStatis->colId == PRIMARYKEY_TIMESTAMP_COL_ID);
H
Haojun Liao 已提交
3335 3336 3337 3338

  pPrimaryColStatis->numOfNull = 0;
  pPrimaryColStatis->min = pBlockInfo->compBlock->keyFirst;
  pPrimaryColStatis->max = pBlockInfo->compBlock->keyLast;
3339
  pHandle->suppInfo.plist[0] = &pHandle->suppInfo.pstatis[0];
H
Haojun Liao 已提交
3340

dengyihao's avatar
dengyihao 已提交
3341
  // update the number of NULL data rows
3342
  int32_t* slotIds = pHandle->suppInfo.slotIds;
dengyihao's avatar
dengyihao 已提交
3343
  for (int32_t i = 1; i < numOfCols; ++i) {
3344
    ASSERT(colIds[i] == pHandle->pSchema->columns[slotIds[i]].colId);
C
Cary Xu 已提交
3345
    if (IS_BSMA_ON(&(pHandle->pSchema->columns[slotIds[i]]))) {
3346 3347 3348 3349 3350 3351 3352
      if (pHandle->suppInfo.pstatis[i].numOfNull == -1) {  // set the column data are all NULL
        pHandle->suppInfo.pstatis[i].numOfNull = pBlockInfo->compBlock->numOfRows;
      } else {
        pHandle->suppInfo.plist[i] = &pHandle->suppInfo.pstatis[i];
      }
    } else {
      *allHave = false;
H
Haojun Liao 已提交
3353 3354
    }
  }
H
Haojun Liao 已提交
3355 3356 3357 3358

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

3359
  *pBlockStatis = pHandle->suppInfo.plist;
3360
  return TSDB_CODE_SUCCESS;
H
hjxilinx 已提交
3361 3362
}

H
Haojun Liao 已提交
3363
SArray* tsdbRetrieveDataBlock(tsdbReaderT* pTsdbReadHandle, SArray* pIdList) {
H
[td-32]  
hjxilinx 已提交
3364
  /**
H
hjxilinx 已提交
3365
   * In the following two cases, the data has been loaded to SColumnInfoData.
H
[td-32]  
hjxilinx 已提交
3366 3367
   * 1. data is from cache, 2. data block is not completed qualified to query time range
   */
3368
  STsdbReadHandle* pHandle = (STsdbReadHandle*)pTsdbReadHandle;
D
dapan1121 已提交
3369
  if (pHandle->cur.fid == INT32_MIN) {
H
[td-32]  
hjxilinx 已提交
3370 3371
    return pHandle->pColumns;
  } else {
H
Haojun Liao 已提交
3372 3373
    STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[pHandle->cur.slot];
    STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo;
3374

3375
    if (pHandle->cur.mixBlock) {
H
[td-32]  
hjxilinx 已提交
3376 3377
      return pHandle->pColumns;
    } else {
H
Haojun Liao 已提交
3378
      SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlockInfo->compBlock);
3379
      assert(pHandle->realNumOfRows <= binfo.rows);
H
Haojun Liao 已提交
3380

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

H
Hongze Cheng 已提交
3384
      if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fid == pHandle->cur.fid &&
H
Haojun Liao 已提交
3385
          pBlockLoadInfo->uid == pCheckInfo->tableId) {
H
hjxilinx 已提交
3386
        return pHandle->pColumns;
H
Haojun Liao 已提交
3387
      } else {  // only load the file block
H
refact  
Hongze Cheng 已提交
3388
        SBlock* pBlock = pBlockInfo->compBlock;
H
Haojun Liao 已提交
3389
        if (doLoadFileDataBlock(pHandle, pBlock, pCheckInfo, pHandle->cur.slot) != TSDB_CODE_SUCCESS) {
3390 3391
          return NULL;
        }
H
Haojun Liao 已提交
3392

H
Haojun Liao 已提交
3393
        int32_t numOfRows = doCopyRowsFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfRows - 1);
H
hjxilinx 已提交
3394 3395
        return pHandle->pColumns;
      }
H
[td-32]  
hjxilinx 已提交
3396 3397
    }
  }
H
hjxilinx 已提交
3398
}
3399
#if 0
3400
void filterPrepare(void* expr, void* param) {
3401
  tExprNode* pExpr = (tExprNode*)expr;
H
[td-32]  
hjxilinx 已提交
3402
  if (pExpr->_node.info != NULL) {
3403 3404
    return;
  }
3405

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

3408
  STSchema*   pTSSchema = (STSchema*) param;
H
hjxilinx 已提交
3409 3410 3411
  tQueryInfo* pInfo = pExpr->_node.info;
  tVariant*   pCond = pExpr->_node.pRight->pVal;
  SSchema*    pSchema = pExpr->_node.pLeft->pSchema;
3412

3413 3414
  pInfo->sch      = *pSchema;
  pInfo->optr     = pExpr->_node.optr;
Y
yihaoDeng 已提交
3415
  pInfo->compare  = getComparFunc(pInfo->sch.type, pInfo->optr);
H
Haojun Liao 已提交
3416
  pInfo->indexed  = pTSSchema->columns->colId == pInfo->sch.colId;
H
Haojun Liao 已提交
3417

H
hjxilinx 已提交
3418
  if (pInfo->optr == TSDB_RELATION_IN) {
Y
yihaoDeng 已提交
3419
     int dummy = -1;
3420
     SHashObj *pObj = NULL;
Y
yihaoDeng 已提交
3421 3422 3423 3424
     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 已提交
3425
          char* p = taosArrayGetP(arr, i);
3426 3427
          strntolower_s(varDataVal(p), varDataVal(p), varDataLen(p));
          taosHashPut(pObj, varDataVal(p), varDataLen(p), &dummy, sizeof(dummy));
Y
yihaoDeng 已提交
3428 3429 3430 3431
        }
     } else {
       buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen);
     }
3432
     pInfo->q = (char *)pObj;
H
Haojun Liao 已提交
3433
  } else if (pCond != NULL) {
3434 3435 3436 3437
    uint32_t size = pCond->nLen * TSDB_NCHAR_SIZE;
    if (size < (uint32_t)pSchema->bytes) {
      size = pSchema->bytes;
    }
wafwerar's avatar
wafwerar 已提交
3438
    // to make sure tonchar does not cause invalid write, since the '\0' needs at least sizeof(TdUcs4) space.
wafwerar's avatar
wafwerar 已提交
3439
    pInfo->q = taosMemoryCalloc(1, size + TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE);
3440
    tVariantDump(pCond, pInfo->q, pSchema->type, true);
weixin_48148422's avatar
weixin_48148422 已提交
3441
  }
3442 3443
}

3444
#endif
3445

dengyihao's avatar
dengyihao 已提交
3446
static int32_t tableGroupComparFn(const void* p1, const void* p2, const void* param) {
3447
#if 0
3448
  STableGroupSupporter* pTableGroupSupp = (STableGroupSupporter*) param;
3449 3450
  STable* pTable1 = ((STableKeyInfo*) p1)->uid;
  STable* pTable2 = ((STableKeyInfo*) p2)->uid;
H
Haojun Liao 已提交
3451

3452 3453 3454
  for (int32_t i = 0; i < pTableGroupSupp->numOfCols; ++i) {
    SColIndex* pColIndex = &pTableGroupSupp->pCols[i];
    int32_t colIndex = pColIndex->colIndex;
H
Haojun Liao 已提交
3455

H
Haojun Liao 已提交
3456
    assert(colIndex >= TSDB_TBNAME_COLUMN_INDEX);
H
Haojun Liao 已提交
3457

3458 3459 3460 3461
    char *  f1 = NULL;
    char *  f2 = NULL;
    int32_t type = 0;
    int32_t bytes = 0;
H
Haojun Liao 已提交
3462

H
Haojun Liao 已提交
3463 3464 3465
    if (colIndex == TSDB_TBNAME_COLUMN_INDEX) {
      f1 = (char*) TABLE_NAME(pTable1);
      f2 = (char*) TABLE_NAME(pTable2);
3466
      type = TSDB_DATA_TYPE_BINARY;
3467
      bytes = tGetTbnameColumnSchema()->bytes;
3468
    } else {
Y
yihaoDeng 已提交
3469 3470 3471 3472 3473 3474 3475
      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);
      } 
3476
    }
H
Haojun Liao 已提交
3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490

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

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

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

3491 3492 3493 3494 3495 3496 3497
    int32_t ret = doCompare(f1, f2, type, bytes);
    if (ret == 0) {
      continue;
    } else {
      return ret;
    }
  }
3498
#endif
3499 3500 3501
  return 0;
}

H
Haojun Liao 已提交
3502
static int tsdbCheckInfoCompar(const void* key1, const void* key2) {
3503
  if (((STableCheckInfo*)key1)->tableId < ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3504
    return -1;
3505
  } else if (((STableCheckInfo*)key1)->tableId > ((STableCheckInfo*)key2)->tableId) {
H
Haojun Liao 已提交
3506 3507 3508 3509 3510 3511 3512 3513 3514
    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) {
3515
  STable* pTable = taosArrayGetP(pTableList, 0);
H
Haojun Liao 已提交
3516 3517
  SArray* g = taosArrayInit(16, sizeof(STableKeyInfo));

3518
  STableKeyInfo info = {.lastKey = skey};
H
Haojun Liao 已提交
3519
  taosArrayPush(g, &info);
3520

3521
  for (int32_t i = 1; i < numOfTables; ++i) {
3522 3523
    STable** prev = taosArrayGet(pTableList, i - 1);
    STable** p = taosArrayGet(pTableList, i);
H
Haojun Liao 已提交
3524

H
hjxilinx 已提交
3525
    int32_t ret = compareFn(prev, p, pSupp);
3526
    assert(ret == 0 || ret == -1);
H
Haojun Liao 已提交
3527

3528
    if (ret == 0) {
3529
      STableKeyInfo info1 = {.lastKey = skey};
H
Haojun Liao 已提交
3530
      taosArrayPush(g, &info1);
3531 3532
    } else {
      taosArrayPush(pGroups, &g);  // current group is ended, start a new group
H
Haojun Liao 已提交
3533 3534
      g = taosArrayInit(16, sizeof(STableKeyInfo));

3535
      STableKeyInfo info1 = {.lastKey = skey};
H
Haojun Liao 已提交
3536
      taosArrayPush(g, &info1);
3537 3538
    }
  }
H
Haojun Liao 已提交
3539

3540
  taosArrayPush(pGroups, &g);
3541 3542
}

dengyihao's avatar
dengyihao 已提交
3543 3544
SArray* createTableGroup(SArray* pTableList, SSchemaWrapper* pTagSchema, SColIndex* pCols, int32_t numOfOrderCols,
                         TSKEY skey) {
3545
  assert(pTableList != NULL);
3546
  SArray* pTableGroup = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3547

3548 3549
  size_t size = taosArrayGetSize(pTableList);
  if (size == 0) {
S
Shengliang Guan 已提交
3550
    tsdbDebug("no qualified tables");
3551 3552
    return pTableGroup;
  }
H
Haojun Liao 已提交
3553

dengyihao's avatar
dengyihao 已提交
3554
  if (numOfOrderCols == 0 || size == 1) {  // no group by tags clause or only one table
3555
    SArray* sa = taosArrayDup(pTableList);
H
Haojun Liao 已提交
3556 3557 3558 3559
    if (sa == NULL) {
      taosArrayDestroy(pTableGroup);
      return NULL;
    }
H
Haojun Liao 已提交
3560

3561
    taosArrayPush(pTableGroup, &sa);
S
TD-1057  
Shengliang Guan 已提交
3562
    tsdbDebug("all %" PRIzu " tables belong to one group", size);
3563
  } else {
H
Haojun Liao 已提交
3564 3565
    STableGroupSupporter sup = {0};
    sup.numOfCols = numOfOrderCols;
3566
    sup.pTagSchema = pTagSchema->pSchema;
H
Haojun Liao 已提交
3567 3568
    sup.pCols = pCols;

3569 3570
    taosqsort(pTableList->pData, size, sizeof(STableKeyInfo), &sup, tableGroupComparFn);
    createTableGroupImpl(pTableGroup, pTableList, size, skey, &sup, tableGroupComparFn);
3571
  }
H
Haojun Liao 已提交
3572

3573 3574 3575
  return pTableGroup;
}

dengyihao's avatar
dengyihao 已提交
3576
// static bool tableFilterFp(const void* pNode, void* param) {
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 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659
//  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 已提交
3660

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

dengyihao's avatar
dengyihao 已提交
3664 3665
// static int32_t doQueryTableList(STable* pSTable, SArray* pRes, tExprNode* pExpr) {
//  //  // query according to the expression tree
3666
//  SExprTraverseSupp supp = {
dengyihao's avatar
dengyihao 已提交
3667
//      .nodeFilterFn = (__result_filter_fn_t)tableFilterFp,
3668 3669
//      .setupInfoFn = filterPrepare,
//      .pExtInfo = pSTable->tagSchema,
dengyihao's avatar
dengyihao 已提交
3670
//  };
3671 3672 3673 3674 3675
//
//  getTableListfromSkipList(pExpr, pSTable->pIndex, pRes, &supp);
//  tExprTreeDestroy(pExpr, destroyHelper);
//  return TSDB_CODE_SUCCESS;
//}
3676

H
Haojun Liao 已提交
3677
int32_t tsdbQuerySTableByTagCond(void* pMeta, uint64_t uid, TSKEY skey, const char* pTagCond, size_t len,
3678
                                 int16_t tagNameRelType, const char* tbnameCond, STableGroupInfo* pGroupInfo,
3679
                                 SColIndex* pColIndex, int32_t numOfCols, uint64_t reqId, uint64_t taskId) {
H
Hongze Cheng 已提交
3680 3681
  SMetaReader mr = {0};

H
Hongze Cheng 已提交
3682
  metaReaderInit(&mr, (SMeta*)pMeta, 0);
H
Hongze Cheng 已提交
3683 3684

  if (metaGetTableEntryByUid(&mr, uid) < 0) {
dengyihao's avatar
dengyihao 已提交
3685
    tsdbError("%p failed to get stable, uid:%" PRIu64 ", TID:0x%" PRIx64 " QID:0x%" PRIx64, pMeta, uid, taskId, reqId);
3686 3687
    terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
    goto _error;
C
Cary Xu 已提交
3688 3689
  } else {
    tsdbDebug("%p succeed to get stable, uid:%" PRIu64 ", TID:0x%" PRIx64 " QID:0x%" PRIx64, pMeta, uid, taskId, reqId);
3690
  }
H
Haojun Liao 已提交
3691

H
Hongze Cheng 已提交
3692
  if (mr.me.type != TSDB_SUPER_TABLE) {
dengyihao's avatar
dengyihao 已提交
3693 3694 3695
    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
3696
    goto _error;
H
hjxilinx 已提交
3697
  }
3698

H
Hongze Cheng 已提交
3699 3700
  metaReaderClear(&mr);

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

weixin_48148422's avatar
weixin_48148422 已提交
3705 3706
  // no tags and tbname condition, all child tables of this stable are involved
  if (tbnameCond == NULL && (pTagCond == NULL || len == 0)) {
H
Haojun Liao 已提交
3707
    int32_t ret = getAllTableList(pMeta, uid, res);
3708 3709
    if (ret != TSDB_CODE_SUCCESS) {
      goto _error;
3710
    }
3711

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

dengyihao's avatar
dengyihao 已提交
3715 3716 3717
    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);
3718

3719
    taosArrayDestroy(res);
3720 3721
    return ret;
  }
3722

H
hjxilinx 已提交
3723
  int32_t ret = TSDB_CODE_SUCCESS;
3724

dengyihao's avatar
dengyihao 已提交
3725 3726
  SFilterInfo* filterInfo = NULL;
  ret = filterInitFromNode((SNode*)pTagCond, &filterInfo, 0);
dengyihao's avatar
dengyihao 已提交
3727 3728 3729 3730 3731 3732 3733 3734
  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 已提交
3735 3736
  // 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 已提交
3737 3738 3739 3740 3741

  taosArrayDestroy(res);
  return ret;

_error:
3742
  return terrno;
3743
}
3744

dengyihao's avatar
dengyihao 已提交
3745 3746 3747 3748 3749
int32_t tsdbQueryTableList(void* pMeta, SArray* pRes, void* filterInfo) {
  // impl later

  return TSDB_CODE_SUCCESS;
}
H
Haojun Liao 已提交
3750
int32_t tsdbGetOneTableGroup(void* pMeta, uint64_t uid, TSKEY startKey, STableGroupInfo* pGroupInfo) {
H
Hongze Cheng 已提交
3751 3752
  SMetaReader mr = {0};

H
Hongze Cheng 已提交
3753
  metaReaderInit(&mr, (SMeta*)pMeta, 0);
H
Hongze Cheng 已提交
3754 3755

  if (metaGetTableEntryByUid(&mr, uid) < 0) {
3756 3757
    terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
    goto _error;
3758
  }
3759

H
Hongze Cheng 已提交
3760 3761
  metaReaderClear(&mr);

3762 3763
  pGroupInfo->numOfTables = 1;
  pGroupInfo->pGroupList = taosArrayInit(1, POINTER_BYTES);
H
Haojun Liao 已提交
3764

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

3767
  STableKeyInfo info = {.lastKey = startKey, .uid = uid};
H
Haojun Liao 已提交
3768
  taosArrayPush(group, &info);
H
Haojun Liao 已提交
3769

3770
  taosArrayPush(pGroupInfo->pGroupList, &group);
3771
  return TSDB_CODE_SUCCESS;
3772

dengyihao's avatar
dengyihao 已提交
3773
_error:
H
Hongze Cheng 已提交
3774
  metaReaderClear(&mr);
3775
  return terrno;
3776
}
3777

3778
#if 0
3779
int32_t tsdbGetTableGroupFromIdListT(STsdb* tsdb, SArray* pTableIdList, STableGroupInfo* pGroupInfo) {
B
Bomin Zhang 已提交
3780 3781 3782
  if (tsdbRLockRepoMeta(tsdb) < 0) {
    return terrno;
  }
3783 3784 3785 3786

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

B
Bomin Zhang 已提交
3789
  for(int32_t i = 0; i < size; ++i) {
3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
    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 已提交
3801 3802 3803
      tsdbUnlockRepoMeta(tsdb);
      taosArrayDestroy(group);
      return terrno;
3804 3805
    }

H
Haojun Liao 已提交
3806 3807
    STableKeyInfo info = {.pTable = pTable, .lastKey = id->key};
    taosArrayPush(group, &info);
3808 3809
  }

B
Bomin Zhang 已提交
3810 3811 3812 3813
  if (tsdbUnlockRepoMeta(tsdb) < 0) {
    taosArrayDestroy(group);
    return terrno;
  }
3814

sangshuduo's avatar
sangshuduo 已提交
3815
  pGroupInfo->numOfTables = (uint32_t) taosArrayGetSize(group);
B
Bomin Zhang 已提交
3816 3817 3818 3819 3820
  if (pGroupInfo->numOfTables > 0) {
    taosArrayPush(pGroupInfo->pGroupList, &group);
  } else {
    taosArrayDestroy(group);
  }
3821 3822 3823

  return TSDB_CODE_SUCCESS;
}
3824
#endif
3825 3826 3827 3828 3829 3830 3831 3832
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 已提交
3833
    taosMemoryFreeClear(pColInfo->pData);
3834 3835 3836 3837 3838 3839
  }

  taosArrayDestroy(pColumnInfoData);
  return NULL;
}

H
Haojun Liao 已提交
3840 3841 3842 3843 3844 3845
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 已提交
3846
    taosMemoryFreeClear(p->pCompInfo);
H
Haojun Liao 已提交
3847 3848 3849 3850 3851 3852
  }

  taosArrayDestroy(pTableCheckInfo);
  return NULL;
}

H
Haojun Liao 已提交
3853
void tsdbCleanupReadHandle(tsdbReaderT queryHandle) {
3854 3855
  STsdbReadHandle* pTsdbReadHandle = (STsdbReadHandle*)queryHandle;
  if (pTsdbReadHandle == NULL) {
3856 3857
    return;
  }
3858

3859
  pTsdbReadHandle->pColumns = doFreeColumnInfoData(pTsdbReadHandle->pColumns);
3860

3861
  taosArrayDestroy(pTsdbReadHandle->suppInfo.defaultLoadColumn);
wafwerar's avatar
wafwerar 已提交
3862
  taosMemoryFreeClear(pTsdbReadHandle->pDataBlockInfo);
3863 3864
  taosMemoryFreeClear(pTsdbReadHandle->suppInfo.pstatis);
  taosMemoryFreeClear(pTsdbReadHandle->suppInfo.plist);
3865

3866
  if (!emptyQueryTimewindow(pTsdbReadHandle)) {
dengyihao's avatar
dengyihao 已提交
3867
    //    tsdbMayUnTakeMemSnapshot(pTsdbReadHandle);
3868
  } else {
3869
    assert(pTsdbReadHandle->pTableCheckInfo == NULL);
3870 3871
  }

3872 3873
  if (pTsdbReadHandle->pTableCheckInfo != NULL) {
    pTsdbReadHandle->pTableCheckInfo = destroyTableCheckInfo(pTsdbReadHandle->pTableCheckInfo);
3874
  }
3875

3876
  tsdbDestroyReadH(&pTsdbReadHandle->rhelper);
H
Haojun Liao 已提交
3877

3878 3879
  tdFreeDataCols(pTsdbReadHandle->pDataCols);
  pTsdbReadHandle->pDataCols = NULL;
H
Haojun Liao 已提交
3880

3881 3882
  pTsdbReadHandle->prev = doFreeColumnInfoData(pTsdbReadHandle->prev);
  pTsdbReadHandle->next = doFreeColumnInfoData(pTsdbReadHandle->next);
3883

3884
  SIOCostSummary* pCost = &pTsdbReadHandle->cost;
3885

dengyihao's avatar
dengyihao 已提交
3886 3887 3888 3889
  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 已提交
3890

wafwerar's avatar
wafwerar 已提交
3891
  taosMemoryFreeClear(pTsdbReadHandle);
3892
}
3893

3894
#if 0
H
Haojun Liao 已提交
3895
void tsdbDestroyTableGroup(STableGroupInfo *pGroupList) {
3896 3897 3898 3899 3900 3901 3902 3903 3904 3905
  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);
3906 3907 3908 3909
      if (pTable != NULL) { // in case of handling retrieve data from tsdb
        tsdbUnRefTable(pTable);
      }
      //assert(pTable != NULL);
3910 3911 3912 3913 3914
    }

    taosArrayDestroy(p);
  }

3915
  taosHashCleanup(pGroupList->map);
3916
  taosArrayDestroy(pGroupList->pGroupList);
H
Haojun Liao 已提交
3917
  pGroupList->numOfTables = 0;
3918
}
H
Haojun Liao 已提交
3919 3920 3921 3922 3923 3924 3925

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 已提交
3926
    if (exprTreeApplyFilter(pExpr, pNode, param)) {
H
Haojun Liao 已提交
3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949
      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 已提交
3950
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3951
    pCond->start->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3952
    pCond->start->v    = queryColInfo->q;
H
Haojun Liao 已提交
3953
  } else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
wafwerar's avatar
wafwerar 已提交
3954
    pCond->end       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3955
    pCond->end->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3956 3957
    pCond->end->v    = queryColInfo->q;
  } else if (optr == TSDB_RELATION_IN) {
wafwerar's avatar
wafwerar 已提交
3958
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
Y
yihaoDeng 已提交
3959 3960 3961
    pCond->start->optr = queryColInfo->optr;
    pCond->start->v    = queryColInfo->q; 
  } else if (optr == TSDB_RELATION_LIKE) {
H
Haojun Liao 已提交
3962
    assert(0);
3963 3964
  } else if (optr == TSDB_RELATION_MATCH) {
    assert(0);
3965 3966
  } else if (optr == TSDB_RELATION_NMATCH) {
    assert(0);
H
Haojun Liao 已提交
3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049
  }

  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 已提交
4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062
    } 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 已提交
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103
    } 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 已提交
4104 4105
  taosMemoryFree(cond.start);
  taosMemoryFree(cond.end);
H
Haojun Liao 已提交
4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123
  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);
4124 4125 4126
      } else if (pQueryInfo->optr == TSDB_RELATION_LIKE ||
                 pQueryInfo->optr == TSDB_RELATION_MATCH ||
                 pQueryInfo->optr == TSDB_RELATION_NMATCH) {
H
Haojun Liao 已提交
4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142
        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 已提交
4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175
//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 已提交
4176
#endif