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);
158
static int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);
dengyihao's avatar
dengyihao 已提交
159 160
static int32_t tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win,
                                     STsdbReadHandle* pTsdbReadHandle);
161
static int32_t tsdbCheckInfoCompar(const void* key1, const void* key2);
dengyihao's avatar
dengyihao 已提交
162 163 164 165
// 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 已提交
166

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

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

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

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

  return pIdList;
}

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

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

  return pLocalIdList;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

422 423 424
    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 已提交
425
  }
426

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

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

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

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

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

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

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

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

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

467
  pTsdbReadHandle->pSchema = metaGetTbTSchema(pVnode->pMeta, pCheckInfo->tableId, 0);
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
  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;
    }
  }
487

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

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

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

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

    return;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return pNew;
}

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

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

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

687
  return pTsdbReadHandle;
688 689
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

770 771 772
  return true;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1025 1026
  return midSlot;
}
1027

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

_error:
  pBlock->numOfRows = 0;

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

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

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

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

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

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

1235 1236 1237 1238
  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 已提交
1239
      // do not load file block into buffer
1240
      int32_t step = ASCENDING_TRAVERSE(pTsdbReadHandle->order) ? 1 : -1;
H
Haojun Liao 已提交
1241

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

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

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

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

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

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

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

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

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

  return code;
1309 1310
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1427 1428 1429
  return midPos;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1511
  return numOfRows + num;
1512 1513
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  int32_t pos = cur->pos;

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

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

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

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

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

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

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

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

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

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

  return endPos;
}

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

1806
  initTableMemIterator(pTsdbReadHandle, pCheckInfo);
1807

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2155
    numOfQualTables++;
2156 2157
  }

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

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

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

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

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

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

  int32_t numOfTotal = 0;

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

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

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

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

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

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

  return TSDB_CODE_SUCCESS;
}

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

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

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

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

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

  int32_t code = TSDB_CODE_SUCCESS;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if (numOfBlocks == 0) {
      continue;
    }

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

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

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

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

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

  return code;
}

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

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

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

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

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

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

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

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

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

2506 2507 2508
  return false;
}

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

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

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

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

    i++;
  }

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

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

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

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

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

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

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

      break;
    }

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

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

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

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

  assert(numOfRows <= maxRowsToRead);

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

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

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

  return numOfRows;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

dengyihao's avatar
dengyihao 已提交
2730
// static bool loadCachedLast(STsdbReadHandle* pTsdbReadHandle) {
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749
//  // 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 已提交
2750 2751
//      tsdbWarn("no last cached for table %s, uid:%" PRIu64 ",tid:%d", pTable->name->data, pTable->uid,
//      pTable->tableId); continue;
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 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
//    }
//
//    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 已提交
2882 2883 2884
  assert(numOfTables > 0);

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

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

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

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

    terrno = TSDB_CODE_SUCCESS;

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

  return false;
2907 2908
}

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

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

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

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

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

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

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

        return false;
      }

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

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

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

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

dengyihao's avatar
dengyihao 已提交
2970
// static int32_t doGetExternalRow(STsdbReadHandle* pTsdbReadHandle, int16_t type, STsdbMemTable* pMemRef) {
2971 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
//  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 已提交
3005
//    colInfo.pData = taosMemoryCalloc(1, pCol->info.bytes);
3006 3007 3008 3009 3010 3011 3012 3013 3014
//    if (colInfo.pData == NULL) {
//      terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
//      goto out_of_memory;
//    }
//
//    taosArrayPush(row, &colInfo);
//  }
//
//  // load the previous row
3015
//  SQueryTableDataCond cond = {.numOfCols = numOfCols, .loadExternalRows = false, .type = BLOCK_LOAD_OFFSET_SEQ_ORDER};
3016 3017 3018 3019 3020 3021 3022 3023
//  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 已提交
3024
//  cond.colList = taosMemoryCalloc(cond.numOfCols, sizeof(SColumnInfo));
3025 3026 3027 3028 3029 3030 3031 3032 3033 3034
//  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 已提交
3035
//  pSecQueryHandle = tsdbQueryTablesImpl(pTsdbReadHandle->pTsdb, &cond, pTsdbReadHandle->idStr, pMemRef);
wafwerar's avatar
wafwerar 已提交
3036
//  taosMemoryFreeClear(cond.colList);
3037 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
//
//  // 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 已提交
3075
// out_of_memory:
3076
//  tsdbCleanupReadHandle(pSecQueryHandle);
3077 3078 3079
//  return terrno;
//}

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

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

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

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

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

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

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

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

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

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

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

