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

#include <gtest/gtest.h>
#include <tglobal.h>
#include <tsort.h>
#include <iostream>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#include "os.h"

28
#include "executorimpl.h"
29 30 31
#include "executor.h"
#include "stub.h"
#include "taos.h"
H
Haojun Liao 已提交
32
#include "tdatablock.h"
33 34 35
#include "tdef.h"
#include "trpc.h"
#include "tvariant.h"
36
#include "tcompare.h"
37 38 39 40 41 42

namespace {
typedef struct {
  int32_t startVal;
  int32_t count;
  int32_t pageRows;
wmmhello's avatar
wmmhello 已提交
43
  int16_t type;
44 45
} _info;

wmmhello's avatar
wmmhello 已提交
46
int16_t VARCOUNT = 16;
47

wmmhello's avatar
wmmhello 已提交
48 49 50 51 52 53
float rand_f2()
{
  unsigned r = taosRand();
  r &= 0x007fffff;
  r |= 0x40800000;
  return *(float*)&r - 6.0;
54 55
}

wmmhello's avatar
wmmhello 已提交
56 57 58 59
static const int32_t TEST_NUMBER = 1;
#define bigendian()     ((*(char *)&TEST_NUMBER) == 0)

SSDataBlock* getSingleColDummyBlock(void* param) {
wmmhello's avatar
wmmhello 已提交
60 61 62 63 64 65 66 67 68
  _info* pInfo = (_info*) param;
  if (--pInfo->count < 0) {
    return NULL;
  }

  SSDataBlock* pBlock = static_cast<SSDataBlock*>(taosMemoryCalloc(1, sizeof(SSDataBlock)));
  pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));

  SColumnInfoData colInfo = {0};
wmmhello's avatar
wmmhello 已提交
69 70 71 72 73 74 75 76 77 78 79 80
  colInfo.info.type = pInfo->type;
  if (pInfo->type == TSDB_DATA_TYPE_NCHAR){
    colInfo.info.bytes = TSDB_NCHAR_SIZE * VARCOUNT + VARSTR_HEADER_SIZE;
    colInfo.varmeta.offset = static_cast<int32_t *>(taosMemoryCalloc(pInfo->pageRows, sizeof(int32_t)));
  } else if(pInfo->type == TSDB_DATA_TYPE_BINARY) {
    colInfo.info.bytes = VARCOUNT + VARSTR_HEADER_SIZE;
    colInfo.varmeta.offset = static_cast<int32_t *>(taosMemoryCalloc(pInfo->pageRows, sizeof(int32_t)));
  } else{
    colInfo.info.bytes = tDataTypes[pInfo->type].bytes;
    colInfo.pData = static_cast<char*>(taosMemoryCalloc(pInfo->pageRows, colInfo.info.bytes));
    colInfo.nullbitmap = static_cast<char*>(taosMemoryCalloc(1, (pInfo->pageRows + 7) / 8));
  }
