sortTests.cpp 11.5 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
#include "executor.h"
#include "taos.h"
H
Haojun Liao 已提交
31
#include "tdatablock.h"
32 33 34
#include "tdef.h"
#include "trpc.h"
#include "tvariant.h"
35
#include "tcompare.h"
36 37 38 39 40 41

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

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

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

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

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

64
  SSDataBlock* pBlock = createDataBlock();
wmmhello's avatar
wmmhello 已提交
65 66

  SColumnInfoData colInfo = {0};
wmmhello's avatar
wmmhello 已提交
67 68 69 70 71 72 73 74
  colInfo.info.type = pInfo->type;
  if (pInfo->type == TSDB_DATA_TYPE_NCHAR){
    colInfo.info.bytes = TSDB_NCHAR_SIZE * VARCOUNT + VARSTR_HEADER_SIZE;
  } else if(pInfo->type == TSDB_DATA_TYPE_BINARY) {
    colInfo.info.bytes = VARCOUNT + VARSTR_HEADER_SIZE;
  } else{
    colInfo.info.bytes = tDataTypes[pInfo->type].bytes;
  }
wmmhello's avatar
wmmhello 已提交
75 76
  colInfo.info.colId = 1;

77 78
  blockDataAppendColInfo(pBlock, &colInfo);
  blockDataEnsureCapacity(pBlock, pInfo->pageRows);
wmmhello's avatar
wmmhello 已提交
79 80 81 82

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

wmmhello's avatar
wmmhello 已提交
83 84 85 86 87 88
    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 已提交
89
      bool ret = taosMbsToUcs4(strOri, size, (TdUcs4*)varDataVal(str), size * TSDB_NCHAR_SIZE, &len);
wmmhello's avatar
wmmhello 已提交
90 91 92 93 94 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
      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);
S
Shengliang Guan 已提交
120
      printf("int: %" PRId64 "\n", v);
wmmhello's avatar
wmmhello 已提交
121
      taosMemoryFree(result);
wmmhello's avatar
wmmhello 已提交
122
    }
wmmhello's avatar
wmmhello 已提交
123 124 125 126 127 128 129
  }

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


130 131 132 133 134
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 已提交
135
  SSortSource** px = reinterpret_cast<SSortSource**>(pParam->pSources);
136 137 138

  SArray *pInfo = pParam->orderInfo;

wmmhello's avatar
wmmhello 已提交
139 140
  SSortSource* pLeftSource  = px[pLeftIdx];
  SSortSource* pRightSource = px[pRightIdx];
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

  // 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 已提交
157
    SColumnInfoData* pLeftColInfoData = (SColumnInfoData*)TARRAY_GET_ELEM(pLeftBlock->pDataBlock, pOrder->slotId);
158 159 160

    bool leftNull  = false;
    if (pLeftColInfoData->hasNull) {
161
      leftNull = colDataIsNull(pLeftColInfoData, pLeftBlock->info.rows, pLeftSource->src.rowIndex, pLeftBlock->pBlockAgg[pOrder->slotId]);
162 163
    }

H
Haojun Liao 已提交
164
    SColumnInfoData* pRightColInfoData = (SColumnInfoData*) TARRAY_GET_ELEM(pRightBlock->pDataBlock, pOrder->slotId);
165 166
    bool rightNull = false;
    if (pRightColInfoData->hasNull) {
167
      rightNull = colDataIsNull(pRightColInfoData, pRightBlock->info.rows, pRightSource->src.rowIndex, pRightBlock->pBlockAgg[pOrder->slotId]);
168 169 170 171 172 173 174
    }

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

    if (rightNull) {
wmmhello's avatar
wmmhello 已提交
175
      return pOrder->nullFirst? 1:-1;
176 177 178
    }

    if (leftNull) {
wmmhello's avatar
wmmhello 已提交
179
      return pOrder->nullFirst? -1:1;
180 181
    }