3169
  return TSDB_CODE_SUCCESS;
3170 3171
}

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

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

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

  return code;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

dengyihao's avatar
dengyihao 已提交
3340
  // update the number of NULL data rows
3341
  int32_t* slotIds = pHandle->suppInfo.slotIds;
dengyihao's avatar
dengyihao 已提交
3342
  for (int32_t i = 1; i < numOfCols; ++i) {
3343
    ASSERT(colIds[i] == pHandle->pSchema->columns[slotIds[i]].colId);
C
Cary Xu 已提交
3344
    if (IS_BSMA_ON(&(pHandle->pSchema->columns[slotIds[i]]))) {
3345 3346 3347 3348 3349 3350 3351
      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 已提交
3352 3353
    }
  }
H
Haojun Liao 已提交
3354 3355 3356 3357

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

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

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

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

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

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

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

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

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

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

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

3443
#endif
3444

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3572 3573 3574
  return pTableGroup;
}

dengyihao's avatar
dengyihao 已提交
3575
// static bool tableFilterFp(const void* pNode, void* param) {
3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 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
//  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 已提交
3659

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  taosArrayDestroy(res);
  return ret;

_error:
3741
  return terrno;
3742
}
3743

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  taosArrayDestroy(pColumnInfoData);
  return NULL;
}

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

  taosArrayDestroy(pTableCheckInfo);
  return NULL;
}

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

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

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

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

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

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

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

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

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

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

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

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

    taosArrayDestroy(p);
  }

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

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 已提交
3925
    if (exprTreeApplyFilter(pExpr, pNode, param)) {
H
Haojun Liao 已提交
3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948
      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 已提交
3949
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3950
    pCond->start->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3951
    pCond->start->v    = queryColInfo->q;
H
Haojun Liao 已提交
3952
  } else if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
wafwerar's avatar
wafwerar 已提交
3953
    pCond->end       = taosMemoryCalloc(1, sizeof(SEndPoint));
H
Haojun Liao 已提交
3954
    pCond->end->optr = queryColInfo->optr;
Y
yihaoDeng 已提交
3955 3956
    pCond->end->v    = queryColInfo->q;
  } else if (optr == TSDB_RELATION_IN) {
wafwerar's avatar
wafwerar 已提交
3957
    pCond->start       = taosMemoryCalloc(1, sizeof(SEndPoint));
Y
yihaoDeng 已提交
3958 3959 3960
    pCond->start->optr = queryColInfo->optr;
    pCond->start->v    = queryColInfo->q; 
  } else if (optr == TSDB_RELATION_LIKE) {
H
Haojun Liao 已提交
3961
    assert(0);
3962 3963
  } else if (optr == TSDB_RELATION_MATCH) {
    assert(0);
3964 3965
  } else if (optr == TSDB_RELATION_NMATCH) {
    assert(0);
H
Haojun Liao 已提交
3966 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
  }

  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 已提交
4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061
    } 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 已提交
4062 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
    } 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 已提交
4103 4104
  taosMemoryFree(cond.start);
  taosMemoryFree(cond.end);
H
Haojun Liao 已提交
4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122
  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);
4123 4124 4125
      } else if (pQueryInfo->optr == TSDB_RELATION_LIKE ||
                 pQueryInfo->optr == TSDB_RELATION_MATCH ||
                 pQueryInfo->optr == TSDB_RELATION_NMATCH) {
H
Haojun Liao 已提交
4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141
        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 已提交
4142 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
//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 已提交
4175
#endif