wmmhello's avatar
wmmhello 已提交
81 82 83 84 85 86 87
  colInfo.info.colId = 1;

  taosArrayPush(pBlock->pDataBlock, &colInfo);

  for (int32_t i = 0; i < pInfo->pageRows; ++i) {
    SColumnInfoData* pColInfo = static_cast<SColumnInfoData*>(TARRAY_GET_ELEM(pBlock->pDataBlock, 0));

wmmhello's avatar
wmmhello 已提交
88 89 90 91 92 93
    if (pInfo->type == TSDB_DATA_TYPE_NCHAR){
      int32_t size = taosRand() % VARCOUNT;
      char str[128] = {0};
      char strOri[128] = {0};
      taosRandStr(strOri, size);
      int32_t len = 0;
wmmhello's avatar
wmmhello 已提交
94
      bool ret = taosMbsToUcs4(strOri, size, (TdUcs4*)varDataVal(str), size * TSDB_NCHAR_SIZE, &len);
wmmhello's avatar
wmmhello 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
      if (!ret){
        printf("error\n");
        return NULL;
      }
      varDataSetLen(str, len);
      colDataAppend(pColInfo, i, reinterpret_cast<const char*>(str), false);
      pBlock->info.hasVarCol = true;
      printf("nchar: %s\n",strOri);
    } else if(pInfo->type == TSDB_DATA_TYPE_BINARY){
      int32_t size = taosRand() % VARCOUNT;
      char str[64] = {0};
      taosRandStr(varDataVal(str), size);
      varDataSetLen(str, size);
      colDataAppend(pColInfo, i, reinterpret_cast<const char*>(str), false);
      pBlock->info.hasVarCol = true;
      printf("binary: %s\n", varDataVal(str));
    } else if(pInfo->type == TSDB_DATA_TYPE_DOUBLE || pInfo->type == TSDB_DATA_TYPE_FLOAT) {
      double v = rand_f2();
      colDataAppend(pColInfo, i, reinterpret_cast<const char*>(&v), false);
      printf("float: %f\n", v);
    } else{
      int64_t v = ++pInfo->startVal;
      char *result = static_cast<char*>(taosMemoryCalloc(tDataTypes[pInfo->type].bytes, 1));
      if (!bigendian()){
        memcpy(result, &v, tDataTypes[pInfo->type].bytes);
      }else{
        memcpy(result, (char*)(&v) + sizeof(int64_t) - tDataTypes[pInfo->type].bytes, tDataTypes[pInfo->type].bytes);
      }

      colDataAppend(pColInfo, i, result, false);
wmmhello's avatar
wmmhello 已提交
125 126
      printf("int: %ld\n", v);
      taosMemoryFree(result);
wmmhello's avatar
wmmhello 已提交
127
    }
wmmhello's avatar
wmmhello 已提交
128 129 130 131 132 133 134 135
  }

  pBlock->info.rows = pInfo->pageRows;
  pBlock->info.numOfCols = 1;
  return pBlock;
}


136 137 138 139 140
int32_t docomp(const void* p1, const void* p2, void* param) {
  int32_t pLeftIdx  = *(int32_t *)p1;
  int32_t pRightIdx = *(int32_t *)p2;

  SMsortComparParam *pParam = (SMsortComparParam *)param;
wmmhello's avatar
wmmhello 已提交
141
  SSortSource** px = reinterpret_cast<SSortSource**>(pParam->pSources);
142 143 144

  SArray *pInfo = pParam->orderInfo;

wmmhello's avatar
wmmhello 已提交
145 146
  SSortSource* pLeftSource  = px[pLeftIdx];
  SSortSource* pRightSource = px[pRightIdx];
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

  // this input is exhausted, set the special value to denote this
  if (pLeftSource->src.rowIndex == -1) {
    return 1;
  }

  if (pRightSource->src.rowIndex == -1) {
    return -1;
  }

  SSDataBlock* pLeftBlock = pLeftSource->src.pBlock;
  SSDataBlock* pRightBlock = pRightSource->src.pBlock;

  for(int32_t i = 0; i < pInfo->size; ++i) {
    SBlockOrderInfo* pOrder = (SBlockOrderInfo*)TARRAY_GET_ELEM(pInfo, i);

H
Haojun Liao 已提交
163
    SColumnInfoData* pLeftColInfoData = (SColumnInfoData*)TARRAY_GET_ELEM(pLeftBlock->pDataBlock, pOrder->slotId);
164 165 166 167 168 169

    bool leftNull  = false;
    if (pLeftColInfoData->hasNull) {
      leftNull = colDataIsNull(pLeftColInfoData, pLeftBlock->info.rows, pLeftSource->src.rowIndex, pLeftBlock->pBlockAgg);
    }

H
Haojun Liao 已提交
170
    SColumnInfoData* pRightColInfoData = (SColumnInfoData*) TARRAY_GET_ELEM(pRightBlock->pDataBlock, pOrder->slotId);
171 172 173 174 175 176 177 178 179 180
    bool rightNull = false;
    if (pRightColInfoData->hasNull) {
      rightNull = colDataIsNull(pRightColInfoData, pRightBlock->info.rows, pRightSource->src.rowIndex, pRightBlock->pBlockAgg);
    }

    if (leftNull && rightNull) {
      continue; // continue to next slot
    }

    if (rightNull) {
wmmhello's avatar
wmmhello 已提交
181
      return pOrder->nullFirst? 1:-1;
182 183 184
    }

    if (leftNull) {
wmmhello's avatar
wmmhello 已提交
185
      return pOrder->nullFirst? -1:1;
186 187
    }

188 189
    void* left1  = colDataGetData(pLeftColInfoData, pLeftSource->src.rowIndex);
    void* right1 = colDataGetData(pRightColInfoData, pRightSource->src.rowIndex);
190
    __compar_fn_t fn = getKeyComparFunc(pLeftColInfoData->info.type, pOrder->order);
191

192 193 194 195 196
    int ret = fn(left1, right1);
    if (ret == 0) {
      continue;
    } else {
      return ret;
197 198
    }
  }
H
Haojun Liao 已提交
199 200

  return 0;
201 202 203
}
}  // namespace