182 183
    void* left1  = colDataGetData(pLeftColInfoData, pLeftSource->src.rowIndex);
    void* right1 = colDataGetData(pRightColInfoData, pRightSource->src.rowIndex);
184
    __compar_fn_t fn = getKeyComparFunc(pLeftColInfoData->info.type, pOrder->order);
185

186 187 188 189 190
    int ret = fn(left1, right1);
    if (ret == 0) {
      continue;
    } else {
      return ret;
191 192
    }
  }
H
Haojun Liao 已提交
193 194

  return 0;
195 196 197
}
}  // namespace

H
Haojun Liao 已提交
198
#if 0
199
TEST(testCase, inMem_sort_Test) {
H
Haojun Liao 已提交
200 201
  SBlockOrderInfo oi = {0};
  oi.order = TSDB_ORDER_ASC;
202
  oi.slotId = 0;
H
Haojun Liao 已提交
203 204 205
  SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
  taosArrayPush(orderInfo, &oi);

206
  SSortHandle* phandle = tsortCreateSortHandle(orderInfo, SORT_SINGLESOURCE_SORT, 1024, 5, NULL, "test_abc");
207
  tsortSetFetchRawDataFp(phandle, getSingleColDummyBlock, NULL, NULL);
208 209 210 211 212

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

wmmhello's avatar
wmmhello 已提交
215
  SSortSource* ps = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
216 217
  ps->param = pInfo;
  tsortAddSource(phandle, ps);
H
Haojun Liao 已提交
218

H
Haojun Liao 已提交
219
  int32_t code = tsortOpen(phandle);
220
  int32_t row = 1;
wmmhello's avatar
wmmhello 已提交
221
  taosMemoryFreeClear(ps);
222 223

  while(1) {
H
Haojun Liao 已提交
224
    STupleHandle* pTupleHandle = tsortNextTuple(phandle);
225 226 227 228
    if (pTupleHandle == NULL) {
      break;
    }

H
Haojun Liao 已提交
229
    void* v = tsortGetValue(pTupleHandle, 0);
wmmhello's avatar
wmmhello 已提交
230 231
    printf("%d: %d\n", row, *(uint16_t*) v);
    ASSERT_EQ(row++, *(uint16_t*) v);
232 233

  }
wmmhello's avatar
wmmhello 已提交
234
  taosArrayDestroy(orderInfo);
H
Haojun Liao 已提交
235
  tsortDestroySortHandle(phandle);
wmmhello's avatar
wmmhello 已提交
236
  taosMemoryFree(pInfo);
237 238 239
}

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

wmmhello's avatar
wmmhello 已提交
241
  _info* pInfo = (_info*) taosMemoryCalloc(8, sizeof(_info));
wmmhello's avatar
wmmhello 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
  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 已提交
260
  pInfo[3].type = TSDB_DATA_TYPE_INT;
wmmhello's avatar
wmmhello 已提交
261 262 263 264

  pInfo[4].startVal = 0;
  pInfo[4].pageRows = 100;
  pInfo[4].count = 6;
wmmhello's avatar
wmmhello 已提交
265
  pInfo[4].type = TSDB_DATA_TYPE_UBIGINT;
wmmhello's avatar
wmmhello 已提交
266 267

  pInfo[5].startVal = 0;
wmmhello's avatar
wmmhello 已提交
268
  pInfo[5].pageRows = 100;
wmmhello's avatar
wmmhello 已提交
269
  pInfo[5].count = 6;
wmmhello's avatar
wmmhello 已提交
270
  pInfo[5].type = TSDB_DATA_TYPE_DOUBLE;
wmmhello's avatar
wmmhello 已提交
271 272

  pInfo[6].startVal = 0;
wmmhello's avatar
wmmhello 已提交
273
  pInfo[6].pageRows = 50;
wmmhello's avatar
wmmhello 已提交
274
  pInfo[6].count = 6;
wmmhello's avatar
wmmhello 已提交
275 276 277 278 279 280
  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 已提交
281

