sortTests.cpp 11.6 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 28
/*
 * 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"

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

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

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

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

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

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

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

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

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

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

      colDataAppend(pColInfo, i, result, false);
S
Shengliang Guan 已提交
119
      printf("int: %" PRId64 "\n", v);
wmmhello's avatar
wmmhello 已提交
120
      taosMemoryFree(result);
wmmhello's avatar
wmmhello 已提交
121
    }
wmmhello's avatar
wmmhello 已提交
122 123 124 125 126 127
  }

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

128
int32_t docomp(const void* p1, const void* p2, void* param) {
H
Hongze Cheng 已提交
129 130
  int32_t pLeftIdx = *(int32_t*)p1;
  int32_t pRightIdx = *(int32_t*)p2;
131

H
Hongze Cheng 已提交
132 133
  SMsortComparParam* pParam = (SMsortComparParam*)param;
  SSortSource**      px = reinterpret_cast<SSortSource**>(pParam->pSources);
134

H
Hongze Cheng 已提交
135
  SArray* pInfo = pParam->orderInfo;
136

H
Hongze Cheng 已提交
137
  SSortSource* pLeftSource = px[pLeftIdx];
wmmhello's avatar
wmmhello 已提交
138
  SSortSource* pRightSource = px[pRightIdx];
139 140 141 142 143 144 145 146 147 148 149 150 151

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

H
Hongze Cheng 已提交
152
  for (int32_t i = 0; i < pInfo->size; ++i) {
153 154
    SBlockOrderInfo* pOrder = (SBlockOrderInfo*)TARRAY_GET_ELEM(pInfo, i);

H
Haojun Liao 已提交
155
    SColumnInfoData* pLeftColInfoData = (SColumnInfoData*)TARRAY_GET_ELEM(pLeftBlock->pDataBlock, pOrder->slotId);
156

H
Hongze Cheng 已提交
157
    bool leftNull = false;
158
    if (pLeftColInfoData->hasNull) {
H
Hongze Cheng 已提交
159 160
      leftNull = colDataIsNull(pLeftColInfoData, pLeftBlock->info.rows, pLeftSource->src.rowIndex,
                               pLeftBlock->pBlockAgg[pOrder->slotId]);
161 162
    }

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

    if (leftNull && rightNull) {
H
Hongze Cheng 已提交
171
      continue;  // continue to next slot
172 173 174
    }

    if (rightNull) {
H
Hongze Cheng 已提交
175
      return pOrder->nullFirst ? 1 : -1;
176 177 178
    }

    if (leftNull) {
H
Hongze Cheng 已提交
179
      return pOrder->nullFirst ? -1 : 1;
180 181
    }

H
Hongze Cheng 已提交
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