wmmhello's avatar
wmmhello 已提交
204
#if 1
205
TEST(testCase, inMem_sort_Test) {
H
Haojun Liao 已提交
206 207
  SBlockOrderInfo oi = {0};
  oi.order = TSDB_ORDER_ASC;
208
  oi.slotId = 0;
H
Haojun Liao 已提交
209 210 211
  SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
  taosArrayPush(orderInfo, &oi);

212
  SSortHandle* phandle = tsortCreateSortHandle(orderInfo, NULL, SORT_SINGLESOURCE_SORT, 1024, 5, NULL, "test_abc");
H
Haojun Liao 已提交
213
  tsortSetFetchRawDataFp(phandle, getSingleColDummyBlock);
214 215 216 217 218

  _info* pInfo = (_info*) taosMemoryCalloc(1, sizeof(_info));
  pInfo->startVal = 0;
  pInfo->pageRows = 100;
  pInfo->count = 6;
wmmhello's avatar
wmmhello 已提交
219
  pInfo->type = TSDB_DATA_TYPE_USMALLINT;
220

wmmhello's avatar
wmmhello 已提交
221
  SSortSource* ps = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
222 223
  ps->param = pInfo;
  tsortAddSource(phandle, ps);
H
Haojun Liao 已提交
224

H
Haojun Liao 已提交
225
  int32_t code = tsortOpen(phandle);
226
  int32_t row = 1;
wmmhello's avatar
wmmhello 已提交
227
  taosMemoryFreeClear(ps);
228 229

  while(1) {
H
Haojun Liao 已提交
230
    STupleHandle* pTupleHandle = tsortNextTuple(phandle);
231 232 233 234
    if (pTupleHandle == NULL) {
      break;
    }

H
Haojun Liao 已提交
235
    void* v = tsortGetValue(pTupleHandle, 0);
wmmhello's avatar
wmmhello 已提交
236 237
    printf("%d: %d\n", row, *(uint16_t*) v);
    ASSERT_EQ(row++, *(uint16_t*) v);
238 239

  }
wmmhello's avatar
wmmhello 已提交
240
  taosArrayDestroy(orderInfo);
H
Haojun Liao 已提交
241
  tsortDestroySortHandle(phandle);
wmmhello's avatar
wmmhello 已提交
242
  taosMemoryFree(pInfo);
243 244 245
}