wmmhello's avatar
wmmhello 已提交
282
  for (int i = 0; i < 8; i++){
wmmhello's avatar
wmmhello 已提交
283
    SBlockOrderInfo oi = {0};
wmmhello's avatar
wmmhello 已提交
284 285 286 287 288 289 290

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

wmmhello's avatar
wmmhello 已提交
291 292 293 294
    oi.slotId = 0;
    SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
    taosArrayPush(orderInfo, &oi);

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

wmmhello's avatar
wmmhello 已提交
298
    SSortSource* ps = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
wmmhello's avatar
wmmhello 已提交
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
    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 已提交
324 325 326 327
      }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 已提交
328 329 330 331 332 333 334
      }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);
        }
S
Shengliang Guan 已提交
335
        printf("%d: %" PRId64 "\n", row++, result);
wmmhello's avatar
wmmhello 已提交
336
      }
H
Haojun Liao 已提交
337
    }
wmmhello's avatar
wmmhello 已提交
338 339
    taosArrayDestroy(orderInfo);
    tsortDestroySortHandle(phandle);
H
Haojun Liao 已提交
340
  }
wmmhello's avatar
wmmhello 已提交
341
  taosMemoryFree(pInfo);
H
Haojun Liao 已提交
342
}
343

344 345 346
TEST(testCase, ordered_merge_sort_Test) {
  SBlockOrderInfo oi = {0};
  oi.order = TSDB_ORDER_ASC;
347
  oi.slotId = 0;
348 349 350
  SArray* orderInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
  taosArrayPush(orderInfo, &oi);

351 352 353 354
  SSDataBlock* pBlock = createDataBlock();
  for (int32_t i = 0; i < 1; ++i) {
    SColumnInfoData colInfo = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1);
    blockDataAppendColInfo(pBlock, &colInfo);
wmmhello's avatar
wmmhello 已提交
355 356
  }

357
  SSortHandle* phandle = tsortCreateSortHandle(orderInfo, SORT_MULTISOURCE_MERGE, 1024, 5, pBlock,"test_abc");
358
  tsortSetFetchRawDataFp(phandle, getSingleColDummyBlock, NULL, NULL);
H
Haojun Liao 已提交
359
  tsortSetComparFp(phandle, docomp);
360

wmmhello's avatar
wmmhello 已提交
361
  SSortSource* p[10] = {0};
wmmhello's avatar
wmmhello 已提交
362
  _info c[10] = {0};
363
  for(int32_t i = 0; i < 10; ++i) {
wmmhello's avatar
wmmhello 已提交
364
    p[i] = static_cast<SSortSource*>(taosMemoryCalloc(1, sizeof(SSortSource)));
wmmhello's avatar
wmmhello 已提交
365 366 367 368 369
    c[i].count    = 1;
    c[i].pageRows = 1000;
    c[i].startVal = i*1000;
    c[i].type = TSDB_DATA_TYPE_INT;

wmmhello's avatar
wmmhello 已提交
370 371
    p[i]->param = &c[i];
    tsortAddSource(phandle, p[i]);
372 373
  }

H
Haojun Liao 已提交
374
  int32_t code = tsortOpen(phandle);
375 376 377
  int32_t row = 1;

  while(1) {
H
Haojun Liao 已提交
378
    STupleHandle* pTupleHandle = tsortNextTuple(phandle);
379 380 381 382
    if (pTupleHandle == NULL) {
      break;
    }

H
Haojun Liao 已提交
383
    void* v = tsortGetValue(pTupleHandle, 0);
H
Haojun Liao 已提交
384
//    printf("%d: %d\n", row, *(int32_t*) v);
385
    ASSERT_EQ(row++, *(int32_t*) v);
386 387

  }
wmmhello's avatar
wmmhello 已提交
388 389

  taosArrayDestroy(orderInfo);
H
Haojun Liao 已提交
390
  tsortDestroySortHandle(phandle);
wmmhello's avatar
wmmhello 已提交
391
  blockDataDestroy(pBlock);
392 393 394
}

#endif
395 396

#pragma GCC diagnostic pop