TEST(testCase, external_mem_sort_Test) {
H
Haojun Liao 已提交
246

wmmhello's avatar
wmmhello 已提交
247
  _info* pInfo = (_info*) taosMemoryCalloc(8, sizeof(_info));
wmmhello's avatar
wmmhello 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
  pInfo[0].startVal = 0;
  pInfo[0].pageRows = 10;
  pInfo[0].count = 6;
  pInfo[0].type = TSDB_DATA_TYPE_BOOL;

  pInfo[1].startVal = 0;
  pInfo[1].pageRows = 10;
  pInfo[1].count = 6;
  pInfo[1].type = TSDB_DATA_TYPE_TINYINT;

  pInfo[2].startVal = 0;
  pInfo[2].pageRows = 100;
  pInfo[2].count = 6;
  pInfo[2].type = TSDB_DATA_TYPE_USMALLINT;

  pInfo[3].startVal = 0;
  pInfo[3].pageRows = 100;
  pInfo[3].count = 6;
wmmhello's avatar
wmmhello 已提交
266
  pInfo[3].type = TSDB_DATA_TYPE_INT;
wmmhello's avatar
wmmhello 已提交
267 268 269 270

  pInfo[4].startVal = 0;
  pInfo[4].pageRows = 100;
  pInfo[4].count = 6;
wmmhello's avatar
wmmhello 已提交
271
  pInfo[4].type = TSDB_DATA_TYPE_UBIGINT;
wmmhello's avatar
wmmhello 已提交
272 273

  pInfo[5].startVal = 0;
wmmhello's avatar
wmmhello 已提交
274
  pInfo[5].pageRows = 100;
wmmhello's avatar
wmmhello 已提交
275
  pInfo[5].count = 6;
wmmhello's avatar
wmmhello 已提交
276
  pInfo[5].type = TSDB_DATA_TYPE_DOUBLE;
wmmhello's avatar
wmmhello 已提交
277 278

  pInfo[6].startVal = 0;
wmmhello's avatar
wmmhello 已提交
279
  pInfo[6].pageRows = 50;
wmmhello's avatar
wmmhello 已提交
280
  pInfo[6].count = 6;
wmmhello's avatar
wmmhello 已提交
281 282 283 284 285 286
  pInfo[6].type = TSDB_DATA_TYPE_NCHAR;

  pInfo[7].startVal = 0;
  pInfo[7].pageRows = 100;
  pInfo[7].count = 6;
  pInfo[7].type = TSDB_DATA_TYPE_BINARY;
wmmhello's avatar
wmmhello 已提交
287

wmmhello's avatar
wmmhello 已提交
288
  for (int i = 0; i < 8; i++){
wmmhello's avatar
wmmhello 已提交
289
    SBlockOrderInfo oi = {0};
wmmhello's avatar
wmmhello 已提交
290 291 292 293 294 295 296

    if(pInfo[i].type == TSDB_DATA_TYPE_NCHAR){
      oi.order = TSDB_ORDER_DESC;
    }else{
      oi.order = TSDB_ORDER_ASC;
    }

wmmhello's avatar
wmmhello 已提交
297 298 299 300
    oi.slotId = 0;
    SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
    taosArrayPush(orderInfo, &oi);

301
    SSortHandle* phandle = tsortCreateSortHandle(orderInfo, NULL, SORT_SINGLESOURCE_SORT, 128, 3, NULL, "test_abc");
wmmhello's avatar
wmmhello 已提交
302 303
    tsortSetFetchRawDataFp(phandle, getSingleColDummyBlock);

wmmhello's avatar
wmmhello 已提交
304
    SSortSource* ps = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
wmmhello's avatar
wmmhello 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
    ps->param = &pInfo[i];

    tsortAddSource(phandle, ps);

    int32_t code = tsortOpen(phandle);
    int32_t row = 1;
    taosMemoryFreeClear(ps);

    printf("--------start with %s-----------\n", tDataTypes[pInfo[i].type].name);
    while(1) {
      STupleHandle* pTupleHandle = tsortNextTuple(phandle);
      if (pTupleHandle == NULL) {
        break;
      }

      void* v = tsortGetValue(pTupleHandle, 0);

      if(pInfo[i].type == TSDB_DATA_TYPE_NCHAR){
        char        buf[128] = {0};
        int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(v), varDataLen(v), buf);
        printf("%d: %s\n", row++, buf);
      }else if(pInfo[i].type == TSDB_DATA_TYPE_BINARY){
        char        buf[128] = {0};
        memcpy(buf, varDataVal(v), varDataLen(v));
        printf("%d: %s\n", row++, buf);
wmmhello's avatar
wmmhello 已提交
330 331 332 333
      }else if(pInfo[i].type == TSDB_DATA_TYPE_DOUBLE) {
        printf("double: %lf\n", *(double*)v);
      }else if (pInfo[i].type == TSDB_DATA_TYPE_FLOAT) {
        printf("float: %f\n", *(float*)v);
wmmhello's avatar
wmmhello 已提交
334 335 336 337 338 339 340
      }else{
        int64_t result = 0;
        if (!bigendian()){
          memcpy(&result, v, tDataTypes[pInfo[i].type].bytes);
        }else{
          memcpy((char*)(&result) + sizeof(int64_t) - tDataTypes[pInfo[i].type].bytes, v, tDataTypes[pInfo[i].type].bytes);
        }
wmmhello's avatar
wmmhello 已提交
341
        printf("%d: %ld\n", row++, result);
wmmhello's avatar
wmmhello 已提交
342
      }
H
Haojun Liao 已提交
343
    }
wmmhello's avatar
wmmhello 已提交
344 345
    taosArrayDestroy(orderInfo);
    tsortDestroySortHandle(phandle);
H
Haojun Liao 已提交
346
  }
wmmhello's avatar
wmmhello 已提交
347
  taosMemoryFree(pInfo);
H
Haojun Liao 已提交
348
}
349

350 351 352
TEST(testCase, ordered_merge_sort_Test) {
  SBlockOrderInfo oi = {0};
  oi.order = TSDB_ORDER_ASC;
353
  oi.slotId = 0;
354 355 356
  SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
  taosArrayPush(orderInfo, &oi);

wmmhello's avatar
wmmhello 已提交
357 358 359 360 361 362 363 364 365 366 367
  SSDataBlock* pBlock = static_cast<SSDataBlock*>(taosMemoryCalloc(1, sizeof(SSDataBlock)));
  pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
  pBlock->info.numOfCols = 1;
  for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
    SColumnInfoData colInfo = {0};
    colInfo.info.type = TSDB_DATA_TYPE_INT;
    colInfo.info.bytes = sizeof(int32_t);
    colInfo.info.colId = 1;
    taosArrayPush(pBlock->pDataBlock, &colInfo);
  }

368
  SSortHandle* phandle = tsortCreateSortHandle(orderInfo, NULL, SORT_MULTISOURCE_MERGE, 1024, 5, pBlock,"test_abc");
H
Haojun Liao 已提交
369 370
  tsortSetFetchRawDataFp(phandle, getSingleColDummyBlock);
  tsortSetComparFp(phandle, docomp);
371

wmmhello's avatar
wmmhello 已提交
372
  SSortSource* p[10] = {0};
wmmhello's avatar
wmmhello 已提交
373
  _info c[10] = {0};
374
  for(int32_t i = 0; i < 10; ++i) {
wmmhello's avatar
wmmhello 已提交
375
    p[i] = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
wmmhello's avatar
wmmhello 已提交
376 377 378 379 380
    c[i].count    = 1;
    c[i].pageRows = 1000;
    c[i].startVal = i*1000;
    c[i].type = TSDB_DATA_TYPE_INT;

wmmhello's avatar
wmmhello 已提交
381 382
    p[i]->param = &c[i];
    tsortAddSource(phandle, p[i]);
383 384
  }

H
Haojun Liao 已提交
385
  int32_t code = tsortOpen(phandle);
386 387 388
  int32_t row = 1;

  while(1) {
H
Haojun Liao 已提交
389
    STupleHandle* pTupleHandle = tsortNextTuple(phandle);
390 391 392 393
    if (pTupleHandle == NULL) {
      break;
    }

H
Haojun Liao 已提交
394
    void* v = tsortGetValue(pTupleHandle, 0);
395 396
    printf("%d: %d\n", row, *(int32_t*) v);
    ASSERT_EQ(row++, *(int32_t*) v);
397 398

  }
wmmhello's avatar
wmmhello 已提交
399 400

  taosArrayDestroy(orderInfo);
H
Haojun Liao 已提交
401
  tsortDestroySortHandle(phandle);
wmmhello's avatar
wmmhello 已提交
402
  blockDataDestroy(pBlock);
403 404 405
}

#endif
406 407

#pragma GCC diagnostic pop