taosdemo.c 366.4 KB
Newer Older
S
TD-1057  
Shengliang Guan 已提交
1
/*
H
hzcheng 已提交
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/>.
 */

16 17 18

/*
   when in some thread query return error, thread don't exit, but return, otherwise coredump in other thread.
19
   */
20

21
#include <stdint.h>
22
#include <taos.h>
S
slguan 已提交
23
#define _GNU_SOURCE
24 25
#define CURL_STATICLIB

S
TD-1057  
Shengliang Guan 已提交
26
#ifdef LINUX
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#include <argp.h>
#include <inttypes.h>
#ifndef _ALPINE
#include <error.h>
#endif
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <wordexp.h>
#include <regex.h>
42
#else
43 44
#include <regex.h>
#include <stdio.h>
45
#endif
H
hzcheng 已提交
46

47
#include <assert.h>
48
#include <stdlib.h>
49 50
#include "cJSON.h"

51
#include "os.h"
H
hzcheng 已提交
52
#include "taos.h"
53
#include "taoserror.h"
H
Hui Li 已提交
54
#include "tutil.h"
S
slguan 已提交
55

56 57 58
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

S
slguan 已提交
59 60
extern char configDir[];

61 62
#define STR_INSERT_INTO     "INSERT INTO "

63 64
#define MAX_RECORDS_PER_REQ     32766

65
#define HEAD_BUFF_LEN       TSDB_MAX_COLUMNS*24  // 16*MAX_COLUMNS + (192+32)*2 + insert into ..
66

67
#define BUFFER_SIZE         TSDB_MAX_ALLOWED_SQL_LEN
68
#define COND_BUF_LEN        (BUFFER_SIZE - 30)
69
#define COL_BUFFER_LEN      ((TSDB_COL_NAME_LEN + 15) * TSDB_MAX_COLUMNS)
70

71
#define MAX_USERNAME_SIZE  64
72
#define MAX_HOSTNAME_SIZE  253      // https://man7.org/linux/man-pages/man7/hostname.7.html
73
#define MAX_TB_NAME_SIZE   64
74
#define MAX_DATA_SIZE      (16*TSDB_MAX_COLUMNS)+20     // max record len: 16*MAX_COLUMNS, timestamp string and ,('') need extra space
75
#define OPT_ABORT          1 /* –abort */
76
#define MAX_FILE_NAME_LEN  256              // max file name length on linux is 255.
77

78 79
#define DEFAULT_START_TIME 1500000000000

80 81 82 83 84 85 86 87 88 89
#define MAX_PREPARED_RAND  1000000
#define INT_BUFF_LEN            11
#define BIGINT_BUFF_LEN         21
#define SMALLINT_BUFF_LEN       6
#define TINYINT_BUFF_LEN        4
#define BOOL_BUFF_LEN           6
#define FLOAT_BUFF_LEN          22
#define DOUBLE_BUFF_LEN         42
#define TIMESTAMP_BUFF_LEN      21

90 91
#define MAX_SAMPLES_ONCE_FROM_FILE   10000
#define MAX_NUM_COLUMNS        (TSDB_MAX_COLUMNS - 1)      // exclude first column timestamp
92

93 94
#define MAX_DB_COUNT            8
#define MAX_SUPER_TABLE_COUNT   200
95

96
#define MAX_QUERY_SQL_COUNT     100
97

98 99
#define MAX_DATABASE_COUNT      256
#define INPUT_BUF_LEN           256
100

101 102 103 104 105
#define TBNAME_PREFIX_LEN       (TSDB_TABLE_NAME_LEN - 20) // 20 characters reserved for seq
#define SMALL_BUFF_LEN          8
#define DATATYPE_BUFF_LEN       (SMALL_BUFF_LEN*3)
#define NOTE_BUFF_LEN           (SMALL_BUFF_LEN*16)

106
#define DEFAULT_TIMESTAMP_STEP  1
107 108
#define DEFAULT_INTERLACE_ROWS  0
#define DEFAULT_DATATYPE_NUM    3
109
#define DEFAULT_CHILDTABLES     10000
110

111

112 113 114 115 116 117 118
enum TEST_MODE {
    INSERT_TEST,            // 0
    QUERY_TEST,             // 1
    SUBSCRIBE_TEST,         // 2
    INVAID_TEST
};

119
typedef enum CREATE_SUB_TALBE_MOD_EN {
120 121 122
    PRE_CREATE_SUBTBL,
    AUTO_CREATE_SUBTBL,
    NO_CREATE_SUBTBL
123
} CREATE_SUB_TALBE_MOD_EN;
124

125
typedef enum TALBE_EXISTS_EN {
126 127 128
    TBL_NO_EXISTS,
    TBL_ALREADY_EXISTS,
    TBL_EXISTS_BUTT
129 130
} TALBE_EXISTS_EN;

131
enum enumSYNC_MODE {
132 133 134
    SYNC_MODE,
    ASYNC_MODE,
    MODE_BUT
135
};
136

S
Shuduo Sang 已提交
137
enum enum_TAOS_INTERFACE {
138 139 140
    TAOSC_IFACE,
    REST_IFACE,
    STMT_IFACE,
141 142 143
    INTERFACE_BUT
};

144 145 146 147 148 149
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

S
Shuduo Sang 已提交
150
typedef enum enum_PROGRESSIVE_OR_INTERLACE {
151 152 153
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
154
} PROG_OR_INTERLACE_MODE;
155

156
typedef enum enumQUERY_TYPE {
157 158 159
    NO_INSERT_TYPE,
    INSERT_TYPE,
    QUERY_TYPE_BUT
160
} QUERY_TYPE;
161 162

enum _show_db_index {
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    TSDB_SHOW_DB_NAME_INDEX,
    TSDB_SHOW_DB_CREATED_TIME_INDEX,
    TSDB_SHOW_DB_NTABLES_INDEX,
    TSDB_SHOW_DB_VGROUPS_INDEX,
    TSDB_SHOW_DB_REPLICA_INDEX,
    TSDB_SHOW_DB_QUORUM_INDEX,
    TSDB_SHOW_DB_DAYS_INDEX,
    TSDB_SHOW_DB_KEEP_INDEX,
    TSDB_SHOW_DB_CACHE_INDEX,
    TSDB_SHOW_DB_BLOCKS_INDEX,
    TSDB_SHOW_DB_MINROWS_INDEX,
    TSDB_SHOW_DB_MAXROWS_INDEX,
    TSDB_SHOW_DB_WALLEVEL_INDEX,
    TSDB_SHOW_DB_FSYNC_INDEX,
    TSDB_SHOW_DB_COMP_INDEX,
    TSDB_SHOW_DB_CACHELAST_INDEX,
    TSDB_SHOW_DB_PRECISION_INDEX,
    TSDB_SHOW_DB_UPDATE_INDEX,
    TSDB_SHOW_DB_STATUS_INDEX,
    TSDB_MAX_SHOW_DB
183 184 185 186
};

// -----------------------------------------SHOW TABLES CONFIGURE -------------------------------------
enum _show_stables_index {
187 188 189 190 191 192 193 194
    TSDB_SHOW_STABLES_NAME_INDEX,
    TSDB_SHOW_STABLES_CREATED_TIME_INDEX,
    TSDB_SHOW_STABLES_COLUMNS_INDEX,
    TSDB_SHOW_STABLES_METRIC_INDEX,
    TSDB_SHOW_STABLES_UID_INDEX,
    TSDB_SHOW_STABLES_TID_INDEX,
    TSDB_SHOW_STABLES_VGID_INDEX,
    TSDB_MAX_SHOW_STABLES
195 196
};

197
enum _describe_table_index {
198 199 200 201 202
    TSDB_DESCRIBE_METRIC_FIELD_INDEX,
    TSDB_DESCRIBE_METRIC_TYPE_INDEX,
    TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
    TSDB_DESCRIBE_METRIC_NOTE_INDEX,
    TSDB_MAX_DESCRIBE_METRIC
203 204
};

H
hzcheng 已提交
205
/* Used by main to communicate with parse_opt. */
206 207
static char *g_dupstr = NULL;

208
typedef struct SArguments_S {
209
    char     *metaFile;
210
    uint32_t test_mode;
211
    char     *host;
212 213 214
    uint16_t port;
    uint16_t iface;
    char *   user;
215
    char     password[SHELL_MAX_PASSWORD_LEN];
216 217 218 219 220 221 222 223 224 225 226 227 228
    char *   database;
    int      replica;
    char *   tb_prefix;
    char *   sqlFile;
    bool     use_metric;
    bool     drop_database;
    bool     insert_only;
    bool     answer_yes;
    bool     debug_print;
    bool     verbose_print;
    bool     performance_print;
    char *   output_file;
    bool     async_mode;
229
    char *   datatype[MAX_NUM_COLUMNS + 1];
230
    uint32_t binwidth;
231 232 233
    uint32_t num_of_CPR;
    uint32_t num_of_threads;
    uint64_t insert_interval;
234
    uint64_t timestamp_step;
235 236 237 238 239 240 241 242
    int64_t  query_times;
    uint32_t interlace_rows;
    uint32_t num_of_RPR;                  // num_of_records_per_req
    uint64_t max_sql_len;
    int64_t  num_of_tables;
    int64_t  num_of_DPT;
    int      abort;
    uint32_t disorderRatio;               // 0: no disorder, >0: x%
243
    int      disorderRange;               // ms, us or ns. accordig to database precision
244 245 246 247
    uint32_t method_of_delete;
    uint64_t totalInsertRows;
    uint64_t totalAffectedRows;
    bool     demo_mode;                  // use default column name and semi-random data
248 249 250
} SArguments;

typedef struct SColumn_S {
251
    char      field[TSDB_COL_NAME_LEN];
252
    char      dataType[DATATYPE_BUFF_LEN];
253
    uint32_t  dataLen;
254
    char      note[NOTE_BUFF_LEN];
255 256 257
} StrColumn;

typedef struct SSuperTable_S {
258
    char         sTblName[TSDB_TABLE_NAME_LEN];
259 260
    char         dataSource[SMALL_BUFF_LEN];  // rand_gen or sample
    char         childTblPrefix[TBNAME_PREFIX_LEN];
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
    uint16_t     childTblExists;
    int64_t      childTblCount;
    uint64_t     batchCreateTableNum;     // 0: no batch,  > 0: batch table number in one sql
    uint8_t      autoCreateTable;         // 0: create sub table, 1: auto create sub table
    uint16_t     iface;                   // 0: taosc, 1: rest, 2: stmt
    int64_t      childTblLimit;
    uint64_t     childTblOffset;

    //  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
    uint32_t     interlaceRows;           //
    int          disorderRatio;           // 0: no disorder, >0: x%
    int          disorderRange;           // ms, us or ns. according to database precision
    uint64_t     maxSqlLen;               //

    uint64_t     insertInterval;          // insert interval, will override global insert interval
    int64_t      insertRows;
    int64_t      timeStampStep;
    char         startTimestamp[MAX_TB_NAME_SIZE];
279
    char         sampleFormat[SMALL_BUFF_LEN];  // csv, json
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
    char         sampleFile[MAX_FILE_NAME_LEN];
    char         tagsFile[MAX_FILE_NAME_LEN];

    uint32_t     columnCount;
    StrColumn    columns[TSDB_MAX_COLUMNS];
    uint32_t     tagCount;
    StrColumn    tags[TSDB_MAX_TAGS];

    char*        childTblName;
    char*        colsOfCreateChildTable;
    uint64_t     lenOfOneRow;
    uint64_t     lenOfTagOfOneRow;

    char*        sampleDataBuf;
    //int          sampleRowCount;
    //int          sampleUsePos;

    uint32_t     tagSource;    // 0: rand, 1: tag sample
    char*        tagDataBuf;
    uint32_t     tagSampleCount;
    uint32_t     tagUsePos;

    // statistics
    uint64_t     totalInsertRows;
    uint64_t     totalAffectedRows;
305 306 307
} SSuperTable;

typedef struct {
308 309 310 311 312 313 314
    char     name[TSDB_DB_NAME_LEN];
    char     create_time[32];
    int64_t  ntables;
    int32_t  vgroups;
    int16_t  replica;
    int16_t  quorum;
    int16_t  days;
315
    char     keeplist[64];
316 317 318 319 320 321 322 323
    int32_t  cache; //MB
    int32_t  blocks;
    int32_t  minrows;
    int32_t  maxrows;
    int8_t   wallevel;
    int32_t  fsync;
    int8_t   comp;
    int8_t   cachelast;
324
    char     precision[SMALL_BUFF_LEN];   // time resolution
325 326
    int8_t   update;
    char     status[16];
327 328
} SDbInfo;

329
typedef struct SDbCfg_S {
330 331 332 333 334 335 336 337 338 339 340 341 342 343
    //  int       maxtablesPerVnode;
    uint32_t  minRows;        // 0 means default
    uint32_t  maxRows;        // 0 means default
    int       comp;
    int       walLevel;
    int       cacheLast;
    int       fsync;
    int       replica;
    int       update;
    int       keep;
    int       days;
    int       cache;
    int       blocks;
    int       quorum;
344
    char      precision[SMALL_BUFF_LEN];
345 346 347
} SDbCfg;

typedef struct SDataBase_S {
348 349 350 351 352
    char         dbName[TSDB_DB_NAME_LEN];
    bool         drop;  // 0: use exists, 1: if exists, drop then new create
    SDbCfg       dbCfg;
    uint64_t     superTblCount;
    SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
353 354 355
} SDataBase;

typedef struct SDbs_S {
356 357 358 359 360 361
    char        cfgDir[MAX_FILE_NAME_LEN];
    char        host[MAX_HOSTNAME_SIZE];
    struct      sockaddr_in serv_addr;

    uint16_t    port;
    char        user[MAX_USERNAME_SIZE];
362
    char        password[SHELL_MAX_PASSWORD_LEN];
363 364 365 366 367 368 369
    char        resultFile[MAX_FILE_NAME_LEN];
    bool        use_metric;
    bool        insert_only;
    bool        do_aggreFunc;
    bool        asyncMode;

    uint32_t    threadCount;
370
    uint32_t    threadCountForCreateTbl;
371 372 373 374 375 376
    uint32_t    dbCount;
    SDataBase   db[MAX_DB_COUNT];

    // statistics
    uint64_t    totalInsertRows;
    uint64_t    totalAffectedRows;
377

378 379
} SDbs;

380
typedef struct SpecifiedQueryInfo_S {
381 382 383 384 385 386 387 388
    uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
    uint32_t     concurrent;
    int          sqlCount;
    uint32_t     asyncMode; // 0: sync, 1: async
    uint64_t     subscribeInterval; // ms
    uint64_t     queryTimes;
    bool         subscribeRestart;
    int          subscribeKeepProgress;
389
    char         sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
390 391 392 393 394 395 396 397
    char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
    int          resubAfterConsume[MAX_QUERY_SQL_COUNT];
    int          endAfterConsume[MAX_QUERY_SQL_COUNT];
    TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
    char         topic[MAX_QUERY_SQL_COUNT][32];
    int          consumed[MAX_QUERY_SQL_COUNT];
    TAOS_RES*    res[MAX_QUERY_SQL_COUNT];
    uint64_t     totalQueried;
398
} SpecifiedQueryInfo;
399

400
typedef struct SuperQueryInfo_S {
401 402 403 404 405 406 407 408 409
    char         sTblName[TSDB_TABLE_NAME_LEN];
    uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
    uint32_t     threadCnt;
    uint32_t     asyncMode; // 0: sync, 1: async
    uint64_t     subscribeInterval; // ms
    bool         subscribeRestart;
    int          subscribeKeepProgress;
    uint64_t     queryTimes;
    int64_t      childTblCount;
410
    char         childTblPrefix[TBNAME_PREFIX_LEN];    // 20 characters reserved for seq
411
    int          sqlCount;
412
    char         sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
413 414 415 416 417 418 419
    char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
    int          resubAfterConsume;
    int          endAfterConsume;
    TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];

    char*        childTblName;
    uint64_t     totalQueried;
420
} SuperQueryInfo;
421 422

typedef struct SQueryMetaInfo_S {
423 424 425 426 427
    char         cfgDir[MAX_FILE_NAME_LEN];
    char         host[MAX_HOSTNAME_SIZE];
    uint16_t     port;
    struct       sockaddr_in serv_addr;
    char         user[MAX_USERNAME_SIZE];
428
    char         password[SHELL_MAX_PASSWORD_LEN];
429
    char         dbName[TSDB_DB_NAME_LEN];
430
    char         queryMode[SMALL_BUFF_LEN];  // taosc, rest
431 432 433 434

    SpecifiedQueryInfo  specifiedQueryInfo;
    SuperQueryInfo      superQueryInfo;
    uint64_t     totalQueried;
435 436 437
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
438 439
    TAOS *    taos;
    TAOS_STMT *stmt;
440 441
    char*     sampleBindArray;
    int64_t   *bind_ts;
442 443 444 445 446 447 448 449 450
    int       threadID;
    char      db_name[TSDB_DB_NAME_LEN];
    uint32_t  time_precision;
    char      filePath[4096];
    FILE      *fp;
    char      tb_prefix[TSDB_TABLE_NAME_LEN];
    uint64_t  start_table_from;
    uint64_t  end_table_to;
    int64_t   ntables;
451
    int64_t   tables_created;
452 453 454 455
    uint64_t  data_of_rate;
    int64_t   start_time;
    char*     cols;
    bool      use_metric;
456
    SSuperTable* stbInfo;
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
    char      *buffer;    // sql cmd buffer

    // for async insert
    tsem_t    lock_sem;
    int64_t   counter;
    uint64_t  st;
    uint64_t  et;
    uint64_t  lastTs;

    // sample data
    int64_t   samplePos;
    // statistics
    uint64_t  totalInsertRows;
    uint64_t  totalAffectedRows;

    // insert delay statistics
    uint64_t  cntDelay;
    uint64_t  totalDelay;
    uint64_t  avgDelay;
    uint64_t  maxDelay;
    uint64_t  minDelay;

    // seq of query or subscribe
    uint64_t  querySeq;   // sequence number of sql command
    TAOS_SUB*  tsub;
482

483 484
} threadInfo;

485
#ifdef WINDOWS
486 487
#define _CRT_RAND_S

488
#include <windows.h>
489 490 491 492 493
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
494 495
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
496
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
497
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
498 499 500 501

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

502
static void setupForAnsiEscape(void) {
503 504
    DWORD mode = 0;
    g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
505

506 507 508
    if(g_stdoutHandle == INVALID_HANDLE_VALUE) {
        exit(GetLastError());
    }
509

510 511 512
    if(!GetConsoleMode(g_stdoutHandle, &mode)) {
        exit(GetLastError());
    }
513

514
    g_consoleMode = mode;
515

516 517
    // Enable ANSI escape codes
    mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
518

519 520 521
    if(!SetConsoleMode(g_stdoutHandle, mode)) {
        exit(GetLastError());
    }
522 523
}

524
static void resetAfterAnsiEscape(void) {
525 526
    // Reset colors
    printf("\x1b[0m");
527

528 529 530 531
    // Reset console mode
    if(!SetConsoleMode(g_stdoutHandle, g_consoleMode)) {
        exit(GetLastError());
    }
532
}
533

534
static int taosRandom()
535 536 537 538 539 540
{
    int number;
    rand_s(&number);

    return number;
}
541
#else   // Not windows
542
static void setupForAnsiEscape(void) {}
543

544
static void resetAfterAnsiEscape(void) {
545 546
    // Reset colors
    printf("\x1b[0m");
547
}
548

549 550
#include <time.h>

551
static int taosRandom()
552
{
553
    return rand();
554 555
}

556
#endif // ifdef Windows
557

558
static void prompt();
559
static int createDatabasesAndStables();
560
static void createChildTables();
561
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
562
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
563
        uint16_t port, char* sqlstr, threadInfo *pThreadInfo);
564 565
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
        int disorderRatio, int disorderRange);
566 567
static bool getInfoFromJsonFile(char* file);
static void init_rand_data();
568 569 570

/* ************ Global variables ************  */

571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
int32_t  g_randint[MAX_PREPARED_RAND];
int64_t  g_randbigint[MAX_PREPARED_RAND];
float    g_randfloat[MAX_PREPARED_RAND];
double   g_randdouble[MAX_PREPARED_RAND];

char    *g_randbool_buff = NULL;
char    *g_randint_buff = NULL;
char    *g_rand_voltage_buff = NULL;
char    *g_randbigint_buff = NULL;
char    *g_randsmallint_buff = NULL;
char    *g_randtinyint_buff = NULL;
char    *g_randfloat_buff = NULL;
char    *g_rand_current_buff = NULL;
char    *g_rand_phase_buff = NULL;
char    *g_randdouble_buff = NULL;

char    *g_aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)",
588 589
    "max(col0)", "min(col0)", "first(col0)", "last(col0)"};

590
SArguments g_args = {
591 592 593 594 595 596
    NULL,           // metaFile
    0,              // test_mode
    "localhost",    // host
    6030,           // port
    INTERFACE_BUT,  // iface
    "root",         // user
597 598 599
#ifdef _TD_POWER_
    "powerdb",      // password
#elif (_TD_TQ_ == true)
600
    "tqueue",       // password
601
#else
602
    "taosdata",     // password
603
#endif
604 605
    "test",         // database
    1,              // replica
606 607 608 609 610 611 612 613 614 615 616 617 618 619
    "d",             // tb_prefix
    NULL,            // sqlFile
    true,            // use_metric
    true,            // drop_database
    true,            // insert_only
    false,           // debug_print
    false,           // verbose_print
    false,           // performance statistic print
    false,           // answer_yes;
    "./output.txt",  // output_file
    0,               // mode : sync or async
    {
        "FLOAT",         // datatype
        "INT",           // datatype
620
        "FLOAT",         // datatype. DEFAULT_DATATYPE_NUM is 3
621
    },
622
    64,              // binwidth
623 624 625
    4,               // num_of_CPR
    10,              // num_of_connections/thread
    0,               // insert_interval
626
    DEFAULT_TIMESTAMP_STEP, // timestamp_step
627
    1,               // query_times
628
    DEFAULT_INTERLACE_ROWS, // interlace_rows;
629 630
    30000,           // num_of_RPR
    (1024*1024),     // max_sql_len
631
    DEFAULT_CHILDTABLES,    // num_of_tables
632 633 634 635 636 637 638 639
    10000,           // num_of_DPT
    0,               // abort
    0,               // disorderRatio
    1000,            // disorderRange
    1,               // method_of_delete
    0,               // totalInsertRows;
    0,               // totalAffectedRows;
    true,            // demo_mode;
640 641 642
};

static SDbs            g_Dbs;
643
static int64_t         g_totalChildTables = DEFAULT_CHILDTABLES;
644
static int64_t         g_actualChildTables = 0;
645 646 647
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

648 649 650 651
#if _MSC_VER <= 1900
#define __func__ __FUNCTION__
#endif

652
#define debugPrint(fmt, ...) \
653
    do { if (g_args.debug_print || g_args.verbose_print) \
654
        fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
655

656
#define verbosePrint(fmt, ...) \
657 658
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
659

660 661
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
662
        fprintf(stderr, "PERF: "fmt, __VA_ARGS__); } while(0)
663

664
#define errorPrint(fmt, ...) \
665 666 667 668 669 670 671
    do {\
        fprintf(stderr, " \033[31m");\
        fprintf(stderr, "ERROR: "fmt, __VA_ARGS__);\
        fprintf(stderr, " \033[0m");\
    } while(0)

#define errorPrint2(fmt, ...) \
672 673 674 675 676 677 678 679 680 681 682 683 684
    do {\
        struct tm      Tm, *ptm;\
        struct timeval timeSecs; \
        time_t         curTime;\
        gettimeofday(&timeSecs, NULL); \
        curTime = timeSecs.tv_sec;\
        ptm = localtime_r(&curTime, &Tm);\
        fprintf(stderr, " \033[31m");\
        fprintf(stderr, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " ",\
                ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour,\
                ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec,\
                taosGetSelfPthreadId());\
        fprintf(stderr, " \033[0m");\
685
        errorPrint(fmt, __VA_ARGS__);\
686
    } while(0)
687

688 689 690
// for strncpy buffer overflow
#define min(a, b) (((a) < (b)) ? (a) : (b))

691

692
///////////////////////////////////////////////////
H
hzcheng 已提交
693

694
static void ERROR_EXIT(const char *msg) { errorPrint("%s", msg); exit(-1); }
695

696 697 698 699 700 701 702 703
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

704
#ifndef TAOSDEMO_STATUS
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
#define TAOSDEMO_STATUS "unknown"
#endif

static void printVersion() {
    char tdengine_ver[] = TD_VERNUMBER;
    char taosdemo_ver[] = TAOSDEMO_COMMIT_SHA1;
    char taosdemo_status[] = TAOSDEMO_STATUS;

    if (strlen(taosdemo_status) == 0) {
        printf("taosdemo verison %s-%s\n",
                tdengine_ver, taosdemo_ver);
    } else {
        printf("taosdemo verison %s-%s, status:%s\n",
                tdengine_ver, taosdemo_ver, taosdemo_status);
    }
}

722
static void printHelp() {
723 724 725
    char indent[10] = "  ";
    printf("%s\n\n", "Usage: taosdemo [OPTION...]");
    printf("%s%s%s%s\n", indent, "-f, --file=FILE", "\t\t",
726
            "The meta file to the execution procedure. Default is './meta.json'.");
727 728
    printf("%s%s%s%s\n", indent, "-u, --user=USER", "\t\t",
            "The user name to use when connecting to the server.");
729
#ifdef _TD_POWER_
730 731 732
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
            "The password to use when connecting to the server. Default is 'powerdb'");
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
733
            "Configuration directory. Default is '/etc/power/'.");
734
#elif (_TD_TQ_ == true)
735 736 737
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
            "The password to use when connecting to the server. Default is 'tqueue'");
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
738
            "Configuration directory. Default is '/etc/tq/'.");
739
#else
740 741 742 743
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
            "The password to use when connecting to the server.");
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
            "Configuration directory.");
744
#endif
745 746 747 748 749
    printf("%s%s%s%s\n", indent, "-h, --host=HOST", "\t\t",
            "TDengine server FQDN to connect. The default host is localhost.");
    printf("%s%s%s%s\n", indent, "-P, --port=PORT", "\t\t",
            "The TCP/IP port number to use for the connection.");
    printf("%s%s%s%s\n", indent, "-I, --interface=INTERFACE", "\t",
750
            "The interface (taosc, rest, and stmt) taosdemo uses. Default is 'taosc'.");
751
    printf("%s%s%s%s\n", indent, "-d, --database=DATABASE", "\t",
752
            "Destination database. Default is 'test'.");
753
    printf("%s%s%s%s\n", indent, "-a, --replica=REPLICA", "\t\t",
754
            "Set the replica parameters of the database, Default 1, min: 1, max: 3.");
755
    printf("%s%s%s%s\n", indent, "-m, --table-prefix=TABLEPREFIX", "\t",
756
            "Table prefix name. Default is 'd'.");
757 758
    printf("%s%s%s%s\n", indent, "-s, --sql-file=FILE", "\t\t",
            "The select sql file.");
759 760
    printf("%s%s%s%s\n", indent, "-N, --normal-table", "\t\t", "Use normal table flag.");
    printf("%s%s%s%s\n", indent, "-o, --output=FILE", "\t\t",
761
            "Direct output to the named file. Default is './output.txt'.");
762
    printf("%s%s%s%s\n", indent, "-q, --query-mode=MODE", "\t\t",
763
            "Query mode -- 0: SYNC, 1: ASYNC. Default is SYNC.");
764
    printf("%s%s%s%s\n", indent, "-b, --data-type=DATATYPE", "\t",
765
            "The data_type of columns, default: FLOAT, INT, FLOAT.");
766 767 768 769
    printf("%s%s%s%s%d\n", indent, "-w, --binwidth=WIDTH", "\t\t",
            "The width of data_type 'BINARY' or 'NCHAR'. Default is ",
            g_args.binwidth);
    printf("%s%s%s%s%d%s%d\n", indent, "-l, --columns=COLUMNS", "\t\t",
770
            "The number of columns per record. Demo mode by default is ",
771
            DEFAULT_DATATYPE_NUM,
772
            " (float, int, float). Max values is ",
773 774
            MAX_NUM_COLUMNS);
    printf("%s%s%s%s\n", indent, indent, indent,
775 776
            "\t\t\t\tAll of the new column(s) type is INT. If use -b to specify column type, -l will be ignored.");
    printf("%s%s%s%s\n", indent, "-T, --threads=NUMBER", "\t\t",
777
            "The number of threads. Default is 10.");
778
    printf("%s%s%s%s\n", indent, "-i, --insert-interval=NUMBER", "\t",
779
            "The sleep time (ms) between insertion. Default is 0.");
780
    printf("%s%s%s%s%d.\n", indent, "-S, --time-step=TIME_STEP", "\t",
781
            "The timestamp step between insertion. Default is ",
782
            DEFAULT_TIMESTAMP_STEP);
783 784 785 786
    printf("%s%s%s%s%d.\n", indent, "-B, --interlace-rows=NUMBER", "\t",
            "The interlace rows of insertion. Default is ",
            DEFAULT_INTERLACE_ROWS);
    printf("%s%s%s%s\n", indent, "-r, --rec-per-req=NUMBER", "\t",
787
            "The number of records per request. Default is 30000.");
788
    printf("%s%s%s%s\n", indent, "-t, --tables=NUMBER", "\t\t",
789
            "The number of tables. Default is 10000.");
790
    printf("%s%s%s%s\n", indent, "-n, --records=NUMBER", "\t\t",
791
            "The number of records per table. Default is 10000.");
792
    printf("%s%s%s%s\n", indent, "-M, --random", "\t\t\t",
793
            "The value of records generated are totally random.");
794 795 796 797 798 799 800
    printf("%s\n", "\t\t\t\tThe default is to simulate power equipment senario.");
    printf("%s%s%s%s\n", indent, "-x, --no-insert", "\t\t",
            "No-insert flag.");
    printf("%s%s%s%s\n", indent, "-y, --answer-yes", "\t\t", "Default input yes for prompt.");
    printf("%s%s%s%s\n", indent, "-O, --disorder=NUMBER", "\t\t",
            "Insert order mode--0: In order, 1 ~ 50: disorder ratio. Default is in order.");
    printf("%s%s%s%s\n", indent, "-R, --disorder-range=NUMBER", "\t",
801
            "Out of order data's range, ms, default is 1000.");
802
    printf("%s%s%s%s\n", indent, "-g, --debug", "\t\t\t",
803
            "Print debug info.");
804 805 806 807
    printf("%s%s%s%s\n", indent, "-?, --help\t", "\t\t",
            "Give this help list");
    printf("%s%s%s%s\n", indent, "    --usage\t", "\t\t",
            "Give a short usage message");
808
    printf("%s%s\n", indent, "-V, --version\t\t\tPrint program version.");
809 810
    /*    printf("%s%s%s%s\n", indent, "-D", indent,
          "Delete database if exists. 0: no, 1: yes, default is 1");
811
          */
812 813 814 815
    printf("\nMandatory or optional arguments to long options are also mandatory or optional\n\
for any corresponding short options.\n\
\n\
Report bugs to <support@taosdata.com>.\n");
816 817
}

818 819
static bool isStringNumber(char *input)
{
820 821 822 823
    int len = strlen(input);
    if (0 == len) {
        return false;
    }
824

825 826 827 828
    for (int i = 0; i < len; i++) {
        if (!isdigit(input[i]))
            return false;
    }
829

830
    return true;
831 832
}

833 834 835 836 837 838
static void errorWrongValue(char *program, char *wrong_arg, char *wrong_value)
{
    fprintf(stderr, "%s %s: %s is an invalid value\n", program, wrong_arg, wrong_value);
    fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

839 840 841 842 843 844
static void errorUnreconized(char *program, char *wrong_arg)
{
    fprintf(stderr, "%s: unrecognized options '%s'\n", program, wrong_arg);
    fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
static void errorPrintReqArg(char *program, char *wrong_arg)
{
    fprintf(stderr,
            "%s: option requires an argument -- '%s'\n",
            program, wrong_arg);
    fprintf(stderr,
            "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

static void errorPrintReqArg2(char *program, char *wrong_arg)
{
    fprintf(stderr,
            "%s: option requires a number argument '-%s'\n",
            program, wrong_arg);
    fprintf(stderr,
            "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

static void errorPrintReqArg3(char *program, char *wrong_arg)
{
    fprintf(stderr,
            "%s: option '%s' requires an argument\n",
            program, wrong_arg);
    fprintf(stderr,
            "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

872
static void parse_args(int argc, char *argv[], SArguments *arguments) {
873

874
    for (int i = 1; i < argc; i++) {
875
        if ((0 == strncmp(argv[i], "-f", strlen("-f")))
876
                || (0 == strncmp(argv[i], "--file", strlen("--file")))) {
877
            arguments->demo_mode = false;
878

879 880 881
            if (2 == strlen(argv[i])) {
                if (i+1 == argc) {
                    errorPrintReqArg(argv[0], "f");
882 883 884
                    exit(EXIT_FAILURE);
                }
                arguments->metaFile = argv[++i];
885 886
            } else if (0 == strncmp(argv[i], "-f", strlen("-f"))) {
                arguments->metaFile = (char *)(argv[i] + strlen("-f"));
887
            } else if (strlen("--file") == strlen(argv[i])) {
888 889 890 891 892
                if (i+1 == argc) {
                    errorPrintReqArg3(argv[0], "--file");
                    exit(EXIT_FAILURE);
                }
                arguments->metaFile = argv[++i];
893 894
            } else if (0 == strncmp(argv[i], "--file=", strlen("--file="))) {
                arguments->metaFile = (char *)(argv[i] + strlen("--file="));
895 896 897
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
898
            }
899
        } else if ((0 == strncmp(argv[i], "-c", strlen("-c")))
900 901 902 903 904 905 906
                || (0 == strncmp(argv[i], "--config-dir", strlen("--config-dir")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "c");
                    exit(EXIT_FAILURE);
                }
                tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
907
            } else if (0 == strncmp(argv[i], "-c", strlen("-c"))) {
908
                tstrncpy(configDir, (char *)(argv[i] + strlen("-c")), TSDB_FILENAME_LEN);
909
            } else if (strlen("--config-dir") == strlen(argv[i])) {
910 911 912 913 914
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--config-dir");
                    exit(EXIT_FAILURE);
                }
                tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
915 916
            } else if (0 == strncmp(argv[i], "--config-dir=", strlen("--config-dir="))) {
                tstrncpy(configDir, (char *)(argv[i] + strlen("--config-dir=")), TSDB_FILENAME_LEN);
917 918 919
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
920
            }
921
        } else if ((0 == strncmp(argv[i], "-h", strlen("-h")))
922 923 924 925 926 927 928
                || (0 == strncmp(argv[i], "--host", strlen("--host")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "h");
                    exit(EXIT_FAILURE);
                }
                arguments->host = argv[++i];
929 930
            } else if (0 == strncmp(argv[i], "-h", strlen("-h"))) {
                arguments->host = (char *)(argv[i] + strlen("-h"));
931
            } else if (strlen("--host") == strlen(argv[i])) {
932 933 934 935 936
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--host");
                    exit(EXIT_FAILURE);
                }
                arguments->host = argv[++i];
937 938
            } else if (0 == strncmp(argv[i], "--host=", strlen("--host="))) {
                arguments->host = (char *)(argv[i] + strlen("--host="));
939 940 941
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
942
            }
943 944 945
        } else if (strcmp(argv[i], "-PP") == 0) {
            arguments->performance_print = true;
        } else if ((0 == strncmp(argv[i], "-P", strlen("-P")))
946 947 948 949 950 951 952 953 954 955 956 957 958 959
                || (0 == strncmp(argv[i], "--port", strlen("--port")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "P");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "P");
                    exit(EXIT_FAILURE);
                }
                arguments->port = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--port=", strlen("--port="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--port=")))) {
                    arguments->port = atoi((char *)(argv[i]+strlen("--port=")));
                }
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
            } else if (0 == strncmp(argv[i], "-P", strlen("-P"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-P")))) {
                    arguments->port = atoi((char *)(argv[i]+strlen("-P")));
                }
            } else if (strlen("--port") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--port");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--port");
                    exit(EXIT_FAILURE);
                }
                arguments->port = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
976
            }
977
        } else if ((0 == strncmp(argv[i], "-I", strlen("-I")))
978 979 980 981 982 983 984 985 986 987 988 989 990
                || (0 == strncmp(argv[i], "--interface", strlen("--interface")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "I");
                    exit(EXIT_FAILURE);
                }
                if (0 == strcasecmp(argv[i+1], "taosc")) {
                    arguments->iface = TAOSC_IFACE;
                } else if (0 == strcasecmp(argv[i+1], "rest")) {
                    arguments->iface = REST_IFACE;
                } else if (0 == strcasecmp(argv[i+1], "stmt")) {
                    arguments->iface = STMT_IFACE;
                } else {
991
                    errorWrongValue(argv[0], "-I", argv[i+1]);
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
                    exit(EXIT_FAILURE);
                }
                i++;
            } else if (0 == strncmp(argv[i], "--interface=", strlen("--interface="))) {
                if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "taosc")) {
                    arguments->iface = TAOSC_IFACE;
                } else if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "rest")) {
                    arguments->iface = REST_IFACE;
                } else if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "stmt")) {
                    arguments->iface = STMT_IFACE;
                } else {
                    errorPrintReqArg3(argv[0], "--interface");
                    exit(EXIT_FAILURE);
                }
1006 1007 1008 1009 1010 1011 1012 1013
            } else if (0 == strncmp(argv[i], "-I", strlen("-I"))) {
                if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "taosc")) {
                    arguments->iface = TAOSC_IFACE;
                } else if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "rest")) {
                    arguments->iface = REST_IFACE;
                } else if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "stmt")) {
                    arguments->iface = STMT_IFACE;
                } else {
1014 1015
                    errorWrongValue(argv[0], "-I",
                            (char *)(argv[i] + strlen("-I")));
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--interface") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--interface");
                    exit(EXIT_FAILURE);
                }
                if (0 == strcasecmp(argv[i+1], "taosc")) {
                    arguments->iface = TAOSC_IFACE;
                } else if (0 == strcasecmp(argv[i+1], "rest")) {
                    arguments->iface = REST_IFACE;
                } else if (0 == strcasecmp(argv[i+1], "stmt")) {
                    arguments->iface = STMT_IFACE;
                } else {
1030
                    errorWrongValue(argv[0], "--interface", argv[i+1]);
1031 1032 1033 1034 1035 1036
                    exit(EXIT_FAILURE);
                }
                i++;
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1037
            }
1038
        } else if ((0 == strncmp(argv[i], "-u", strlen("-u")))
1039 1040 1041 1042 1043 1044 1045
                || (0 == strncmp(argv[i], "--user", strlen("--user")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "u");
                    exit(EXIT_FAILURE);
                }
                arguments->user = argv[++i];
1046 1047
            } else if (0 == strncmp(argv[i], "-u", strlen("-u"))) {
                arguments->user = (char *)(argv[i++] + strlen("-u"));
1048 1049
            } else if (0 == strncmp(argv[i], "--user=", strlen("--user="))) {
                arguments->user = (char *)(argv[i++] + strlen("--user="));
1050 1051 1052 1053 1054 1055 1056 1057 1058
            } else if (strlen("--user") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--user");
                    exit(EXIT_FAILURE);
                }
                arguments->user = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1059
            }
1060
        } else if ((0 == strncmp(argv[i], "-p", strlen("-p")))
1061 1062
                || (0 == strcmp(argv[i], "--password"))) {
            if ((strlen(argv[i]) == 2) || (0 == strcmp(argv[i], "--password"))) {
1063 1064
                printf("Enter password: ");
                taosSetConsoleEcho(false);
1065 1066 1067
                if (scanf("%s", arguments->password) > 1) {
                    fprintf(stderr, "password read error!\n");
                }
1068
                taosSetConsoleEcho(true);
1069
            } else {
1070
                tstrncpy(arguments->password, (char *)(argv[i] + 2), SHELL_MAX_PASSWORD_LEN);
1071
            }
1072
        } else if ((0 == strncmp(argv[i], "-o", strlen("-o")))
1073 1074 1075
                || (0 == strncmp(argv[i], "--output", strlen("--output")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
1076
                    errorPrintReqArg3(argv[0], "--output");
1077 1078 1079 1080 1081
                    exit(EXIT_FAILURE);
                }
                arguments->output_file = argv[++i];
            } else if (0 == strncmp(argv[i], "--output=", strlen("--output="))) {
                arguments->output_file = (char *)(argv[i++] + strlen("--output="));
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
            } else if (0 == strncmp(argv[i], "-o", strlen("-o"))) {
                arguments->output_file = (char *)(argv[i++] + strlen("-o"));
            } else if (strlen("--output") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--output");
                    exit(EXIT_FAILURE);
                }
                arguments->output_file = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1093
            }
1094
        } else if ((0 == strncmp(argv[i], "-s", strlen("-s")))
1095 1096 1097 1098 1099 1100 1101 1102
                || (0 == strncmp(argv[i], "--sql-file", strlen("--sql-file")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "s");
                    exit(EXIT_FAILURE);
                }
                arguments->sqlFile = argv[++i];
            } else if (0 == strncmp(argv[i], "--sql-file=", strlen("--sql-file="))) {
1103
                arguments->sqlFile = (char *)(argv[i++] + strlen("--sql-file="));
1104
            } else if (0 == strncmp(argv[i], "-s", strlen("-s"))) {
1105
                arguments->sqlFile = (char *)(argv[i++] + strlen("-s"));
1106 1107 1108 1109 1110 1111 1112 1113 1114
            } else if (strlen("--sql-file") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--sql-file");
                    exit(EXIT_FAILURE);
                }
                arguments->sqlFile = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1115
            }
1116
        } else if ((0 == strncmp(argv[i], "-q", strlen("-q")))
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
                || (0 == strncmp(argv[i], "--query-mode", strlen("--query-mode")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "q");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "q");
                    exit(EXIT_FAILURE);
                }
                arguments->async_mode = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--query-mode=", strlen("--query-mode="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--query-mode=")))) {
                    arguments->async_mode = atoi((char *)(argv[i]+strlen("--query-mode=")));
                } else {
                    errorPrintReqArg2(argv[0], "--query-mode");
                    exit(EXIT_FAILURE);
                }
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
            } else if (0 == strncmp(argv[i], "-q", strlen("-q"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-q")))) {
                    arguments->async_mode = atoi((char *)(argv[i]+strlen("-q")));
                } else {
                    errorPrintReqArg2(argv[0], "-q");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--query-mode") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--query-mode");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--query-mode");
                    exit(EXIT_FAILURE);
                }
                arguments->async_mode = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1153
            }
1154
        } else if ((0 == strncmp(argv[i], "-T", strlen("-T")))
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
                || (0 == strncmp(argv[i], "--threads", strlen("--threads")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "T");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "T");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_threads = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--threads=", strlen("--threads="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--threads=")))) {
                    arguments->num_of_threads = atoi((char *)(argv[i]+strlen("--threads=")));
                } else {
                    errorPrintReqArg2(argv[0], "--threads");
                    exit(EXIT_FAILURE);
                }
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
            } else if (0 == strncmp(argv[i], "-T", strlen("-T"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-T")))) {
                    arguments->num_of_threads = atoi((char *)(argv[i]+strlen("-T")));
                } else {
                    errorPrintReqArg2(argv[0], "-T");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--threads") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--threads");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--threads");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_threads = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1191
            }
1192
        } else if ((0 == strncmp(argv[i], "-i", strlen("-i")))
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
                || (0 == strncmp(argv[i], "--insert-interval", strlen("--insert-interval")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "i");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "i");
                    exit(EXIT_FAILURE);
                }
                arguments->insert_interval = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--insert-interval=", strlen("--insert-interval="))) {
1204
                if (isStringNumber((char *)(argv[i] + strlen("--insert-interval=")))) {
1205 1206 1207 1208 1209
                    arguments->insert_interval = atoi((char *)(argv[i]+strlen("--insert-interval=")));
                } else {
                    errorPrintReqArg3(argv[0], "--insert-innterval");
                    exit(EXIT_FAILURE);
                }
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
            } else if (0 == strncmp(argv[i], "-i", strlen("-i"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-i")))) {
                    arguments->insert_interval = atoi((char *)(argv[i]+strlen("-i")));
                } else {
                    errorPrintReqArg3(argv[0], "-i");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--insert-interval")== strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--insert-interval");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--insert-interval");
                    exit(EXIT_FAILURE);
                }
                arguments->insert_interval = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
1228 1229
                exit(EXIT_FAILURE);
            }
1230
        } else if ((0 == strncmp(argv[i], "-S", strlen("-S")))
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
                || (0 == strncmp(argv[i], "--time-step", strlen("--time-step")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "S");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "S");
                    exit(EXIT_FAILURE);
                }
                arguments->async_mode = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--time-step=", strlen("--time-step="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--time-step=")))) {
                    arguments->async_mode = atoi((char *)(argv[i]+strlen("--time-step=")));
                } else {
                    errorPrintReqArg2(argv[0], "--time-step");
                    exit(EXIT_FAILURE);
                }
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
            } else if (0 == strncmp(argv[i], "-S", strlen("-S"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-S")))) {
                    arguments->async_mode = atoi((char *)(argv[i]+strlen("-S")));
                } else {
                    errorPrintReqArg2(argv[0], "-S");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--time-step") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--time-step");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--time-step");
                    exit(EXIT_FAILURE);
                }
                arguments->async_mode = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1267
            }
1268 1269 1270 1271 1272 1273 1274 1275
        } else if (strcmp(argv[i], "-qt") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-qt need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->query_times = atoi(argv[++i]);
1276
        } else if ((0 == strncmp(argv[i], "-B", strlen("-B")))
1277
                || (0 == strncmp(argv[i], "--interlace-rows", strlen("--interlace-rows")))) {
1278
            if (strlen("-B") == strlen(argv[i])) {
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "B");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "B");
                    exit(EXIT_FAILURE);
                }
                arguments->interlace_rows = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--interlace-rows=", strlen("--interlace-rows="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--interlace-rows=")))) {
                    arguments->interlace_rows = atoi((char *)(argv[i]+strlen("--interlace-rows=")));
                } else {
                    errorPrintReqArg2(argv[0], "--interlace-rows");
                    exit(EXIT_FAILURE);
                }
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
            } else if (0 == strncmp(argv[i], "-B", strlen("-B"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-B")))) {
                    arguments->interlace_rows = atoi((char *)(argv[i]+strlen("-B")));
                } else {
                    errorPrintReqArg2(argv[0], "-B");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--interlace-rows")== strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--interlace-rows");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--interlace-rows");
                    exit(EXIT_FAILURE);
                }
                arguments->interlace_rows = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1313
            }
1314
        } else if ((0 == strncmp(argv[i], "-r", strlen("-r")))
1315
                || (0 == strncmp(argv[i], "--rec-per-req", 13))) {
1316
            if (strlen("-r") == strlen(argv[i])) {
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "r");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "r");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_RPR = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--rec-per-req=", strlen("--rec-per-req="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--rec-per-req=")))) {
                    arguments->num_of_RPR = atoi((char *)(argv[i]+strlen("--rec-per-req=")));
                } else {
                    errorPrintReqArg2(argv[0], "--rec-per-req");
                    exit(EXIT_FAILURE);
                }
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
            } else if (0 == strncmp(argv[i], "-r", strlen("-r"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-r")))) {
                    arguments->num_of_RPR = atoi((char *)(argv[i]+strlen("-r")));
                } else {
                    errorPrintReqArg2(argv[0], "-r");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--rec-per-req")== strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--rec-per-req");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--rec-per-req");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_RPR = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1351
            }
1352
        } else if ((0 == strncmp(argv[i], "-t", strlen("-t")))
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
                || (0 == strncmp(argv[i], "--tables", strlen("--tables")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "t");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "t");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_tables = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--tables=", strlen("--tables="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--tables=")))) {
                    arguments->num_of_tables = atoi((char *)(argv[i]+strlen("--tables=")));
                } else {
                    errorPrintReqArg2(argv[0], "--tables");
                    exit(EXIT_FAILURE);
                }
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
            } else if (0 == strncmp(argv[i], "-t", strlen("-t"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-t")))) {
                    arguments->num_of_tables = atoi((char *)(argv[i]+strlen("-t")));
                } else {
                    errorPrintReqArg2(argv[0], "-t");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--tables") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--tables");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--tables");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_tables = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1389
            }
1390 1391

            g_totalChildTables = arguments->num_of_tables;
1392
        } else if ((0 == strncmp(argv[i], "-n", strlen("-n")))
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
                || (0 == strncmp(argv[i], "--records", strlen("--records")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "n");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "n");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_DPT = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--records=", strlen("--records="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--records=")))) {
                    arguments->num_of_DPT = atoi((char *)(argv[i]+strlen("--records=")));
                } else {
                    errorPrintReqArg2(argv[0], "--records");
                    exit(EXIT_FAILURE);
                }
1410 1411 1412
            } else if (0 == strncmp(argv[i], "-n", strlen("-n"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-n")))) {
                    arguments->num_of_DPT = atoi((char *)(argv[i]+strlen("-n")));
1413
                } else {
1414
                    errorPrintReqArg2(argv[0], "-n");
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--records") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--records");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--records");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_DPT = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1429
            }
1430
        } else if ((0 == strncmp(argv[i], "-d", strlen("-d")))
1431 1432 1433
                || (0 == strncmp(argv[i], "--database", strlen("--database")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
1434
                    errorPrintReqArg(argv[0], "d");
1435 1436 1437 1438 1439
                    exit(EXIT_FAILURE);
                }
                arguments->database = argv[++i];
            } else if (0 == strncmp(argv[i], "--database=", strlen("--database="))) {
                arguments->output_file = (char *)(argv[i] + strlen("--database="));
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
            } else if (0 == strncmp(argv[i], "-d", strlen("-d"))) {
                arguments->output_file = (char *)(argv[i] + strlen("-d"));
            } else if (strlen("--database") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--database");
                    exit(EXIT_FAILURE);
                }
                arguments->database = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1451
            }
1452
        } else if ((0 == strncmp(argv[i], "-l", strlen("-l")))
1453
                || (0 == strncmp(argv[i], "--columns", strlen("--columns")))) {
1454
            arguments->demo_mode = false;
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "l");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "l");
                    exit(EXIT_FAILURE);
                }
                arguments->num_of_CPR = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--columns=", strlen("--columns="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--columns=")))) {
1466 1467 1468 1469 1470 1471 1472 1473
                    arguments->num_of_CPR = atoi((char *)(argv[i]+strlen("--columns=")));
                } else {
                    errorPrintReqArg2(argv[0], "--columns");
                    exit(EXIT_FAILURE);
                }
            } else if (0 == strncmp(argv[i], "-l", strlen("-l"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-l")))) {
                    arguments->num_of_CPR = atoi((char *)(argv[i]+strlen("-l")));
1474
                } else {
1475 1476 1477 1478 1479 1480 1481 1482
                    errorPrintReqArg2(argv[0], "-l");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--columns")== strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--columns");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
1483
                    errorPrintReqArg2(argv[0], "--columns");
1484 1485
                    exit(EXIT_FAILURE);
                }
1486 1487 1488 1489
                arguments->num_of_CPR = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1490
            }
1491

1492 1493
            if (arguments->num_of_CPR > MAX_NUM_COLUMNS) {
                printf("WARNING: max acceptible columns count is %d\n", MAX_NUM_COLUMNS);
1494
                prompt();
1495
                arguments->num_of_CPR = MAX_NUM_COLUMNS;
1496
            }
1497

1498 1499 1500 1501
            for (int col = DEFAULT_DATATYPE_NUM; col < arguments->num_of_CPR; col ++) {
                arguments->datatype[col] = "INT";
            }
            for (int col = arguments->num_of_CPR; col < MAX_NUM_COLUMNS; col++) {
1502 1503
                arguments->datatype[col] = NULL;
            }
1504
        } else if ((0 == strncmp(argv[i], "-b", strlen("-b")))
1505
                || (0 == strncmp(argv[i], "--data-type", strlen("--data-type")))) {
1506
            arguments->demo_mode = false;
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516

            char *dataType;
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "b");
                    exit(EXIT_FAILURE);
                }
                dataType = argv[++i];
            } else if (0 == strncmp(argv[i], "--data-type=", strlen("--data-type="))) {
                dataType = (char *)(argv[i] + strlen("--data-type="));
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
            } else if (0 == strncmp(argv[i], "-b", strlen("-b"))) {
                dataType = (char *)(argv[i] + strlen("-b"));
            } else if (strlen("--data-type") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--data-type");
                    exit(EXIT_FAILURE);
                }
                dataType = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1528
            }
1529 1530

            if (strstr(dataType, ",") == NULL) {
1531
                // only one col
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
                if (strcasecmp(dataType, "INT")
                        && strcasecmp(dataType, "FLOAT")
                        && strcasecmp(dataType, "TINYINT")
                        && strcasecmp(dataType, "BOOL")
                        && strcasecmp(dataType, "SMALLINT")
                        && strcasecmp(dataType, "BIGINT")
                        && strcasecmp(dataType, "DOUBLE")
                        && strcasecmp(dataType, "BINARY")
                        && strcasecmp(dataType, "TIMESTAMP")
                        && strcasecmp(dataType, "NCHAR")) {
1542 1543 1544 1545
                    printHelp();
                    errorPrint("%s", "-b: Invalid data_type!\n");
                    exit(EXIT_FAILURE);
                }
1546
                arguments->datatype[0] = dataType;
1547
                arguments->datatype[1] = NULL;
1548 1549 1550
            } else {
                // more than one col
                int index = 0;
1551
                g_dupstr = strdup(dataType);
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
                char *running = g_dupstr;
                char *token = strsep(&running, ",");
                while(token != NULL) {
                    if (strcasecmp(token, "INT")
                            && strcasecmp(token, "FLOAT")
                            && strcasecmp(token, "TINYINT")
                            && strcasecmp(token, "BOOL")
                            && strcasecmp(token, "SMALLINT")
                            && strcasecmp(token, "BIGINT")
                            && strcasecmp(token, "DOUBLE")
                            && strcasecmp(token, "BINARY")
                            && strcasecmp(token, "TIMESTAMP")
                            && strcasecmp(token, "NCHAR")) {
                        printHelp();
                        free(g_dupstr);
                        errorPrint("%s", "-b: Invalid data_type!\n");
                        exit(EXIT_FAILURE);
                    }
                    arguments->datatype[index++] = token;
                    token = strsep(&running, ",");
1572
                    if (index >= MAX_NUM_COLUMNS) break;
1573 1574 1575
                }
                arguments->datatype[index] = NULL;
            }
1576
        } else if ((0 == strncmp(argv[i], "-w", strlen("-w")))
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
                || (0 == strncmp(argv[i], "--binwidth", strlen("--binwidth")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "w");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "w");
                    exit(EXIT_FAILURE);
                }
                arguments->binwidth = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--binwidth=", strlen("--binwidth="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--binwidth=")))) {
                    arguments->binwidth = atoi((char *)(argv[i]+strlen("--binwidth=")));
                } else {
                    errorPrintReqArg2(argv[0], "--binwidth");
                    exit(EXIT_FAILURE);
                }
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
            } else if (0 == strncmp(argv[i], "-w", strlen("-w"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-w")))) {
                    arguments->binwidth = atoi((char *)(argv[i]+strlen("-w")));
                } else {
                    errorPrintReqArg2(argv[0], "-w");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--binwidth") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--binwidth");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--binwidth");
                    exit(EXIT_FAILURE);
                }
                arguments->binwidth = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1613
            }
1614
        } else if ((0 == strncmp(argv[i], "-m", strlen("-m")))
1615 1616 1617
                || (0 == strncmp(argv[i], "--table-prefix", strlen("--table-prefix")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
1618
                    errorPrintReqArg(argv[0], "m");
1619 1620 1621 1622 1623
                    exit(EXIT_FAILURE);
                }
                arguments->tb_prefix = argv[++i];
            } else if (0 == strncmp(argv[i], "--table-prefix=", strlen("--table-prefix="))) {
                arguments->tb_prefix = (char *)(argv[i] + strlen("--table-prefix="));
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
            } else if (0 == strncmp(argv[i], "-m", strlen("-m"))) {
                arguments->tb_prefix = (char *)(argv[i] + strlen("-m"));
            } else if (strlen("--table-prefix") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--table-prefix");
                    exit(EXIT_FAILURE);
                }
                arguments->tb_prefix = argv[++i];
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1635
            }
1636 1637
        } else if ((strcmp(argv[i], "-N") == 0)
                || (0 == strcmp(argv[i], "--normal-table"))) {
1638
            arguments->use_metric = false;
1639 1640
        } else if ((strcmp(argv[i], "-M") == 0)
                || (0 == strcmp(argv[i], "--random"))) {
1641
            arguments->demo_mode = false;
1642 1643
        } else if ((strcmp(argv[i], "-x") == 0)
                || (0 == strcmp(argv[i], "--no-insert"))) {
1644
            arguments->insert_only = false;
1645 1646
        } else if ((strcmp(argv[i], "-y") == 0)
                || (0 == strcmp(argv[i], "--answer-yes"))) {
1647
            arguments->answer_yes = true;
1648 1649
        } else if ((strcmp(argv[i], "-g") == 0)
                || (0 == strcmp(argv[i], "--debug"))) {
1650 1651 1652
            arguments->debug_print = true;
        } else if (strcmp(argv[i], "-gg") == 0) {
            arguments->verbose_print = true;
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
        } else if ((0 == strncmp(argv[i], "-R", strlen("-R")))
                || (0 == strncmp(argv[i], "--disorder-range",
                        strlen("--disorder-range")))) {
            if (strlen("-R") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "R");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "R");
                    exit(EXIT_FAILURE);
                }
                arguments->disorderRange = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--disorder-range=",
                        strlen("--disorder-range="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--disorder-range=")))) {
                    arguments->disorderRange =
                        atoi((char *)(argv[i]+strlen("--disorder-range=")));
                } else {
                    errorPrintReqArg2(argv[0], "--disorder-range");
                    exit(EXIT_FAILURE);
                }
            } else if (0 == strncmp(argv[i], "-R", strlen("-R"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-R")))) {
                    arguments->disorderRange =
                        atoi((char *)(argv[i]+strlen("-R")));
                } else {
                    errorPrintReqArg2(argv[0], "-R");
                    exit(EXIT_FAILURE);
                }

                if (arguments->disorderRange < 0) {
                    errorPrint("Invalid disorder range %d, will be set to %d\n",
                            arguments->disorderRange, 1000);
                    arguments->disorderRange = 1000;
                }
            } else if (strlen("--disorder-range") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--disorder-range");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--disorder-range");
                    exit(EXIT_FAILURE);
                }
                arguments->disorderRange = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
            }
1701
        } else if ((0 == strncmp(argv[i], "-O", strlen("-O")))
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
                || (0 == strncmp(argv[i], "--disorder", strlen("--disorder")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "O");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "O");
                    exit(EXIT_FAILURE);
                }
                arguments->disorderRatio = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--disorder=", strlen("--disorder="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--disorder=")))) {
                    arguments->disorderRatio = atoi((char *)(argv[i]+strlen("--disorder=")));
                } else {
                    errorPrintReqArg2(argv[0], "--disorder");
                    exit(EXIT_FAILURE);
                }
1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
            } else if (0 == strncmp(argv[i], "-O", strlen("-O"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-O")))) {
                    arguments->disorderRatio = atoi((char *)(argv[i]+strlen("-O")));
                } else {
                    errorPrintReqArg2(argv[0], "-O");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--disorder") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--disorder");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--disorder");
                    exit(EXIT_FAILURE);
                }
                arguments->disorderRatio = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1738
            }
1739

1740
            if (arguments->disorderRatio > 50) {
1741 1742
                errorPrint("Invalid disorder ratio %d, will be set to %d\n",
                        arguments->disorderRatio, 50);
1743 1744
                arguments->disorderRatio = 50;
            }
1745

1746
            if (arguments->disorderRatio < 0) {
1747 1748
                errorPrint("Invalid disorder ratio %d, will be set to %d\n",
                        arguments->disorderRatio, 0);
1749 1750
                arguments->disorderRatio = 0;
            }
1751
        } else if ((0 == strncmp(argv[i], "-a", strlen("-a")))
1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
                || (0 == strncmp(argv[i], "--replica",
                        strlen("--replica")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg(argv[0], "a");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "a");
                    exit(EXIT_FAILURE);
                }
                arguments->replica = atoi(argv[++i]);
            } else if (0 == strncmp(argv[i], "--replica=",
                        strlen("--replica="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--replica=")))) {
                    arguments->replica =
                        atoi((char *)(argv[i]+strlen("--replica=")));
                } else {
                    errorPrintReqArg2(argv[0], "--replica");
                    exit(EXIT_FAILURE);
                }
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
            } else if (0 == strncmp(argv[i], "-a", strlen("-a"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-a")))) {
                    arguments->replica =
                        atoi((char *)(argv[i]+strlen("-a")));
                } else {
                    errorPrintReqArg2(argv[0], "-a");
                    exit(EXIT_FAILURE);
                }
            } else if (strlen("--replica") == strlen(argv[i])) {
                if (argc == i+1) {
                    errorPrintReqArg3(argv[0], "--replica");
                    exit(EXIT_FAILURE);
                } else if (!isStringNumber(argv[i+1])) {
                    errorPrintReqArg2(argv[0], "--replica");
                    exit(EXIT_FAILURE);
                }
                arguments->replica = atoi(argv[++i]);
            } else {
                errorUnreconized(argv[0], argv[i]);
                exit(EXIT_FAILURE);
1792
            }
1793

1794
            if (arguments->replica > 3 || arguments->replica < 1) {
1795 1796
                errorPrint("Invalid replica value %d, will be set to %d\n",
                        arguments->replica, 1);
1797 1798 1799 1800 1801 1802 1803 1804
                arguments->replica = 1;
            }
        } else if (strcmp(argv[i], "-D") == 0) {
            arguments->method_of_delete = atoi(argv[++i]);
            if (arguments->method_of_delete > 3) {
                errorPrint("%s", "\n\t-D need a valud (0~3) number following!\n");
                exit(EXIT_FAILURE);
            }
1805 1806
        } else if ((strcmp(argv[i], "--version") == 0)
                || (strcmp(argv[i], "-V") == 0)) {
1807 1808
            printVersion();
            exit(0);
1809 1810
        } else if ((strcmp(argv[i], "--help") == 0)
                || (strcmp(argv[i], "-?") == 0)) {
1811 1812
            printHelp();
            exit(0);
1813 1814 1815 1816 1817 1818 1819 1820 1821
        } else if (strcmp(argv[i], "--usage") == 0) {
            printf("    Usage: taosdemo [-f JSONFILE] [-u USER] [-p PASSWORD] [-c CONFIG_DIR]\n\
                    [-h HOST] [-P PORT] [-I INTERFACE] [-d DATABASE] [-a REPLICA]\n\
                    [-m TABLEPREFIX] [-s SQLFILE] [-N] [-o OUTPUTFILE] [-q QUERYMODE]\n\
                    [-b DATATYPES] [-w WIDTH_OF_BINARY] [-l COLUNNS] [-T THREADNUMBER]\n\
                    [-i SLEEPTIME] [-S TIME_STEP] [-B INTERLACE_ROWS] [-t TABLES]\n\
                    [-n RECORDS] [-M] [-x] [-y] [-O ORDERMODE] [-R RANGE] [-a REPLIcA][-g]\n\
                    [--help] [--usage] [--version]\n");
            exit(0);
1822
        } else {
1823 1824
            // to simulate argp_option output
            if (strlen(argv[i]) > 2) {
1825 1826 1827 1828 1829 1830 1831 1832 1833
                if (0 == strncmp(argv[i], "--", 2)) {
                    fprintf(stderr, "%s: unrecognized options '%s'\n", argv[0], argv[i]);
                } else if (0 == strncmp(argv[i], "-", 1)) {
                    char tmp[2] = {0};
                    tstrncpy(tmp, argv[i]+1, 2);
                    fprintf(stderr, "%s: invalid options -- '%s'\n", argv[0], tmp);
                } else {
                    fprintf(stderr, "%s: Too many arguments\n", argv[0]);
                }
1834 1835 1836 1837 1838
            } else {
                fprintf(stderr, "%s invalid options -- '%s'\n", argv[0],
                        (char *)((char *)argv[i])+1);
            }
            fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
1839 1840
            exit(EXIT_FAILURE);
        }
S
TD-1057  
Shengliang Guan 已提交
1841
    }
1842

1843
    int columnCount;
1844
    for (columnCount = 0; columnCount < MAX_NUM_COLUMNS; columnCount ++) {
1845 1846 1847
        if (g_args.datatype[columnCount] == NULL) {
            break;
        }
1848 1849
    }

1850
    if (0 == columnCount) {
1851
        ERROR_EXIT("data type error!");
1852 1853 1854
    }
    g_args.num_of_CPR = columnCount;

1855
    if (((arguments->debug_print) && (NULL != arguments->metaFile))
1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867
            || arguments->verbose_print) {
        printf("###################################################################\n");
        printf("# meta file:                         %s\n", arguments->metaFile);
        printf("# Server IP:                         %s:%hu\n",
                arguments->host == NULL ? "localhost" : arguments->host,
                arguments->port );
        printf("# User:                              %s\n", arguments->user);
        printf("# Password:                          %s\n", arguments->password);
        printf("# Use metric:                        %s\n",
                arguments->use_metric ? "true" : "false");
        if (*(arguments->datatype)) {
            printf("# Specified data type:               ");
1868 1869 1870
            for (int c = 0; c < MAX_NUM_COLUMNS; c++)
                if (arguments->datatype[c])
                    printf("%s,", arguments->datatype[c]);
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880
                else
                    break;
            printf("\n");
        }
        printf("# Insertion interval:                %"PRIu64"\n",
                arguments->insert_interval);
        printf("# Number of records per req:         %u\n",
                arguments->num_of_RPR);
        printf("# Max SQL length:                    %"PRIu64"\n",
                arguments->max_sql_len);
1881
        printf("# Length of Binary:                  %d\n", arguments->binwidth);
1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899
        printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
        printf("# Number of Tables:                  %"PRId64"\n",
                arguments->num_of_tables);
        printf("# Number of Data per Table:          %"PRId64"\n",
                arguments->num_of_DPT);
        printf("# Database name:                     %s\n", arguments->database);
        printf("# Table prefix:                      %s\n", arguments->tb_prefix);
        if (arguments->disorderRatio) {
            printf("# Data order:                        %d\n", arguments->disorderRatio);
            printf("# Data out of order rate:            %d\n", arguments->disorderRange);
        }
        printf("# Delete method:                     %d\n", arguments->method_of_delete);
        printf("# Answer yes when prompt:            %d\n", arguments->answer_yes);
        printf("# Print debug info:                  %d\n", arguments->debug_print);
        printf("# Print verbose info:                %d\n", arguments->verbose_print);
        printf("###################################################################\n");

        prompt();
1900
    }
1901
}
H
hzcheng 已提交
1902

1903
static void tmfclose(FILE *fp) {
1904 1905 1906
    if (NULL != fp) {
        fclose(fp);
    }
1907
}
1908

1909
static void tmfree(char *buf) {
1910 1911 1912
    if (NULL != buf) {
        free(buf);
    }
1913
}
H
Hui Li 已提交
1914

1915
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1916 1917 1918 1919 1920 1921 1922 1923 1924
    int i;
    TAOS_RES *res = NULL;
    int32_t   code = -1;

    for (i = 0; i < 5 /* retry */; i++) {
        if (NULL != res) {
            taos_free_result(res);
            res = NULL;
        }
1925

1926 1927 1928 1929 1930
        res = taos_query(taos, command);
        code = taos_errno(res);
        if (0 == code) {
            break;
        }
H
hzcheng 已提交
1931
    }
1932

1933 1934 1935
    verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
    if (code != 0) {
        if (!quiet) {
1936
            errorPrint2("Failed to execute %s, reason: %s\n",
1937 1938 1939 1940 1941
                    command, taos_errstr(res));
        }
        taos_free_result(res);
        //taos_close(taos);
        return -1;
1942
    }
H
hzcheng 已提交
1943

1944 1945 1946 1947
    if (INSERT_TYPE == type) {
        int affectedRows = taos_affected_rows(res);
        taos_free_result(res);
        return affectedRows;
1948
    }
H
hzcheng 已提交
1949

1950
    taos_free_result(res);
1951
    return 0;
1952
}
H
hzcheng 已提交
1953

1954
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
1955
{
1956 1957
    pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
    if (pThreadInfo->fp == NULL) {
1958
        errorPrint2(
1959 1960 1961 1962
                "%s() LN%d, failed to open result file: %s, result will not save to file\n",
                __func__, __LINE__, pThreadInfo->filePath);
        return;
    }
1963

1964 1965 1966
    fprintf(pThreadInfo->fp, "%s", resultBuf);
    tmfclose(pThreadInfo->fp);
    pThreadInfo->fp = NULL;
1967 1968
}

1969
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
1970 1971 1972 1973 1974 1975 1976
    TAOS_ROW    row = NULL;
    int         num_rows = 0;
    int         num_fields = taos_field_count(res);
    TAOS_FIELD *fields     = taos_fetch_fields(res);

    char* databuf = (char*) calloc(1, 100*1024*1024);
    if (databuf == NULL) {
1977
        errorPrint2("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
1978 1979 1980
                __func__, __LINE__);
        return ;
    }
H
hzcheng 已提交
1981

1982
    int64_t   totalLen = 0;
H
hzcheng 已提交
1983

1984 1985
    // fetch the records row by row
    while((row = taos_fetch_row(res))) {
1986
        if (totalLen >= (100*1024*1024 - HEAD_BUFF_LEN*2)) {
1987 1988 1989 1990 1991 1992
            if (strlen(pThreadInfo->filePath) > 0)
                appendResultBufToFile(databuf, pThreadInfo);
            totalLen = 0;
            memset(databuf, 0, 100*1024*1024);
        }
        num_rows++;
1993
        char  temp[HEAD_BUFF_LEN] = {0};
1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
        int len = taos_print_row(temp, row, fields, num_fields);
        len += sprintf(temp + len, "\n");
        //printf("query result:%s\n", temp);
        memcpy(databuf + totalLen, temp, len);
        totalLen += len;
        verbosePrint("%s() LN%d, totalLen: %"PRId64"\n",
                __func__, __LINE__, totalLen);
    }

    verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
            __func__, __LINE__, databuf, pThreadInfo->filePath);
    if (strlen(pThreadInfo->filePath) > 0) {
        appendResultBufToFile(databuf, pThreadInfo);
    }
    free(databuf);
2009
}
H
hzcheng 已提交
2010

2011
static void selectAndGetResult(
2012 2013
        threadInfo *pThreadInfo, char *command)
{
2014 2015 2016
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
        TAOS_RES *res = taos_query(pThreadInfo->taos, command);
        if (res == NULL || taos_errno(res) != 0) {
2017
            errorPrint2("%s() LN%d, failed to execute sql:%s, reason:%s\n",
2018 2019 2020 2021
                    __func__, __LINE__, command, taos_errstr(res));
            taos_free_result(res);
            return;
        }
2022

2023 2024
        fetchResult(res, pThreadInfo);
        taos_free_result(res);
2025

2026 2027 2028 2029 2030 2031 2032 2033
    } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
        int retCode = postProceSql(
                g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
                command,
                pThreadInfo);
        if (0 != retCode) {
            printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
        }
2034

2035
    } else {
2036
        errorPrint2("%s() LN%d, unknown query mode: %s\n",
2037 2038
                __func__, __LINE__, g_queryInfo.queryMode);
    }
2039
}
H
hzcheng 已提交
2040

2041
static char *rand_bool_str() {
2042 2043 2044
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2045
    return g_randbool_buff + ((cursor % MAX_PREPARED_RAND) * BOOL_BUFF_LEN);
2046 2047
}

2048
static int32_t rand_bool() {
2049 2050
    static int cursor;
    cursor++;
2051 2052
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 2;
2053 2054
}

2055 2056 2057 2058 2059
static char *rand_tinyint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2060 2061
    return g_randtinyint_buff +
        ((cursor % MAX_PREPARED_RAND) * TINYINT_BUFF_LEN);
2062 2063 2064 2065
}

static int32_t rand_tinyint()
{
2066 2067
    static int cursor;
    cursor++;
2068 2069
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 128;
2070 2071 2072 2073 2074 2075 2076
}

static char *rand_smallint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2077 2078
    return g_randsmallint_buff +
        ((cursor % MAX_PREPARED_RAND) * SMALLINT_BUFF_LEN);
2079 2080
}

2081 2082
static int32_t rand_smallint()
{
2083 2084
    static int cursor;
    cursor++;
2085 2086
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 32767;
2087 2088
}

2089 2090 2091 2092 2093
static char *rand_int_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2094
    return g_randint_buff + ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN);
2095 2096 2097 2098
}

static int32_t rand_int()
{
2099 2100
    static int cursor;
    cursor++;
2101 2102
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND];
2103 2104 2105 2106 2107 2108 2109
}

static char *rand_bigint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2110 2111
    return g_randbigint_buff +
        ((cursor % MAX_PREPARED_RAND) * BIGINT_BUFF_LEN);
2112 2113
}

2114 2115
static int64_t rand_bigint()
{
2116 2117
    static int cursor;
    cursor++;
2118 2119
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randbigint[cursor % MAX_PREPARED_RAND];
2120 2121
}

2122 2123 2124 2125 2126
static char *rand_float_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2127
    return g_randfloat_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2128 2129
}

S
Shengliang Guan 已提交
2130

2131 2132
static float rand_float()
{
2133 2134
    static int cursor;
    cursor++;
2135 2136
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randfloat[cursor % MAX_PREPARED_RAND];
2137 2138
}

2139 2140 2141 2142 2143
static char *demo_current_float_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2144 2145
    return g_rand_current_buff +
        ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2146 2147 2148 2149
}

static float UNUSED_FUNC demo_current_float()
{
2150 2151
    static int cursor;
    cursor++;
2152 2153 2154
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return (float)(9.8 + 0.04 * (g_randint[cursor % MAX_PREPARED_RAND] % 10)
            + g_randfloat[cursor % MAX_PREPARED_RAND]/1000000000);
2155 2156 2157 2158 2159 2160 2161
}

static char *demo_voltage_int_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2162 2163
    return g_rand_voltage_buff +
        ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN);
2164 2165
}

2166 2167
static int32_t UNUSED_FUNC demo_voltage_int()
{
2168 2169
    static int cursor;
    cursor++;
2170 2171
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return 215 + g_randint[cursor % MAX_PREPARED_RAND] % 10;
2172 2173 2174 2175 2176 2177
}

static char *demo_phase_float_str() {
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2178
    return g_rand_phase_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2179 2180
}

2181
static float UNUSED_FUNC demo_phase_float() {
2182 2183
    static int cursor;
    cursor++;
2184 2185 2186
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return (float)((115 + g_randint[cursor % MAX_PREPARED_RAND] % 10
                + g_randfloat[cursor % MAX_PREPARED_RAND]/1000000000)/360);
2187 2188
}

2189 2190 2191 2192 2193 2194
#if 0
static const char charNum[] = "0123456789";

static void nonrand_string(char *, int) __attribute__ ((unused));   // reserve for debugging purpose
static void nonrand_string(char *str, int size)
{
2195 2196 2197 2198 2199 2200 2201 2202
    str[0] = 0;
    if (size > 0) {
        int n;
        for (n = 0; n < size; n++) {
            str[n] = charNum[n % 10];
        }
        str[n] = 0;
    }
2203 2204 2205
}
#endif

2206
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
2207

2208
static void rand_string(char *str, int size) {
2209 2210 2211 2212 2213 2214 2215 2216 2217
    str[0] = 0;
    if (size > 0) {
        //--size;
        int n;
        for (n = 0; n < size; n++) {
            int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
            str[n] = charset[key];
        }
        str[n] = 0;
2218 2219 2220
    }
}

2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
static char *rand_double_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randdouble_buff + (cursor * DOUBLE_BUFF_LEN);
}

static double rand_double()
{
2231 2232 2233
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
2234
    return g_randdouble[cursor];
2235 2236 2237
}

static void init_rand_data() {
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259

    g_randint_buff = calloc(1, INT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randint_buff);
    g_rand_voltage_buff = calloc(1, INT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_rand_voltage_buff);
    g_randbigint_buff = calloc(1, BIGINT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randbigint_buff);
    g_randsmallint_buff = calloc(1, SMALLINT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randsmallint_buff);
    g_randtinyint_buff = calloc(1, TINYINT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randtinyint_buff);
    g_randbool_buff = calloc(1, BOOL_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randbool_buff);
    g_randfloat_buff = calloc(1, FLOAT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randfloat_buff);
    g_rand_current_buff = calloc(1, FLOAT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_rand_current_buff);
    g_rand_phase_buff = calloc(1, FLOAT_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_rand_phase_buff);
    g_randdouble_buff = calloc(1, DOUBLE_BUFF_LEN * MAX_PREPARED_RAND);
    assert(g_randdouble_buff);

2260
    for (int i = 0; i < MAX_PREPARED_RAND; i++) {
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290
        g_randint[i] = (int)(taosRandom() % 65535);
        sprintf(g_randint_buff + i * INT_BUFF_LEN, "%d",
                g_randint[i]);
        sprintf(g_rand_voltage_buff + i * INT_BUFF_LEN, "%d",
                215 + g_randint[i] % 10);

        sprintf(g_randbool_buff + i * BOOL_BUFF_LEN, "%s",
                ((g_randint[i] % 2) & 1)?"true":"false");
        sprintf(g_randsmallint_buff + i * SMALLINT_BUFF_LEN, "%d",
                g_randint[i] % 32767);
        sprintf(g_randtinyint_buff + i * TINYINT_BUFF_LEN, "%d",
                g_randint[i] % 128);

        g_randbigint[i] = (int64_t)(taosRandom() % 2147483648);
        sprintf(g_randbigint_buff + i * BIGINT_BUFF_LEN, "%"PRId64"",
                g_randbigint[i]);

        g_randfloat[i] = (float)(taosRandom() / 1000.0);
        sprintf(g_randfloat_buff + i * FLOAT_BUFF_LEN, "%f",
                g_randfloat[i]);
        sprintf(g_rand_current_buff + i * FLOAT_BUFF_LEN, "%f",
                (float)(9.8 + 0.04 * (g_randint[i] % 10)
                    + g_randfloat[i]/1000000000));
        sprintf(g_rand_phase_buff + i * FLOAT_BUFF_LEN, "%f",
                (float)((115 + g_randint[i] % 10
                        + g_randfloat[i]/1000000000)/360));

        g_randdouble[i] = (double)(taosRandom() / 1000000.0);
        sprintf(g_randdouble_buff + i * DOUBLE_BUFF_LEN, "%f",
                g_randdouble[i]);
2291
    }
2292 2293
}

2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313
#define SHOW_PARSE_RESULT_START()   \
    do { if (g_args.metaFile)  \
        printf("\033[1m\033[40;32m================ %s parse result START ================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_END() \
    do { if (g_args.metaFile)   \
        printf("\033[1m\033[40;32m================ %s parse result END================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_START_TO_FILE(fp)   \
    do { if (g_args.metaFile)  \
        fprintf(fp, "\033[1m\033[40;32m================ %s parse result START ================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_END_TO_FILE(fp) \
    do { if (g_args.metaFile)   \
        fprintf(fp, "\033[1m\033[40;32m================ %s parse result END================\033[0m\n", \
                g_args.metaFile); } while(0)

2314
static int printfInsertMeta() {
2315
    SHOW_PARSE_RESULT_START();
2316

2317 2318 2319 2320 2321
    if (g_args.demo_mode)
        printf("\ntaosdemo is simulating data generated by power equipments monitoring...\n\n");
    else
        printf("\ntaosdemo is simulating random data as you request..\n\n");

2322 2323 2324
    if (g_args.iface != INTERFACE_BUT) {
        // first time if no iface specified
        printf("interface:                  \033[33m%s\033[0m\n",
2325 2326
                (g_args.iface==TAOSC_IFACE)?"taosc":
                (g_args.iface==REST_IFACE)?"rest":"stmt");
2327 2328
    }

2329 2330 2331 2332 2333 2334 2335 2336
    printf("host:                       \033[33m%s:%u\033[0m\n",
            g_Dbs.host, g_Dbs.port);
    printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
    printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
    printf("configDir:                  \033[33m%s\033[0m\n", configDir);
    printf("resultFile:                 \033[33m%s\033[0m\n", g_Dbs.resultFile);
    printf("thread num of insert data:  \033[33m%d\033[0m\n", g_Dbs.threadCount);
    printf("thread num of create table: \033[33m%d\033[0m\n",
2337
            g_Dbs.threadCountForCreateTbl);
2338 2339 2340 2341 2342 2343 2344 2345
    printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
            g_args.insert_interval);
    printf("number of records per req:  \033[33m%u\033[0m\n",
            g_args.num_of_RPR);
    printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
            g_args.max_sql_len);

    printf("database count:             \033[33m%d\033[0m\n", g_Dbs.dbCount);
2346

2347 2348 2349 2350 2351 2352 2353 2354 2355
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        printf("database[\033[33m%d\033[0m]:\n", i);
        printf("  database[%d] name:      \033[33m%s\033[0m\n",
                i, g_Dbs.db[i].dbName);
        if (0 == g_Dbs.db[i].drop) {
            printf("  drop:                  \033[33mno\033[0m\n");
        } else {
            printf("  drop:                  \033[33myes\033[0m\n");
        }
2356

2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
        if (g_Dbs.db[i].dbCfg.blocks > 0) {
            printf("  blocks:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.blocks);
        }
        if (g_Dbs.db[i].dbCfg.cache > 0) {
            printf("  cache:                 \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.cache);
        }
        if (g_Dbs.db[i].dbCfg.days > 0) {
            printf("  days:                  \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.days);
        }
        if (g_Dbs.db[i].dbCfg.keep > 0) {
            printf("  keep:                  \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.keep);
        }
        if (g_Dbs.db[i].dbCfg.replica > 0) {
            printf("  replica:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.replica);
        }
        if (g_Dbs.db[i].dbCfg.update > 0) {
            printf("  update:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.update);
        }
        if (g_Dbs.db[i].dbCfg.minRows > 0) {
            printf("  minRows:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.minRows);
        }
        if (g_Dbs.db[i].dbCfg.maxRows > 0) {
            printf("  maxRows:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.maxRows);
        }
        if (g_Dbs.db[i].dbCfg.comp > 0) {
            printf("  comp:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.comp);
        }
        if (g_Dbs.db[i].dbCfg.walLevel > 0) {
            printf("  walLevel:              \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.walLevel);
        }
        if (g_Dbs.db[i].dbCfg.fsync > 0) {
            printf("  fsync:                 \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.fsync);
        }
        if (g_Dbs.db[i].dbCfg.quorum > 0) {
            printf("  quorum:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.quorum);
        }
        if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
2406 2407
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2))) {
2408 2409 2410 2411 2412 2413 2414 2415
                printf("  precision:             \033[33m%s\033[0m\n",
                        g_Dbs.db[i].dbCfg.precision);
            } else {
                printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                        g_Dbs.db[i].dbCfg.precision);
                return -1;
            }
        }
2416

2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432
        printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
                g_Dbs.db[i].superTblCount);
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);

            printf("      stbName:           \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sTblName);

            if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "no");
            } else if (AUTO_CREATE_SUBTBL ==
                    g_Dbs.db[i].superTbls[j].autoCreateTable) {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "yes");
            } else {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "error");
            }
2433

2434 2435 2436 2437 2438 2439 2440
            if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "no");
            } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "yes");
            } else {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "error");
            }
2441

2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474
            printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].childTblCount);
            printf("      childTblPrefix:    \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].childTblPrefix);
            printf("      dataSource:        \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].dataSource);
            printf("      iface:             \033[33m%s\033[0m\n",
                    (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
                    (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
            if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
                printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].childTblLimit);
            }
            if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
                printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].childTblOffset);
            }
            printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].insertRows);
            /*
               if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
               printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
               }else {
               printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
               }
               */
            printf("      interlaceRows:     \033[33m%u\033[0m\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);

            if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
                printf("      stable insert interval:   \033[33m%"PRIu64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].insertInterval);
            }
2475

2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
            printf("      disorderRange:     \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].disorderRange);
            printf("      disorderRatio:     \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].disorderRatio);
            printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].maxSqlLen);
            printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].timeStampStep);
            printf("      startTimestamp:    \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].startTimestamp);
            printf("      sampleFormat:      \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sampleFormat);
            printf("      sampleFile:        \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sampleFile);
            printf("      tagsFile:          \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].tagsFile);
            printf("      columnCount:       \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].columnCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "binary", 6))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "nchar", 5))) {
                    printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType,
                            g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                } else {
                    printf("column[%d]:\033[33m%s\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType);
                }
            }
            printf("\n");

            printf("      tagCount:            \033[33m%d\033[0m\n        ",
                    g_Dbs.db[i].superTbls[j].tagCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "nchar", strlen("nchar")))) {
                    printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].tags[k].dataType,
                            g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                } else {
                    printf("tag[%d]:\033[33m%s\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].tags[k].dataType);
                }
            }
            printf("\n");
2527
        }
2528
        printf("\n");
2529
    }
2530

2531
    SHOW_PARSE_RESULT_END();
2532

2533
    return 0;
2534 2535 2536
}

static void printfInsertMetaToFile(FILE* fp) {
2537

2538
    SHOW_PARSE_RESULT_START_TO_FILE(fp);
2539

2540 2541 2542 2543 2544
    fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
    fprintf(fp, "user:                       %s\n", g_Dbs.user);
    fprintf(fp, "configDir:                  %s\n", configDir);
    fprintf(fp, "resultFile:                 %s\n", g_Dbs.resultFile);
    fprintf(fp, "thread num of insert data:  %d\n", g_Dbs.threadCount);
2545
    fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountForCreateTbl);
2546 2547 2548
    fprintf(fp, "number of records per req:  %u\n", g_args.num_of_RPR);
    fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
    fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
2549

2550 2551 2552 2553 2554 2555 2556 2557
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        fprintf(fp, "database[%d]:\n", i);
        fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
        if (0 == g_Dbs.db[i].drop) {
            fprintf(fp, "  drop:                  no\n");
        }else {
            fprintf(fp, "  drop:                  yes\n");
        }
2558

2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596
        if (g_Dbs.db[i].dbCfg.blocks > 0) {
            fprintf(fp, "  blocks:                %d\n", g_Dbs.db[i].dbCfg.blocks);
        }
        if (g_Dbs.db[i].dbCfg.cache > 0) {
            fprintf(fp, "  cache:                 %d\n", g_Dbs.db[i].dbCfg.cache);
        }
        if (g_Dbs.db[i].dbCfg.days > 0) {
            fprintf(fp, "  days:                  %d\n", g_Dbs.db[i].dbCfg.days);
        }
        if (g_Dbs.db[i].dbCfg.keep > 0) {
            fprintf(fp, "  keep:                  %d\n", g_Dbs.db[i].dbCfg.keep);
        }
        if (g_Dbs.db[i].dbCfg.replica > 0) {
            fprintf(fp, "  replica:               %d\n", g_Dbs.db[i].dbCfg.replica);
        }
        if (g_Dbs.db[i].dbCfg.update > 0) {
            fprintf(fp, "  update:                %d\n", g_Dbs.db[i].dbCfg.update);
        }
        if (g_Dbs.db[i].dbCfg.minRows > 0) {
            fprintf(fp, "  minRows:               %d\n", g_Dbs.db[i].dbCfg.minRows);
        }
        if (g_Dbs.db[i].dbCfg.maxRows > 0) {
            fprintf(fp, "  maxRows:               %d\n", g_Dbs.db[i].dbCfg.maxRows);
        }
        if (g_Dbs.db[i].dbCfg.comp > 0) {
            fprintf(fp, "  comp:                  %d\n", g_Dbs.db[i].dbCfg.comp);
        }
        if (g_Dbs.db[i].dbCfg.walLevel > 0) {
            fprintf(fp, "  walLevel:              %d\n", g_Dbs.db[i].dbCfg.walLevel);
        }
        if (g_Dbs.db[i].dbCfg.fsync > 0) {
            fprintf(fp, "  fsync:                 %d\n", g_Dbs.db[i].dbCfg.fsync);
        }
        if (g_Dbs.db[i].dbCfg.quorum > 0) {
            fprintf(fp, "  quorum:                %d\n", g_Dbs.db[i].dbCfg.quorum);
        }
        if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
2597
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2))
2598 2599 2600 2601 2602 2603 2604 2605
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
                fprintf(fp, "  precision:             %s\n",
                        g_Dbs.db[i].dbCfg.precision);
            } else {
                fprintf(fp, "  precision error:       %s\n",
                        g_Dbs.db[i].dbCfg.precision);
            }
        }
2606

2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622
        fprintf(fp, "  super table count:     %"PRIu64"\n",
                g_Dbs.db[i].superTblCount);
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            fprintf(fp, "  super table[%d]:\n", j);

            fprintf(fp, "      stbName:           %s\n",
                    g_Dbs.db[i].superTbls[j].sTblName);

            if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                fprintf(fp, "      autoCreateTable:   %s\n",  "no");
            } else if (AUTO_CREATE_SUBTBL
                    == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
            } else {
                fprintf(fp, "      autoCreateTable:   %s\n",  "error");
            }
2623

2624 2625 2626 2627 2628 2629 2630 2631
            if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                fprintf(fp, "      childTblExists:    %s\n",  "no");
            } else if (TBL_ALREADY_EXISTS
                    == g_Dbs.db[i].superTbls[j].childTblExists) {
                fprintf(fp, "      childTblExists:    %s\n",  "yes");
            } else {
                fprintf(fp, "      childTblExists:    %s\n",  "error");
            }
2632

2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712
            fprintf(fp, "      childTblCount:     %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].childTblCount);
            fprintf(fp, "      childTblPrefix:    %s\n",
                    g_Dbs.db[i].superTbls[j].childTblPrefix);
            fprintf(fp, "      dataSource:        %s\n",
                    g_Dbs.db[i].superTbls[j].dataSource);
            fprintf(fp, "      iface:             %s\n",
                    (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
                    (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
            fprintf(fp, "      insertRows:        %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].insertRows);
            fprintf(fp, "      interlace rows:    %u\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);
            if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
                fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
                        g_Dbs.db[i].superTbls[j].insertInterval);
            }
            /*
               if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
               fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
               }else {
               fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
               }
               */
            fprintf(fp, "      interlaceRows:     %u\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);
            fprintf(fp, "      disorderRange:     %d\n",
                    g_Dbs.db[i].superTbls[j].disorderRange);
            fprintf(fp, "      disorderRatio:     %d\n",
                    g_Dbs.db[i].superTbls[j].disorderRatio);
            fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
                    g_Dbs.db[i].superTbls[j].maxSqlLen);

            fprintf(fp, "      timeStampStep:     %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].timeStampStep);
            fprintf(fp, "      startTimestamp:    %s\n",
                    g_Dbs.db[i].superTbls[j].startTimestamp);
            fprintf(fp, "      sampleFormat:      %s\n",
                    g_Dbs.db[i].superTbls[j].sampleFormat);
            fprintf(fp, "      sampleFile:        %s\n",
                    g_Dbs.db[i].superTbls[j].sampleFile);
            fprintf(fp, "      tagsFile:          %s\n",
                    g_Dbs.db[i].superTbls[j].tagsFile);

            fprintf(fp, "      columnCount:       %d\n        ",
                    g_Dbs.db[i].superTbls[j].columnCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                if ((0 == strncasecmp(
                                g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(
                                g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "nchar", strlen("nchar")))) {
                    fprintf(fp, "column[%d]:%s(%d) ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType,
                            g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                } else {
                    fprintf(fp, "column[%d]:%s ",
                            k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
                }
            }
            fprintf(fp, "\n");

            fprintf(fp, "      tagCount:            %d\n        ",
                    g_Dbs.db[i].superTbls[j].tagCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "nchar", strlen("nchar")))) {
                    fprintf(fp, "tag[%d]:%s(%d) ",
                            k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
                            g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                } else {
                    fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
                }
            }
            fprintf(fp, "\n");
2713
        }
2714
        fprintf(fp, "\n");
2715
    }
2716

2717
    SHOW_PARSE_RESULT_END_TO_FILE(fp);
2718 2719 2720
}

static void printfQueryMeta() {
2721

2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 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
    SHOW_PARSE_RESULT_START();

    printf("host:                    \033[33m%s:%u\033[0m\n",
            g_queryInfo.host, g_queryInfo.port);
    printf("user:                    \033[33m%s\033[0m\n", g_queryInfo.user);
    printf("database name:           \033[33m%s\033[0m\n", g_queryInfo.dbName);

    printf("\n");

    if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) {
        printf("specified table query info:                   \n");
        printf("sqlCount:       \033[33m%d\033[0m\n",
                g_queryInfo.specifiedQueryInfo.sqlCount);
        if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
            printf("specified tbl query times:\n");
            printf("                \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.queryTimes);
            printf("query interval: \033[33m%"PRIu64" ms\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.queryInterval);
            printf("top query times:\033[33m%"PRIu64"\033[0m\n", g_args.query_times);
            printf("concurrent:     \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.concurrent);
            printf("mod:            \033[33m%s\033[0m\n",
                    (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
            printf("interval:       \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeInterval);
            printf("restart:        \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeRestart);
            printf("keepProgress:   \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);

            for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
                printf("  sql[%d]: \033[33m%s\033[0m\n",
                        i, g_queryInfo.specifiedQueryInfo.sql[i]);
            }
            printf("\n");
        }

        printf("super table query info:\n");
        printf("sqlCount:       \033[33m%d\033[0m\n",
                g_queryInfo.superQueryInfo.sqlCount);

        if (g_queryInfo.superQueryInfo.sqlCount > 0) {
            printf("query interval: \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.queryInterval);
            printf("threadCnt:      \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.threadCnt);
            printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
                    g_queryInfo.superQueryInfo.childTblCount);
            printf("stable name:    \033[33m%s\033[0m\n",
                    g_queryInfo.superQueryInfo.sTblName);
            printf("stb query times:\033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.queryTimes);

            printf("mod:            \033[33m%s\033[0m\n",
                    (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
            printf("interval:       \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeInterval);
            printf("restart:        \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeRestart);
            printf("keepProgress:   \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);

            for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
                printf("  sql[%d]: \033[33m%s\033[0m\n",
                        i, g_queryInfo.superQueryInfo.sql[i]);
            }
            printf("\n");
        }
2791
    }
2792

2793
    SHOW_PARSE_RESULT_END();
2794 2795
}

2796
static char* formatTimestamp(char* buf, int64_t val, int precision) {
2797
    time_t tt;
2798
    if (precision == TSDB_TIME_PRECISION_MICRO) {
2799
        tt = (time_t)(val / 1000000);
2800 2801
    } if (precision == TSDB_TIME_PRECISION_NANO) {
        tt = (time_t)(val / 1000000000);
2802 2803 2804
    } else {
        tt = (time_t)(val / 1000);
    }
2805

2806 2807 2808 2809 2810 2811 2812
    /* comment out as it make testcases like select_with_tags.sim fail.
       but in windows, this may cause the call to localtime crash if tt < 0,
       need to find a better solution.
       if (tt < 0) {
       tt = 0;
       }
       */
2813 2814

#ifdef WINDOWS
2815
    if (tt < 0) tt = 0;
2816 2817
#endif

2818 2819
    struct tm* ptm = localtime(&tt);
    size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);
2820

2821
    if (precision == TSDB_TIME_PRECISION_MICRO) {
2822
        sprintf(buf + pos, ".%06d", (int)(val % 1000000));
2823 2824
    } else if (precision == TSDB_TIME_PRECISION_NANO) {
        sprintf(buf + pos, ".%09d", (int)(val % 1000000000));
2825 2826 2827
    } else {
        sprintf(buf + pos, ".%03d", (int)(val % 1000));
    }
2828

2829
    return buf;
2830 2831
}

2832
static void xDumpFieldToFile(FILE* fp, const char* val,
2833
        TAOS_FIELD* field, int32_t length, int precision) {
2834

2835 2836 2837 2838
    if (val == NULL) {
        fprintf(fp, "%s", TSDB_DATA_NULL_STR);
        return;
    }
2839

2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
    char buf[TSDB_MAX_BYTES_PER_ROW];
    switch (field->type) {
        case TSDB_DATA_TYPE_BOOL:
            fprintf(fp, "%d", ((((int32_t)(*((char *)val))) == 1) ? 1 : 0));
            break;
        case TSDB_DATA_TYPE_TINYINT:
            fprintf(fp, "%d", *((int8_t *)val));
            break;
        case TSDB_DATA_TYPE_SMALLINT:
            fprintf(fp, "%d", *((int16_t *)val));
            break;
        case TSDB_DATA_TYPE_INT:
            fprintf(fp, "%d", *((int32_t *)val));
            break;
        case TSDB_DATA_TYPE_BIGINT:
2855
            fprintf(fp, "%"PRId64"", *((int64_t *)val));
2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875
            break;
        case TSDB_DATA_TYPE_FLOAT:
            fprintf(fp, "%.5f", GET_FLOAT_VAL(val));
            break;
        case TSDB_DATA_TYPE_DOUBLE:
            fprintf(fp, "%.9f", GET_DOUBLE_VAL(val));
            break;
        case TSDB_DATA_TYPE_BINARY:
        case TSDB_DATA_TYPE_NCHAR:
            memcpy(buf, val, length);
            buf[length] = 0;
            fprintf(fp, "\'%s\'", buf);
            break;
        case TSDB_DATA_TYPE_TIMESTAMP:
            formatTimestamp(buf, *(int64_t*)val, precision);
            fprintf(fp, "'%s'", buf);
            break;
        default:
            break;
    }
2876 2877 2878
}

static int xDumpResultToFile(const char* fname, TAOS_RES* tres) {
2879 2880 2881 2882
    TAOS_ROW row = taos_fetch_row(tres);
    if (row == NULL) {
        return 0;
    }
2883

2884 2885
    FILE* fp = fopen(fname, "at");
    if (fp == NULL) {
2886
        errorPrint2("%s() LN%d, failed to open file: %s\n",
2887 2888 2889
                __func__, __LINE__, fname);
        return -1;
    }
2890

2891 2892 2893
    int num_fields = taos_num_fields(tres);
    TAOS_FIELD *fields = taos_fetch_fields(tres);
    int precision = taos_result_precision(tres);
2894

2895 2896 2897 2898 2899
    for (int col = 0; col < num_fields; col++) {
        if (col > 0) {
            fprintf(fp, ",");
        }
        fprintf(fp, "%s", fields[col].name);
2900 2901 2902
    }
    fputc('\n', fp);

2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
    int numOfRows = 0;
    do {
        int32_t* length = taos_fetch_lengths(tres);
        for (int i = 0; i < num_fields; i++) {
            if (i > 0) {
                fputc(',', fp);
            }
            xDumpFieldToFile(fp,
                    (const char*)row[i], fields +i, length[i], precision);
        }
        fputc('\n', fp);

        numOfRows++;
        row = taos_fetch_row(tres);
    } while( row != NULL);
2918

2919
    fclose(fp);
2920

2921
    return numOfRows;
2922 2923
}

2924
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
2925 2926 2927
    TAOS_RES * res;
    TAOS_ROW row = NULL;
    int count = 0;
2928

2929 2930
    res = taos_query(taos, "show databases;");
    int32_t code = taos_errno(res);
2931

2932
    if (code != 0) {
2933
        errorPrint2("failed to run <show databases>, reason: %s\n",
2934 2935
                taos_errstr(res));
        return -1;
2936
    }
2937

2938
    TAOS_FIELD *fields = taos_fetch_fields(res);
2939

2940 2941 2942 2943 2944 2945
    while((row = taos_fetch_row(res)) != NULL) {
        // sys database name : 'log'
        if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
                    fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
            continue;
        }
2946

2947 2948
        dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo));
        if (dbInfos[count] == NULL) {
2949
            errorPrint2("failed to allocate memory for some dbInfo[%d]\n", count);
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988
            return -1;
        }

        tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
        formatTimestamp(dbInfos[count]->create_time,
                *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
                TSDB_TIME_PRECISION_MILLI);
        dbInfos[count]->ntables = *((int64_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
        dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
        dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
        dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
        dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);

        tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
                fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
        dbInfos[count]->cache = *((int32_t *)row[TSDB_SHOW_DB_CACHE_INDEX]);
        dbInfos[count]->blocks = *((int32_t *)row[TSDB_SHOW_DB_BLOCKS_INDEX]);
        dbInfos[count]->minrows = *((int32_t *)row[TSDB_SHOW_DB_MINROWS_INDEX]);
        dbInfos[count]->maxrows = *((int32_t *)row[TSDB_SHOW_DB_MAXROWS_INDEX]);
        dbInfos[count]->wallevel = *((int8_t *)row[TSDB_SHOW_DB_WALLEVEL_INDEX]);
        dbInfos[count]->fsync = *((int32_t *)row[TSDB_SHOW_DB_FSYNC_INDEX]);
        dbInfos[count]->comp = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX]));
        dbInfos[count]->cachelast =
            (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));

        tstrncpy(dbInfos[count]->precision,
                (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
                fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
        dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
        tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
                fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);

        count++;
        if (count > MAX_DATABASE_COUNT) {
            errorPrint("%s() LN%d, The database count overflow than %d\n",
                    __func__, __LINE__, MAX_DATABASE_COUNT);
            break;
        }
2989 2990
    }

2991
    return count;
2992 2993
}

2994
static void printfDbInfoForQueryToFile(
2995
        char* filename, SDbInfo* dbInfos, int index) {
2996

2997 2998
    if (filename[0] == 0)
        return;
2999

3000 3001 3002 3003 3004
    FILE *fp = fopen(filename, "at");
    if (fp == NULL) {
        errorPrint( "failed to open file: %s\n", filename);
        return;
    }
3005

3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
    fprintf(fp, "================ database[%d] ================\n", index);
    fprintf(fp, "name: %s\n", dbInfos->name);
    fprintf(fp, "created_time: %s\n", dbInfos->create_time);
    fprintf(fp, "ntables: %"PRId64"\n", dbInfos->ntables);
    fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
    fprintf(fp, "replica: %d\n", dbInfos->replica);
    fprintf(fp, "quorum: %d\n", dbInfos->quorum);
    fprintf(fp, "days: %d\n", dbInfos->days);
    fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
    fprintf(fp, "cache(MB): %d\n", dbInfos->cache);
    fprintf(fp, "blocks: %d\n", dbInfos->blocks);
    fprintf(fp, "minrows: %d\n", dbInfos->minrows);
    fprintf(fp, "maxrows: %d\n", dbInfos->maxrows);
    fprintf(fp, "wallevel: %d\n", dbInfos->wallevel);
    fprintf(fp, "fsync: %d\n", dbInfos->fsync);
    fprintf(fp, "comp: %d\n", dbInfos->comp);
    fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
    fprintf(fp, "precision: %s\n", dbInfos->precision);
    fprintf(fp, "update: %d\n", dbInfos->update);
    fprintf(fp, "status: %s\n", dbInfos->status);
    fprintf(fp, "\n");
3027

3028
    fclose(fp);
3029 3030 3031
}

static void printfQuerySystemInfo(TAOS * taos) {
3032 3033
    char filename[MAX_FILE_NAME_LEN] = {0};
    char buffer[1024] = {0};
3034 3035 3036 3037 3038 3039
    TAOS_RES* res;

    time_t t;
    struct tm* lt;
    time(&t);
    lt = localtime(&t);
3040
    snprintf(filename, MAX_FILE_NAME_LEN, "querySystemInfo-%d-%d-%d %d:%d:%d",
3041 3042 3043 3044 3045 3046
            lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
            lt->tm_sec);

    // show variables
    res = taos_query(taos, "show variables;");
    //fetchResult(res, filename);
3047
    xDumpResultToFile(filename, res);
3048

3049 3050
    // show dnodes
    res = taos_query(taos, "show dnodes;");
3051
    xDumpResultToFile(filename, res);
3052
    //fetchResult(res, filename);
3053

3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071
    // show databases
    res = taos_query(taos, "show databases;");
    SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
    if (dbInfos == NULL) {
        errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
        return;
    }
    int dbCount = getDbFromServer(taos, dbInfos);
    if (dbCount <= 0) {
        free(dbInfos);
        return;
    }

    for (int i = 0; i < dbCount; i++) {
        // printf database info
        printfDbInfoForQueryToFile(filename, dbInfos[i], i);

        // show db.vgroups
3072
        snprintf(buffer, 1024, "show %s.vgroups;", dbInfos[i]->name);
3073 3074 3075 3076
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);

        // show db.stables
3077
        snprintf(buffer, 1024, "show %s.stables;", dbInfos[i]->name);
3078 3079 3080 3081
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);
        free(dbInfos[i]);
    }
3082

3083
    free(dbInfos);
3084 3085
}

3086
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
3087
        char* sqlstr, threadInfo *pThreadInfo)
3088
{
3089
    char *req_fmt = "POST %s HTTP/1.1\r\nHost: %s:%d\r\nAccept: */*\r\nAuthorization: Basic %s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s";
3090

3091
    char *url = "/rest/sql";
3092

3093 3094 3095 3096
    int bytes, sent, received, req_str_len, resp_len;
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
3097

3098
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
3099

3100 3101
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
3102
        errorPrint("%s", "cannot allocate memory.\n");
3103
        exit(EXIT_FAILURE);
3104
    }
3105

3106 3107
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
3108

3109
    static char base64[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
3110 3111 3112 3113 3114 3115 3116
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
        'w', 'x', 'y', 'z', '0', '1', '2', '3',
        '4', '5', '6', '7', '8', '9', '+', '/'};
3117

3118
    snprintf(userpass_buf, INPUT_BUF_LEN, "%s:%s",
3119
            g_Dbs.user, g_Dbs.password);
3120 3121
    size_t userpass_buf_len = strlen(userpass_buf);
    size_t encoded_len = 4 * ((userpass_buf_len +2) / 3);
3122

3123
    char base64_buf[INPUT_BUF_LEN];
3124
#ifdef WINDOWS
3125
    WSADATA wsaData;
3126
    WSAStartup(MAKEWORD(2, 2), &wsaData);
3127 3128
    SOCKET sockfd;
#else
3129
    int sockfd;
3130
#endif
3131 3132
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
3133
#ifdef WINDOWS
3134
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
3135
#endif
3136 3137
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
3138
        ERROR_EXIT("opening socket");
3139
    }
3140

3141
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
3142 3143 3144
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
3145
        ERROR_EXIT("connecting");
3146
    }
3147

3148
    memset(base64_buf, 0, INPUT_BUF_LEN);
3149

3150
    for (int n = 0, m = 0; n < userpass_buf_len;) {
3151 3152 3153 3154 3155 3156 3157
        uint32_t oct_a = n < userpass_buf_len ?
            (unsigned char) userpass_buf[n++]:0;
        uint32_t oct_b = n < userpass_buf_len ?
            (unsigned char) userpass_buf[n++]:0;
        uint32_t oct_c = n < userpass_buf_len ?
            (unsigned char) userpass_buf[n++]:0;
        uint32_t triple = (oct_a << 0x10) + (oct_b << 0x08) + oct_c;
3158

3159 3160 3161 3162
        base64_buf[m++] = base64[(triple >> 3* 6) & 0x3f];
        base64_buf[m++] = base64[(triple >> 2* 6) & 0x3f];
        base64_buf[m++] = base64[(triple >> 1* 6) & 0x3f];
        base64_buf[m++] = base64[(triple >> 0* 6) & 0x3f];
3163
    }
3164

3165
    for (int l = 0; l < mod_table[userpass_buf_len % 3]; l++)
3166
        base64_buf[encoded_len - 1 - l] = '=';
3167

3168 3169 3170
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
3171

3172 3173 3174 3175 3176 3177
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
3178
        ERROR_EXIT("too long request");
3179 3180
    }
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
3181

3182 3183 3184
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
3185
#ifdef WINDOWS
3186
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
3187
#else
3188
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
3189
#endif
3190
        if (bytes < 0)
3191
            ERROR_EXIT("writing message to socket");
3192 3193 3194 3195
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
3196

3197 3198 3199 3200
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
3201
#ifdef WINDOWS
3202
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
3203
#else
3204
        bytes = read(sockfd, response_buf + received, resp_len - received);
3205
#endif
3206 3207
        if (bytes < 0) {
            free(request_buf);
3208
            ERROR_EXIT("reading response from socket");
3209 3210 3211 3212 3213
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
3214

3215 3216
    if (received == resp_len) {
        free(request_buf);
3217
        ERROR_EXIT("storing complete response from socket");
3218
    }
H
Haojun Liao 已提交
3219

3220 3221
    response_buf[RESP_BUF_LEN - 1] = '\0';
    printf("Response:\n%s\n", response_buf);
H
Haojun Liao 已提交
3222

3223
    if (strlen(pThreadInfo->filePath) > 0) {
3224
        appendResultBufToFile(response_buf, pThreadInfo);
3225 3226
    }

3227
    free(request_buf);
3228
#ifdef WINDOWS
3229
    closesocket(sockfd);
3230 3231
    WSACleanup();
#else
3232
    close(sockfd);
3233
#endif
3234

3235
    return 0;
3236 3237
}

3238
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
3239 3240
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
3241
        errorPrint2("%s() LN%d, calloc failed! size:%d\n",
3242 3243 3244
                __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
        return NULL;
    }
3245

3246 3247 3248
    int    dataLen = 0;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
            "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
3249

3250
    return dataBuf;
3251 3252
}

3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271
static char *generateBinaryNCharTagValues(int64_t tableSeq, uint32_t len)
{
    char* buf = (char*)calloc(len, 1);
    if (NULL == buf) {
        printf("calloc failed! size:%d\n", len);
        return NULL;
    }

    if (tableSeq % 2) {
        tstrncpy(buf, "beijing", len);
    } else {
        tstrncpy(buf, "shanghai", len);
    }
    //rand_string(buf, stbInfo->tags[i].dataLen);

    return buf;
}

static char* generateTagValuesForStb(SSuperTable* stbInfo, int64_t tableSeq) {
3272 3273 3274
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
        printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1);
3275
        return NULL;
3276
    }
3277

3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290
    int    dataLen = 0;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "(");
    for (int i = 0; i < stbInfo->tagCount; i++) {
        if ((0 == strncasecmp(stbInfo->tags[i].dataType,
                        "binary", strlen("binary")))
                || (0 == strncasecmp(stbInfo->tags[i].dataType,
                        "nchar", strlen("nchar")))) {
            if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
                printf("binary or nchar length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                tmfree(dataBuf);
                return NULL;
            }
3291

3292 3293
            int32_t tagBufLen = stbInfo->tags[i].dataLen + 1;
            char *buf = generateBinaryNCharTagValues(tableSeq, tagBufLen);
3294 3295 3296 3297 3298
            if (NULL == buf) {
                tmfree(dataBuf);
                return NULL;
            }
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3299
                    "\'%s\',", buf);
3300 3301 3302
            tmfree(buf);
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "int", strlen("int"))) {
3303 3304 3305
            if ((g_args.demo_mode) && (i == 0)) {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
3306
                        "%"PRId64",", (tableSeq % 10) + 1);
3307 3308 3309
            } else {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
3310
                        "%"PRId64",", tableSeq);
3311
            }
3312 3313 3314
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bigint", strlen("bigint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3315
                    "%"PRId64",", rand_bigint());
3316 3317 3318
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "float", strlen("float"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3319
                    "%f,", rand_float());
3320 3321 3322
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "double", strlen("double"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3323
                    "%f,", rand_double());
3324 3325 3326
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "smallint", strlen("smallint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3327
                    "%d,", rand_smallint());
3328 3329 3330
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "tinyint", strlen("tinyint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3331
                    "%d,", rand_tinyint());
3332 3333 3334
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bool", strlen("bool"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3335
                    "%d,", rand_bool());
3336 3337 3338
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "timestamp", strlen("timestamp"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3339
                    "%"PRId64",", rand_bigint());
3340
        }  else {
3341
            errorPrint2("No support data type: %s\n", stbInfo->tags[i].dataType);
3342 3343 3344
            tmfree(dataBuf);
            return NULL;
        }
3345
    }
3346

3347
    dataLen -= 1;
3348 3349
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
    return dataBuf;
3350 3351
}

3352
static int calcRowLen(SSuperTable*  superTbls) {
3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
    int colIndex;
    int  lenOfOneRow = 0;

    for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
        char* dataType = superTbls->columns[colIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
            lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
            lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
3364
            lenOfOneRow += INT_BUFF_LEN;
3365
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3366
            lenOfOneRow += BIGINT_BUFF_LEN;
3367
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3368
            lenOfOneRow += SMALLINT_BUFF_LEN;
3369
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3370
            lenOfOneRow += TINYINT_BUFF_LEN;
3371
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3372
            lenOfOneRow += BOOL_BUFF_LEN;
3373
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
3374
            lenOfOneRow += FLOAT_BUFF_LEN;
3375
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
3376
            lenOfOneRow += DOUBLE_BUFF_LEN;
3377
        }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
3378
            lenOfOneRow += TIMESTAMP_BUFF_LEN;
3379
        } else {
3380
            errorPrint2("get error data type : %s\n", dataType);
3381
            exit(EXIT_FAILURE);
3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396
        }
    }

    superTbls->lenOfOneRow = lenOfOneRow + 20; // timestamp

    int tagIndex;
    int lenOfTagOfOneRow = 0;
    for (tagIndex = 0; tagIndex < superTbls->tagCount; tagIndex++) {
        char* dataType = superTbls->tags[tagIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
3397
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + INT_BUFF_LEN;
3398
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3399
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + BIGINT_BUFF_LEN;
3400
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3401
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + SMALLINT_BUFF_LEN;
3402
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3403
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + TINYINT_BUFF_LEN;
3404
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3405
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + BOOL_BUFF_LEN;
3406
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
3407
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + FLOAT_BUFF_LEN;
3408
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
3409
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + DOUBLE_BUFF_LEN;
3410
        } else {
3411
            errorPrint2("get error tag type : %s\n", dataType);
3412
            exit(EXIT_FAILURE);
3413
        }
3414 3415
    }

3416
    superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
3417

3418
    return 0;
3419 3420 3421
}


3422
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
3423
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
3424
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
3425

3426
    char command[1024] = "\0";
3427
    char limitBuf[100] = "\0";
3428

3429 3430
    TAOS_RES * res;
    TAOS_ROW row = NULL;
3431

3432
    char* childTblName = *childTblNameOfSuperTbl;
3433

3434 3435 3436 3437
    if (offset >= 0) {
        snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
                limit, offset);
    }
3438

3439
    //get all child table name use cmd: select tbname from superTblName;
3440
    snprintf(command, 1024, "select tbname from %s.%s %s",
3441
            dbName, sTblName, limitBuf);
3442

3443 3444 3445 3446
    res = taos_query(taos, command);
    int32_t code = taos_errno(res);
    if (code != 0) {
        taos_free_result(res);
3447
        taos_close(taos);
3448
        errorPrint2("%s() LN%d, failed to run command %s\n",
3449
                __func__, __LINE__, command);
3450
        exit(EXIT_FAILURE);
3451
    }
3452

3453 3454 3455 3456 3457 3458 3459
    int64_t childTblCount = (limit < 0)?10000:limit;
    int64_t count = 0;
    if (childTblName == NULL) {
        childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
        if (NULL ==  childTblName) {
            taos_free_result(res);
            taos_close(taos);
3460
            errorPrint2("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
3461
            exit(EXIT_FAILURE);
3462
        }
3463 3464
    }

3465 3466 3467 3468 3469
    char* pTblName = childTblName;
    while((row = taos_fetch_row(res)) != NULL) {
        int32_t* len = taos_fetch_lengths(res);

        if (0 == strlen((char *)row[0])) {
3470
            errorPrint2("%s() LN%d, No.%"PRId64" table return empty name\n",
3471
                    __func__, __LINE__, count);
3472
            exit(EXIT_FAILURE);
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
        }

        tstrncpy(pTblName, (char *)row[0], len[0]+1);
        //printf("==== sub table name: %s\n", pTblName);
        count++;
        if (count >= childTblCount - 1) {
            char *tmp = realloc(childTblName,
                    (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
            if (tmp != NULL) {
                childTblName = tmp;
                childTblCount = (int)(childTblCount*1.5);
                memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
                        (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
            } else {
                // exit, if allocate more memory failed
                tmfree(childTblName);
                taos_free_result(res);
                taos_close(taos);
3491
                errorPrint2("%s() LN%d, realloc fail for save child table name of %s.%s\n",
3492 3493
                        __func__, __LINE__, dbName, sTblName);
                exit(EXIT_FAILURE);
3494 3495 3496
            }
        }
        pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
3497
    }
3498

3499 3500
    *childTblCountOfSuperTbl = count;
    *childTblNameOfSuperTbl  = childTblName;
3501

3502 3503
    taos_free_result(res);
    return 0;
3504 3505
}

3506
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
3507
        char* sTblName, char** childTblNameOfSuperTbl,
3508
        int64_t* childTblCountOfSuperTbl) {
3509

3510 3511
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
3512
            -1, 0);
3513 3514
}

3515
static int getSuperTableFromServer(TAOS * taos, char* dbName,
3516
        SSuperTable*  superTbls) {
3517

3518
    char command[1024] = "\0";
3519 3520 3521 3522 3523
    TAOS_RES * res;
    TAOS_ROW row = NULL;
    int count = 0;

    //get schema use cmd: describe superTblName;
3524
    snprintf(command, 1024, "describe %s.%s", dbName, superTbls->sTblName);
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547
    res = taos_query(taos, command);
    int32_t code = taos_errno(res);
    if (code != 0) {
        printf("failed to run command %s\n", command);
        taos_free_result(res);
        return -1;
    }

    int tagIndex = 0;
    int columnIndex = 0;
    TAOS_FIELD *fields = taos_fetch_fields(res);
    while((row = taos_fetch_row(res)) != NULL) {
        if (0 == count) {
            count++;
            continue;
        }

        if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
            tstrncpy(superTbls->tags[tagIndex].field,
                    (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
                    fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
            tstrncpy(superTbls->tags[tagIndex].dataType,
                    (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
3548 3549
                    min(DATATYPE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes) + 1);
3550 3551 3552 3553
            superTbls->tags[tagIndex].dataLen =
                *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
            tstrncpy(superTbls->tags[tagIndex].note,
                    (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
3554 3555
                    min(NOTE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes) + 1);
3556 3557 3558 3559 3560 3561 3562
            tagIndex++;
        } else {
            tstrncpy(superTbls->columns[columnIndex].field,
                    (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
                    fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
            tstrncpy(superTbls->columns[columnIndex].dataType,
                    (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
3563 3564
                    min(DATATYPE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes) + 1);
3565 3566 3567 3568
            superTbls->columns[columnIndex].dataLen =
                *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
            tstrncpy(superTbls->columns[columnIndex].note,
                    (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
3569 3570
                    min(NOTE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes) + 1);
3571 3572 3573 3574 3575 3576 3577
            columnIndex++;
        }
        count++;
    }

    superTbls->columnCount = columnIndex;
    superTbls->tagCount    = tagIndex;
3578
    taos_free_result(res);
3579

3580 3581 3582 3583
    calcRowLen(superTbls);

    /*
       if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
3584
    //get all child table name use cmd: select tbname from superTblName;
3585 3586 3587
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
3588
    errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
3589
    return -1;
3590
    }
3591
    getAllChildNameOfSuperTable(taos, dbName,
3592 3593 3594 3595 3596 3597
    superTbls->sTblName,
    &superTbls->childTblName,
    &superTbls->childTblCount);
    }
    */
    return 0;
3598 3599
}

H
Haojun Liao 已提交
3600
static int createSuperTable(
3601 3602
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
3603

3604 3605
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);
3606

3607
    char cols[COL_BUFFER_LEN] = "\0";
3608 3609
    int colIndex;
    int len = 0;
3610

3611
    int  lenOfOneRow = 0;
3612

3613
    if (superTbl->columnCount == 0) {
3614
        errorPrint2("%s() LN%d, super table column count is %d\n",
3615
                __func__, __LINE__, superTbl->columnCount);
3616
        free(command);
3617 3618
        return -1;
    }
3619

3620 3621 3622 3623
    for (colIndex = 0; colIndex < superTbl->columnCount; colIndex++) {
        char* dataType = superTbl->columns[colIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
3624
            len += snprintf(cols + len, COL_BUFFER_LEN - len,
3625
                    ",C%d %s(%d)", colIndex, "BINARY",
3626 3627 3628
                    superTbl->columns[colIndex].dataLen);
            lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
3629
            len += snprintf(cols + len, COL_BUFFER_LEN - len,
3630
                    ",C%d %s(%d)", colIndex, "NCHAR",
3631 3632 3633 3634
                    superTbl->columns[colIndex].dataLen);
            lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
            if ((g_args.demo_mode) && (colIndex == 1)) {
3635 3636
                len += snprintf(cols + len, COL_BUFFER_LEN - len,
                        ", VOLTAGE INT");
3637
            } else {
3638
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "INT");
3639
            }
3640
            lenOfOneRow += INT_BUFF_LEN;
3641
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3642
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
3643
                    colIndex, "BIGINT");
3644
            lenOfOneRow += BIGINT_BUFF_LEN;
3645
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3646
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
3647
                    colIndex, "SMALLINT");
3648
            lenOfOneRow += SMALLINT_BUFF_LEN;
3649
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3650
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "TINYINT");
3651
            lenOfOneRow += TINYINT_BUFF_LEN;
3652
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3653
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "BOOL");
3654
            lenOfOneRow += BOOL_BUFF_LEN;
3655 3656 3657
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
            if (g_args.demo_mode) {
                if (colIndex == 0) {
3658
                    len += snprintf(cols + len, COL_BUFFER_LEN - len, ", CURRENT FLOAT");
3659
                } else if (colIndex == 2) {
3660
                    len += snprintf(cols + len, COL_BUFFER_LEN - len, ", PHASE FLOAT");
3661 3662
                }
            } else {
3663
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "FLOAT");
3664
            }
3665

3666
            lenOfOneRow += FLOAT_BUFF_LEN;
3667
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
3668
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
3669
                    colIndex, "DOUBLE");
3670
            lenOfOneRow += DOUBLE_BUFF_LEN;
3671
        }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
3672
            len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
3673
                    colIndex, "TIMESTAMP");
3674
            lenOfOneRow += TIMESTAMP_BUFF_LEN;
3675 3676
        } else {
            taos_close(taos);
3677
            free(command);
3678
            errorPrint2("%s() LN%d, config error data type : %s\n",
3679
                    __func__, __LINE__, dataType);
3680
            exit(EXIT_FAILURE);
3681
        }
3682 3683
    }

3684
    superTbl->lenOfOneRow = lenOfOneRow + 20; // timestamp
3685

3686 3687 3688 3689
    // save for creating child table
    superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
    if (NULL == superTbl->colsOfCreateChildTable) {
        taos_close(taos);
3690
        free(command);
3691
        errorPrint2("%s() LN%d, Failed when calloc, size:%d",
3692 3693
                __func__, __LINE__, len+1);
        exit(EXIT_FAILURE);
3694
    }
3695

3696 3697 3698
    snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
    verbosePrint("%s() LN%d: %s\n",
            __func__, __LINE__, superTbl->colsOfCreateChildTable);
3699

3700
    if (superTbl->tagCount == 0) {
3701
        errorPrint2("%s() LN%d, super table tag count is %d\n",
3702
                __func__, __LINE__, superTbl->tagCount);
3703
        free(command);
3704 3705
        return -1;
    }
3706

3707
    char tags[TSDB_MAX_TAGS_LEN] = "\0";
3708 3709
    int tagIndex;
    len = 0;
3710

3711
    int lenOfTagOfOneRow = 0;
3712
    len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len, "(");
3713 3714 3715 3716
    for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
        char* dataType = superTbl->tags[tagIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
3717
            if ((g_args.demo_mode) && (tagIndex == 1)) {
3718
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3719
                        "location BINARY(%d),",
3720 3721
                        superTbl->tags[tagIndex].dataLen);
            } else {
3722
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3723
                        "T%d %s(%d),", tagIndex, "BINARY",
3724
                        superTbl->tags[tagIndex].dataLen);
3725
            }
3726 3727
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
3728
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3729
                    "T%d %s(%d),", tagIndex,
3730 3731 3732
                    "NCHAR", superTbl->tags[tagIndex].dataLen);
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
3733
            if ((g_args.demo_mode) && (tagIndex == 0)) {
3734 3735
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
                        "groupId INT, ");
3736
            } else {
3737
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3738
                        "T%d %s,", tagIndex, "INT");
3739
            }
3740
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + INT_BUFF_LEN;
3741
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3742
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3743
                    "T%d %s,", tagIndex, "BIGINT");
3744
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + BIGINT_BUFF_LEN;
3745
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3746
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3747
                    "T%d %s,", tagIndex, "SMALLINT");
3748
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + SMALLINT_BUFF_LEN;
3749
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3750
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3751
                    "T%d %s,", tagIndex, "TINYINT");
3752
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + TINYINT_BUFF_LEN;
3753
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3754
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3755
                    "T%d %s,", tagIndex, "BOOL");
3756
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + BOOL_BUFF_LEN;
3757
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
3758
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3759
                    "T%d %s,", tagIndex, "FLOAT");
3760
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + FLOAT_BUFF_LEN;
3761
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
3762
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3763
                    "T%d %s,", tagIndex, "DOUBLE");
3764
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + DOUBLE_BUFF_LEN;
3765 3766
        } else {
            taos_close(taos);
3767
            free(command);
3768
            errorPrint2("%s() LN%d, config error tag type : %s\n",
3769
                    __func__, __LINE__, dataType);
3770
            exit(EXIT_FAILURE);
3771
        }
3772
    }
3773

3774
    len -= 1;
3775
    len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len, ")");
3776

3777
    superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;
3778

3779 3780 3781 3782
    snprintf(command, BUFFER_SIZE,
            "create table if not exists %s.%s (ts timestamp%s) tags %s",
            dbName, superTbl->sTblName, cols, tags);
    if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
3783
        errorPrint2("create supertable %s failed!\n\n",
3784
                superTbl->sTblName);
3785
        free(command);
3786 3787
        return -1;
    }
3788

3789
    debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
3790
    free(command);
3791
    return 0;
3792 3793
}

3794
int createDatabasesAndStables(char *command) {
3795 3796 3797 3798
    TAOS * taos = NULL;
    int    ret = 0;
    taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port);
    if (taos == NULL) {
3799
        errorPrint2("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
3800
        return -1;
3801
    }
3802

3803 3804 3805 3806 3807 3808 3809
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        if (g_Dbs.db[i].drop) {
            sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
            if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
                taos_close(taos);
                return -1;
            }
3810

3811 3812
            int dataLen = 0;
            dataLen += snprintf(command + dataLen,
3813 3814
                    BUFFER_SIZE - dataLen, "create database if not exists %s",
                    g_Dbs.db[i].dbName);
3815

3816 3817
            if (g_Dbs.db[i].dbCfg.blocks > 0) {
                dataLen += snprintf(command + dataLen,
3818 3819
                        BUFFER_SIZE - dataLen, " blocks %d",
                        g_Dbs.db[i].dbCfg.blocks);
3820 3821 3822
            }
            if (g_Dbs.db[i].dbCfg.cache > 0) {
                dataLen += snprintf(command + dataLen,
3823 3824
                        BUFFER_SIZE - dataLen, " cache %d",
                        g_Dbs.db[i].dbCfg.cache);
3825 3826 3827
            }
            if (g_Dbs.db[i].dbCfg.days > 0) {
                dataLen += snprintf(command + dataLen,
3828 3829
                        BUFFER_SIZE - dataLen, " days %d",
                        g_Dbs.db[i].dbCfg.days);
3830 3831 3832
            }
            if (g_Dbs.db[i].dbCfg.keep > 0) {
                dataLen += snprintf(command + dataLen,
3833 3834
                        BUFFER_SIZE - dataLen, " keep %d",
                        g_Dbs.db[i].dbCfg.keep);
3835 3836 3837
            }
            if (g_Dbs.db[i].dbCfg.quorum > 1) {
                dataLen += snprintf(command + dataLen,
3838 3839
                        BUFFER_SIZE - dataLen, " quorum %d",
                        g_Dbs.db[i].dbCfg.quorum);
3840 3841 3842
            }
            if (g_Dbs.db[i].dbCfg.replica > 0) {
                dataLen += snprintf(command + dataLen,
3843 3844
                        BUFFER_SIZE - dataLen, " replica %d",
                        g_Dbs.db[i].dbCfg.replica);
3845 3846 3847
            }
            if (g_Dbs.db[i].dbCfg.update > 0) {
                dataLen += snprintf(command + dataLen,
3848 3849
                        BUFFER_SIZE - dataLen, " update %d",
                        g_Dbs.db[i].dbCfg.update);
3850 3851 3852 3853 3854 3855 3856
            }
            //if (g_Dbs.db[i].dbCfg.maxtablesPerVnode > 0) {
            //  dataLen += snprintf(command + dataLen,
            //  BUFFER_SIZE - dataLen, "tables %d ", g_Dbs.db[i].dbCfg.maxtablesPerVnode);
            //}
            if (g_Dbs.db[i].dbCfg.minRows > 0) {
                dataLen += snprintf(command + dataLen,
3857 3858
                        BUFFER_SIZE - dataLen, " minrows %d",
                        g_Dbs.db[i].dbCfg.minRows);
3859 3860 3861
            }
            if (g_Dbs.db[i].dbCfg.maxRows > 0) {
                dataLen += snprintf(command + dataLen,
3862 3863
                        BUFFER_SIZE - dataLen, " maxrows %d",
                        g_Dbs.db[i].dbCfg.maxRows);
3864 3865 3866
            }
            if (g_Dbs.db[i].dbCfg.comp > 0) {
                dataLen += snprintf(command + dataLen,
3867 3868
                        BUFFER_SIZE - dataLen, " comp %d",
                        g_Dbs.db[i].dbCfg.comp);
3869 3870 3871
            }
            if (g_Dbs.db[i].dbCfg.walLevel > 0) {
                dataLen += snprintf(command + dataLen,
3872 3873
                        BUFFER_SIZE - dataLen, " wal %d",
                        g_Dbs.db[i].dbCfg.walLevel);
3874 3875 3876
            }
            if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
                dataLen += snprintf(command + dataLen,
3877 3878
                        BUFFER_SIZE - dataLen, " cachelast %d",
                        g_Dbs.db[i].dbCfg.cacheLast);
3879 3880 3881 3882 3883
            }
            if (g_Dbs.db[i].dbCfg.fsync > 0) {
                dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                        " fsync %d", g_Dbs.db[i].dbCfg.fsync);
            }
3884
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
3885
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
3886
                            "ns", 2))
3887
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
3888
                            "us", 2))) {
3889 3890 3891
                dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                        " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
            }
3892

3893 3894
            if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
                taos_close(taos);
3895
                errorPrint("\ncreate database %s failed!\n\n",
3896
                        g_Dbs.db[i].dbName);
3897 3898 3899 3900
                return -1;
            }
            printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName);
        }
3901

3902 3903
        debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
                __func__, __LINE__, g_Dbs.db[i].superTblCount);
3904

3905
        int validStbCount = 0;
3906

3907 3908 3909 3910
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
                    g_Dbs.db[i].superTbls[j].sTblName);
            ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);
3911

3912 3913 3914
            if ((ret != 0) || (g_Dbs.db[i].drop)) {
                ret = createSuperTable(taos, g_Dbs.db[i].dbName,
                        &g_Dbs.db[i].superTbls[j]);
3915

3916 3917 3918 3919 3920
                if (0 != ret) {
                    errorPrint("create super table %"PRIu64" failed!\n\n", j);
                    continue;
                }
            }
3921

3922 3923 3924
            ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
                    &g_Dbs.db[i].superTbls[j]);
            if (0 != ret) {
3925
                errorPrint2("\nget super table %s.%s info failed!\n\n",
3926 3927 3928
                        g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
                continue;
            }
3929

3930 3931
            validStbCount ++;
        }
3932

3933 3934 3935 3936 3937
        g_Dbs.db[i].superTblCount = validStbCount;
    }

    taos_close(taos);
    return 0;
3938 3939
}

3940 3941
static void* createTable(void *sarg)
{
3942
    threadInfo *pThreadInfo = (threadInfo *)sarg;
3943
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
3944

3945 3946
    setThreadName("createTable");

3947
    uint64_t  lastPrintTime = taosGetTimestampMs();
3948

3949
    int buff_len = BUFFER_SIZE;
3950

3951 3952
    pThreadInfo->buffer = calloc(buff_len, 1);
    if (pThreadInfo->buffer == NULL) {
3953
        errorPrint2("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
3954
        exit(EXIT_FAILURE);
3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971
    }

    int len = 0;
    int batchNum = 0;

    verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
            __func__, __LINE__,
            pThreadInfo->start_table_from, pThreadInfo->end_table_to);

    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
        if (0 == g_Dbs.use_metric) {
            snprintf(pThreadInfo->buffer, buff_len,
                    "create table if not exists %s.%s%"PRIu64" %s;",
                    pThreadInfo->db_name,
                    g_args.tb_prefix, i,
                    pThreadInfo->cols);
3972
            batchNum ++;
3973
        } else {
3974 3975
            if (stbInfo == NULL) {
                free(pThreadInfo->buffer);
3976
                errorPrint2("%s() LN%d, use metric, but super table info is NULL\n",
3977
                        __func__, __LINE__);
3978
                exit(EXIT_FAILURE);
3979 3980 3981 3982 3983 3984 3985
            } else {
                if (0 == len) {
                    batchNum = 0;
                    memset(pThreadInfo->buffer, 0, buff_len);
                    len += snprintf(pThreadInfo->buffer + len,
                            buff_len - len, "create table ");
                }
3986

3987
                char* tagsValBuf = NULL;
3988 3989
                if (0 == stbInfo->tagSource) {
                    tagsValBuf = generateTagValuesForStb(stbInfo, i);
3990
                } else {
3991 3992 3993 3994
                    if (0 == stbInfo->tagSampleCount) {
                        free(pThreadInfo->buffer);
                        ERROR_EXIT("use sample file for tag, but has no content!\n");
                    }
3995
                    tagsValBuf = getTagValueFromTagSample(
3996 3997
                            stbInfo,
                            i % stbInfo->tagSampleCount);
3998
                }
3999

4000 4001
                if (NULL == tagsValBuf) {
                    free(pThreadInfo->buffer);
4002
                    ERROR_EXIT("use metric, but tag buffer is NULL\n");
4003 4004 4005 4006
                }
                len += snprintf(pThreadInfo->buffer + len,
                        buff_len - len,
                        "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
4007
                        pThreadInfo->db_name, stbInfo->childTblPrefix,
4008
                        i, pThreadInfo->db_name,
4009
                        stbInfo->sTblName, tagsValBuf);
4010 4011
                free(tagsValBuf);
                batchNum++;
4012
                if ((batchNum < stbInfo->batchCreateTableNum)
4013
                        && ((buff_len - len)
4014
                            >= (stbInfo->lenOfTagOfOneRow + 256))) {
4015 4016 4017
                    continue;
                }
            }
4018
        }
4019

4020
        len = 0;
S
Shengliang Guan 已提交
4021

4022
        if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
4023
                    NO_INSERT_TYPE, false)) {
4024
            errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
4025 4026 4027
            free(pThreadInfo->buffer);
            return NULL;
        }
4028
        pThreadInfo->tables_created += batchNum;
4029

4030
        uint64_t currentPrintTime = taosGetTimestampMs();
4031 4032 4033 4034 4035
        if (currentPrintTime - lastPrintTime > 30*1000) {
            printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
                    pThreadInfo->threadID, pThreadInfo->start_table_from, i);
            lastPrintTime = currentPrintTime;
        }
4036
    }
4037

4038 4039 4040
    if (0 != len) {
        if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                    NO_INSERT_TYPE, false)) {
4041
            errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
4042
        }
4043
    }
4044

4045 4046
    free(pThreadInfo->buffer);
    return NULL;
4047 4048
}

4049
static int startMultiThreadCreateChildTable(
4050
        char* cols, int threads, uint64_t tableFrom, int64_t ntables,
4051
        char* db_name, SSuperTable* stbInfo) {
4052

4053 4054
    pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
    threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
4055

4056
    if ((NULL == pids) || (NULL == infos)) {
4057
        ERROR_EXIT("createChildTable malloc failed\n");
4058
    }
4059

4060 4061 4062
    if (threads < 1) {
        threads = 1;
    }
4063

4064 4065 4066 4067
    int64_t a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
4068
    }
4069

4070 4071
    int64_t b = 0;
    b = ntables % threads;
4072

4073 4074 4075 4076
    for (int64_t i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
        pThreadInfo->threadID = i;
        tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
4077
        pThreadInfo->stbInfo = stbInfo;
4078 4079 4080 4081 4082 4083 4084 4085
        verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
        pThreadInfo->taos = taos_connect(
                g_Dbs.host,
                g_Dbs.user,
                g_Dbs.password,
                db_name,
                g_Dbs.port);
        if (pThreadInfo->taos == NULL) {
4086
            errorPrint2("%s() LN%d, Failed to connect to TDengine, reason:%s\n",
4087 4088 4089 4090 4091
                    __func__, __LINE__, taos_errstr(NULL));
            free(pids);
            free(infos);
            return -1;
        }
4092

4093 4094 4095 4096 4097 4098 4099
        pThreadInfo->start_table_from = tableFrom;
        pThreadInfo->ntables = i<b?a+1:a;
        pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
        tableFrom = pThreadInfo->end_table_to + 1;
        pThreadInfo->use_metric = true;
        pThreadInfo->cols = cols;
        pThreadInfo->minDelay = UINT64_MAX;
4100
        pThreadInfo->tables_created = 0;
4101 4102
        pthread_create(pids + i, NULL, createTable, pThreadInfo);
    }
4103

4104 4105 4106
    for (int i = 0; i < threads; i++) {
        pthread_join(pids[i], NULL);
    }
4107

4108 4109 4110
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
        taos_close(pThreadInfo->taos);
4111 4112

        g_actualChildTables += pThreadInfo->tables_created;
4113 4114 4115 4116 4117 4118
    }

    free(pids);
    free(infos);

    return 0;
4119 4120
}

4121
static void createChildTables() {
4122
    char tblColsBuf[TSDB_MAX_BYTES_PER_ROW];
4123
    int len;
4124

4125 4126 4127 4128 4129
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        if (g_Dbs.use_metric) {
            if (g_Dbs.db[i].superTblCount > 0) {
                // with super table
                for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4130 4131 4132 4133
                    if ((AUTO_CREATE_SUBTBL
                                == g_Dbs.db[i].superTbls[j].autoCreateTable)
                            || (TBL_ALREADY_EXISTS
                                == g_Dbs.db[i].superTbls[j].childTblExists)) {
4134 4135 4136
                        continue;
                    }
                    verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
4137
                            g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
4138 4139 4140 4141 4142 4143 4144
                    uint64_t startFrom = 0;

                    verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
                            __func__, __LINE__, g_totalChildTables, startFrom);

                    startMultiThreadCreateChildTable(
                            g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
4145
                            g_Dbs.threadCountForCreateTbl,
4146 4147 4148 4149 4150 4151 4152
                            startFrom,
                            g_Dbs.db[i].superTbls[j].childTblCount,
                            g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
                }
            }
        } else {
            // normal table
4153
            len = snprintf(tblColsBuf, TSDB_MAX_BYTES_PER_ROW, "(TS TIMESTAMP");
4154 4155 4156 4157
            for (int j = 0; j < g_args.num_of_CPR; j++) {
                if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0)
                        || (strncasecmp(g_args.datatype[j],
                                "NCHAR", strlen("NCHAR")) == 0)) {
4158
                    snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len,
4159
                            ",C%d %s(%d)", j, g_args.datatype[j], g_args.binwidth);
4160
                } else {
4161 4162
                    snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len,
                            ",C%d %s", j, g_args.datatype[j]);
4163 4164 4165
                }
                len = strlen(tblColsBuf);
            }
4166

4167
            snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len, ")");
4168 4169 4170 4171 4172 4173

            verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
                    __func__, __LINE__,
                    g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
            startMultiThreadCreateChildTable(
                    tblColsBuf,
4174
                    g_Dbs.threadCountForCreateTbl,
4175 4176 4177 4178
                    0,
                    g_args.num_of_tables,
                    g_Dbs.db[i].dbName,
                    NULL);
4179
        }
4180
    }
4181 4182 4183
}

/*
4184 4185
   Read 10000 lines at most. If more than 10000 lines, continue to read after using
   */
4186
static int readTagFromCsvFileToMem(SSuperTable  * stbInfo) {
4187 4188 4189
    size_t  n = 0;
    ssize_t readLen = 0;
    char *  line = NULL;
4190

4191
    FILE *fp = fopen(stbInfo->tagsFile, "r");
4192 4193
    if (fp == NULL) {
        printf("Failed to open tags file: %s, reason:%s\n",
4194
                stbInfo->tagsFile, strerror(errno));
4195
        return -1;
4196 4197
    }

4198 4199 4200
    if (stbInfo->tagDataBuf) {
        free(stbInfo->tagDataBuf);
        stbInfo->tagDataBuf = NULL;
4201 4202
    }

4203 4204
    int tagCount = 10000;
    int count = 0;
4205
    char* tagDataBuf = calloc(1, stbInfo->lenOfTagOfOneRow * tagCount);
4206 4207
    if (tagDataBuf == NULL) {
        printf("Failed to calloc, reason:%s\n", strerror(errno));
4208 4209 4210 4211
        fclose(fp);
        return -1;
    }

4212 4213 4214 4215 4216 4217 4218 4219 4220
    while((readLen = tgetline(&line, &n, fp)) != -1) {
        if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
            line[--readLen] = 0;
        }

        if (readLen == 0) {
            continue;
        }

4221
        memcpy(tagDataBuf + count * stbInfo->lenOfTagOfOneRow, line, readLen);
4222 4223 4224 4225
        count++;

        if (count >= tagCount - 1) {
            char *tmp = realloc(tagDataBuf,
4226
                    (size_t)tagCount*1.5*stbInfo->lenOfTagOfOneRow);
4227 4228 4229
            if (tmp != NULL) {
                tagDataBuf = tmp;
                tagCount = (int)(tagCount*1.5);
4230 4231
                memset(tagDataBuf + count*stbInfo->lenOfTagOfOneRow,
                        0, (size_t)((tagCount-count)*stbInfo->lenOfTagOfOneRow));
4232 4233
            } else {
                // exit, if allocate more memory failed
4234
                printf("realloc fail for save tag val from %s\n", stbInfo->tagsFile);
4235 4236 4237 4238 4239 4240 4241
                tmfree(tagDataBuf);
                free(line);
                fclose(fp);
                return -1;
            }
        }
    }
4242

4243 4244
    stbInfo->tagDataBuf = tagDataBuf;
    stbInfo->tagSampleCount = count;
4245 4246 4247 4248

    free(line);
    fclose(fp);
    return 0;
4249 4250 4251
}

/*
4252 4253
   Read 10000 lines at most. If more than 10000 lines, continue to read after using
   */
4254
static int readSampleFromCsvFileToMem(
4255
        SSuperTable* stbInfo) {
4256 4257 4258 4259 4260
    size_t  n = 0;
    ssize_t readLen = 0;
    char *  line = NULL;
    int getRows = 0;

4261
    FILE*  fp = fopen(stbInfo->sampleFile, "r");
4262
    if (fp == NULL) {
4263
        errorPrint("Failed to open sample file: %s, reason:%s\n",
4264
                stbInfo->sampleFile, strerror(errno));
4265 4266
        return -1;
    }
4267

4268 4269 4270
    assert(stbInfo->sampleDataBuf);
    memset(stbInfo->sampleDataBuf, 0,
            MAX_SAMPLES_ONCE_FROM_FILE * stbInfo->lenOfOneRow);
4271 4272 4273 4274
    while(1) {
        readLen = tgetline(&line, &n, fp);
        if (-1 == readLen) {
            if(0 != fseek(fp, 0, SEEK_SET)) {
4275
                errorPrint("Failed to fseek file: %s, reason:%s\n",
4276
                        stbInfo->sampleFile, strerror(errno));
4277 4278 4279 4280 4281
                fclose(fp);
                return -1;
            }
            continue;
        }
4282

4283 4284 4285
        if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
            line[--readLen] = 0;
        }
4286

4287 4288 4289
        if (readLen == 0) {
            continue;
        }
4290

4291
        if (readLen > stbInfo->lenOfOneRow) {
4292
            printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
4293
                    (int32_t)readLen, stbInfo->lenOfOneRow);
4294 4295
            continue;
        }
4296

4297
        memcpy(stbInfo->sampleDataBuf + getRows * stbInfo->lenOfOneRow,
4298 4299 4300 4301 4302 4303
                line, readLen);
        getRows++;

        if (getRows == MAX_SAMPLES_ONCE_FROM_FILE) {
            break;
        }
4304 4305
    }

4306 4307 4308
    fclose(fp);
    tmfree(line);
    return 0;
4309 4310
}

4311
static bool getColumnAndTagTypeFromInsertJsonFile(
4312
        cJSON* stbInfo, SSuperTable* superTbls) {
4313 4314 4315 4316 4317
    bool  ret = false;

    // columns
    cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
    if (columns && columns->type != cJSON_Array) {
4318
        errorPrint("%s", "failed to read json, columns not found\n");
4319 4320 4321 4322 4323 4324
        goto PARSE_OVER;
    } else if (NULL == columns) {
        superTbls->columnCount = 0;
        superTbls->tagCount    = 0;
        return true;
    }
4325

4326 4327
    int columnSize = cJSON_GetArraySize(columns);
    if ((columnSize + 1/* ts */) > TSDB_MAX_COLUMNS) {
4328 4329
        errorPrint("failed to read json, column size overflow, max column size is %d\n",
                TSDB_MAX_COLUMNS);
4330 4331
        goto PARSE_OVER;
    }
4332

4333 4334 4335
    int count = 1;
    int index = 0;
    StrColumn    columnCase;
4336

4337 4338 4339 4340
    //superTbls->columnCount = columnSize;
    for (int k = 0; k < columnSize; ++k) {
        cJSON* column = cJSON_GetArrayItem(columns, k);
        if (column == NULL) continue;
4341

4342 4343 4344 4345 4346
        count = 1;
        cJSON* countObj = cJSON_GetObjectItem(column, "count");
        if (countObj && countObj->type == cJSON_Number) {
            count = countObj->valueint;
        } else if (countObj && countObj->type != cJSON_Number) {
4347
            errorPrint("%s", "failed to read json, column count not found\n");
4348 4349 4350 4351 4352 4353 4354 4355 4356 4357
            goto PARSE_OVER;
        } else {
            count = 1;
        }

        // column info
        memset(&columnCase, 0, sizeof(StrColumn));
        cJSON *dataType = cJSON_GetObjectItem(column, "type");
        if (!dataType || dataType->type != cJSON_String
                || dataType->valuestring == NULL) {
4358
            errorPrint("%s", "failed to read json, column type not found\n");
4359 4360
            goto PARSE_OVER;
        }
4361 4362 4363
        //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, DATATYPE_BUFF_LEN);
        tstrncpy(columnCase.dataType, dataType->valuestring,
                min(DATATYPE_BUFF_LEN, strlen(dataType->valuestring) + 1));
4364 4365 4366 4367 4368 4369 4370 4371 4372

        cJSON* dataLen = cJSON_GetObjectItem(column, "len");
        if (dataLen && dataLen->type == cJSON_Number) {
            columnCase.dataLen = dataLen->valueint;
        } else if (dataLen && dataLen->type != cJSON_Number) {
            debugPrint("%s() LN%d: failed to read json, column len not found\n",
                    __func__, __LINE__);
            goto PARSE_OVER;
        } else {
4373
            columnCase.dataLen = SMALL_BUFF_LEN;
4374 4375 4376 4377
        }

        for (int n = 0; n < count; ++n) {
            tstrncpy(superTbls->columns[index].dataType,
4378 4379
                    columnCase.dataType,
                    min(DATATYPE_BUFF_LEN, strlen(columnCase.dataType) + 1));
4380 4381 4382 4383 4384 4385
            superTbls->columns[index].dataLen = columnCase.dataLen;
            index++;
        }
    }

    if ((index + 1 /* ts */) > MAX_NUM_COLUMNS) {
4386 4387
        errorPrint("failed to read json, column size overflow, allowed max column size is %d\n",
                MAX_NUM_COLUMNS);
4388 4389 4390 4391
        goto PARSE_OVER;
    }

    superTbls->columnCount = index;
4392

4393
    count = 1;
4394 4395 4396 4397
    index = 0;
    // tags
    cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
    if (!tags || tags->type != cJSON_Array) {
4398
        errorPrint("%s", "failed to read json, tags not found\n");
4399 4400 4401 4402 4403
        goto PARSE_OVER;
    }

    int tagSize = cJSON_GetArraySize(tags);
    if (tagSize > TSDB_MAX_TAGS) {
4404 4405
        errorPrint("failed to read json, tags size overflow, max tag size is %d\n",
                TSDB_MAX_TAGS);
4406
        goto PARSE_OVER;
4407 4408
    }

4409 4410 4411 4412 4413 4414 4415 4416 4417 4418
    //superTbls->tagCount = tagSize;
    for (int k = 0; k < tagSize; ++k) {
        cJSON* tag = cJSON_GetArrayItem(tags, k);
        if (tag == NULL) continue;

        count = 1;
        cJSON* countObj = cJSON_GetObjectItem(tag, "count");
        if (countObj && countObj->type == cJSON_Number) {
            count = countObj->valueint;
        } else if (countObj && countObj->type != cJSON_Number) {
4419
            errorPrint("%s", "failed to read json, column count not found\n");
4420 4421 4422 4423 4424 4425 4426 4427 4428 4429
            goto PARSE_OVER;
        } else {
            count = 1;
        }

        // column info
        memset(&columnCase, 0, sizeof(StrColumn));
        cJSON *dataType = cJSON_GetObjectItem(tag, "type");
        if (!dataType || dataType->type != cJSON_String
                || dataType->valuestring == NULL) {
4430
            errorPrint("%s", "failed to read json, tag type not found\n");
4431 4432
            goto PARSE_OVER;
        }
4433 4434
        tstrncpy(columnCase.dataType, dataType->valuestring,
                min(DATATYPE_BUFF_LEN, strlen(dataType->valuestring) + 1));
4435 4436 4437 4438 4439

        cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
        if (dataLen && dataLen->type == cJSON_Number) {
            columnCase.dataLen = dataLen->valueint;
        } else if (dataLen && dataLen->type != cJSON_Number) {
4440
            errorPrint("%s", "failed to read json, column len not found\n");
4441 4442 4443 4444 4445 4446 4447
            goto PARSE_OVER;
        } else {
            columnCase.dataLen = 0;
        }

        for (int n = 0; n < count; ++n) {
            tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
4448
                    min(DATATYPE_BUFF_LEN, strlen(columnCase.dataType) + 1));
4449 4450 4451
            superTbls->tags[index].dataLen = columnCase.dataLen;
            index++;
        }
4452
    }
4453

4454
    if (index > TSDB_MAX_TAGS) {
4455 4456
        errorPrint("failed to read json, tags size overflow, allowed max tag count is %d\n",
                TSDB_MAX_TAGS);
4457 4458
        goto PARSE_OVER;
    }
4459

4460
    superTbls->tagCount = index;
4461

4462
    if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > TSDB_MAX_COLUMNS) {
4463 4464
        errorPrint("columns + tags is more than allowed max columns count: %d\n",
                TSDB_MAX_COLUMNS);
4465 4466 4467
        goto PARSE_OVER;
    }
    ret = true;
4468

4469
PARSE_OVER:
4470
    return ret;
4471 4472 4473
}

static bool getMetaFromInsertJsonFile(cJSON* root) {
4474
    bool  ret = false;
4475

4476 4477 4478
    cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
    if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
        tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4479
    }
4480

4481 4482 4483 4484 4485
    cJSON* host = cJSON_GetObjectItem(root, "host");
    if (host && host->type == cJSON_String && host->valuestring != NULL) {
        tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
    } else if (!host) {
        tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4486
    } else {
4487
        errorPrint("%s", "failed to read json, host not found\n");
4488
        goto PARSE_OVER;
4489 4490
    }

4491 4492 4493 4494 4495
    cJSON* port = cJSON_GetObjectItem(root, "port");
    if (port && port->type == cJSON_Number) {
        g_Dbs.port = port->valueint;
    } else if (!port) {
        g_Dbs.port = 6030;
4496
    }
4497

4498 4499 4500 4501 4502
    cJSON* user = cJSON_GetObjectItem(root, "user");
    if (user && user->type == cJSON_String && user->valuestring != NULL) {
        tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
    } else if (!user) {
        tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
4503 4504
    }

4505 4506
    cJSON* password = cJSON_GetObjectItem(root, "password");
    if (password && password->type == cJSON_String && password->valuestring != NULL) {
4507
        tstrncpy(g_Dbs.password, password->valuestring, SHELL_MAX_PASSWORD_LEN);
4508
    } else if (!password) {
4509
        tstrncpy(g_Dbs.password, "taosdata", SHELL_MAX_PASSWORD_LEN);
4510 4511
    }

4512 4513 4514 4515 4516
    cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
    if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
        tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
    } else if (!resultfile) {
        tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
4517 4518
    }

4519 4520 4521 4522 4523
    cJSON* threads = cJSON_GetObjectItem(root, "thread_count");
    if (threads && threads->type == cJSON_Number) {
        g_Dbs.threadCount = threads->valueint;
    } else if (!threads) {
        g_Dbs.threadCount = 1;
4524
    } else {
4525
        errorPrint("%s", "failed to read json, threads not found\n");
4526
        goto PARSE_OVER;
4527
    }
4528

4529 4530
    cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
    if (threads2 && threads2->type == cJSON_Number) {
4531
        g_Dbs.threadCountForCreateTbl = threads2->valueint;
4532
    } else if (!threads2) {
4533
        g_Dbs.threadCountForCreateTbl = 1;
4534
    } else {
4535
        errorPrint("%s", "failed to read json, threads2 not found\n");
4536
        goto PARSE_OVER;
4537
    }
4538

4539 4540 4541
    cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
    if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
        if (gInsertInterval->valueint <0) {
4542
            errorPrint("%s", "failed to read json, insert interval input mistake\n");
4543 4544 4545 4546 4547
            goto PARSE_OVER;
        }
        g_args.insert_interval = gInsertInterval->valueint;
    } else if (!gInsertInterval) {
        g_args.insert_interval = 0;
4548
    } else {
4549
        errorPrint("%s", "failed to read json, insert_interval input mistake\n");
4550
        goto PARSE_OVER;
4551
    }
4552

4553 4554 4555
    cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
    if (interlaceRows && interlaceRows->type == cJSON_Number) {
        if (interlaceRows->valueint < 0) {
4556
            errorPrint("%s", "failed to read json, interlace_rows input mistake\n");
4557
            goto PARSE_OVER;
4558

4559 4560 4561 4562
        }
        g_args.interlace_rows = interlaceRows->valueint;
    } else if (!interlaceRows) {
        g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
4563
    } else {
4564
        errorPrint("%s", "failed to read json, interlace_rows input mistake\n");
4565
        goto PARSE_OVER;
4566 4567
    }

4568 4569 4570 4571 4572 4573 4574 4575 4576 4577
    cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
    if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
        if (maxSqlLen->valueint < 0) {
            errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
                    __func__, __LINE__);
            goto PARSE_OVER;
        }
        g_args.max_sql_len = maxSqlLen->valueint;
    } else if (!maxSqlLen) {
        g_args.max_sql_len = (1024*1024);
4578
    } else {
4579 4580 4581
        errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
                __func__, __LINE__);
        goto PARSE_OVER;
4582 4583
    }

4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600
    cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
    if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
        if (numRecPerReq->valueint <= 0) {
            errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
                    __func__, __LINE__);
            goto PARSE_OVER;
        } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
            printf("NOTICE: number of records per request value %"PRIu64" > %d\n\n",
                    numRecPerReq->valueint, MAX_RECORDS_PER_REQ);
            printf("        number of records per request value will be set to %d\n\n",
                    MAX_RECORDS_PER_REQ);
            prompt();
            numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
        }
        g_args.num_of_RPR = numRecPerReq->valueint;
    } else if (!numRecPerReq) {
        g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
4601
    } else {
4602 4603 4604
        errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
                __func__, __LINE__);
        goto PARSE_OVER;
4605 4606
    }

4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619
    cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
    if (answerPrompt
            && answerPrompt->type == cJSON_String
            && answerPrompt->valuestring != NULL) {
        if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
            g_args.answer_yes = false;
        } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
            g_args.answer_yes = true;
        } else {
            g_args.answer_yes = false;
        }
    } else if (!answerPrompt) {
        g_args.answer_yes = true;   // default is no, mean answer_yes.
4620
    } else {
4621 4622
        errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
        goto PARSE_OVER;
4623 4624
    }

4625 4626 4627 4628 4629 4630 4631 4632
    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
        printf("NOTICE: interlace rows value %u > num_of_records_per_req %u\n\n",
                g_args.interlace_rows, g_args.num_of_RPR);
        printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
                g_args.num_of_RPR);
        prompt();
        g_args.interlace_rows = g_args.num_of_RPR;
4633 4634
    }

4635 4636
    cJSON* dbs = cJSON_GetObjectItem(root, "databases");
    if (!dbs || dbs->type != cJSON_Array) {
4637
        errorPrint("%s", "failed to read json, databases not found\n");
4638
        goto PARSE_OVER;
4639
    }
4640

4641 4642 4643
    int dbSize = cJSON_GetArraySize(dbs);
    if (dbSize > MAX_DB_COUNT) {
        errorPrint(
4644
                "failed to read json, databases size overflow, max database is %d\n",
4645 4646
                MAX_DB_COUNT);
        goto PARSE_OVER;
4647 4648
    }

4649 4650 4651 4652
    g_Dbs.dbCount = dbSize;
    for (int i = 0; i < dbSize; ++i) {
        cJSON* dbinfos = cJSON_GetArrayItem(dbs, i);
        if (dbinfos == NULL) continue;
4653

4654 4655 4656
        // dbinfo
        cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
        if (!dbinfo || dbinfo->type != cJSON_Object) {
4657
            errorPrint("%s", "failed to read json, dbinfo not found\n");
4658 4659
            goto PARSE_OVER;
        }
4660

4661 4662
        cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
        if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
4663
            errorPrint("%s", "failed to read json, db name not found\n");
4664 4665 4666
            goto PARSE_OVER;
        }
        tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, TSDB_DB_NAME_LEN);
4667

4668 4669 4670 4671 4672 4673 4674 4675 4676 4677
        cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
        if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
            if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
                g_Dbs.db[i].drop = true;
            } else {
                g_Dbs.db[i].drop = false;
            }
        } else if (!drop) {
            g_Dbs.db[i].drop = g_args.drop_database;
        } else {
4678
            errorPrint("%s", "failed to read json, drop input mistake\n");
4679 4680
            goto PARSE_OVER;
        }
4681

4682 4683 4684 4685
        cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
        if (precision && precision->type == cJSON_String
                && precision->valuestring != NULL) {
            tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
4686
                    SMALL_BUFF_LEN);
4687
        } else if (!precision) {
4688
            memset(g_Dbs.db[i].dbCfg.precision, 0, SMALL_BUFF_LEN);
4689
        } else {
4690
            errorPrint("%s", "failed to read json, precision not found\n");
4691 4692
            goto PARSE_OVER;
        }
4693

4694 4695 4696 4697 4698
        cJSON* update = cJSON_GetObjectItem(dbinfo, "update");
        if (update && update->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.update = update->valueint;
        } else if (!update) {
            g_Dbs.db[i].dbCfg.update = -1;
4699
        } else {
4700
            errorPrint("%s", "failed to read json, update not found\n");
4701
            goto PARSE_OVER;
4702
        }
4703

4704 4705 4706 4707 4708 4709
        cJSON* replica = cJSON_GetObjectItem(dbinfo, "replica");
        if (replica && replica->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.replica = replica->valueint;
        } else if (!replica) {
            g_Dbs.db[i].dbCfg.replica = -1;
        } else {
4710
            errorPrint("%s", "failed to read json, replica not found\n");
4711 4712
            goto PARSE_OVER;
        }
4713

4714 4715 4716 4717 4718 4719
        cJSON* keep = cJSON_GetObjectItem(dbinfo, "keep");
        if (keep && keep->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.keep = keep->valueint;
        } else if (!keep) {
            g_Dbs.db[i].dbCfg.keep = -1;
        } else {
4720
            errorPrint("%s", "failed to read json, keep not found\n");
4721 4722
            goto PARSE_OVER;
        }
4723

4724 4725 4726 4727 4728
        cJSON* days = cJSON_GetObjectItem(dbinfo, "days");
        if (days && days->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.days = days->valueint;
        } else if (!days) {
            g_Dbs.db[i].dbCfg.days = -1;
4729
        } else {
4730
            errorPrint("%s", "failed to read json, days not found\n");
4731 4732
            goto PARSE_OVER;
        }
4733

4734 4735 4736 4737 4738 4739
        cJSON* cache = cJSON_GetObjectItem(dbinfo, "cache");
        if (cache && cache->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.cache = cache->valueint;
        } else if (!cache) {
            g_Dbs.db[i].dbCfg.cache = -1;
        } else {
4740
            errorPrint("%s", "failed to read json, cache not found\n");
4741
            goto PARSE_OVER;
4742 4743
        }

4744 4745 4746 4747 4748 4749
        cJSON* blocks= cJSON_GetObjectItem(dbinfo, "blocks");
        if (blocks && blocks->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.blocks = blocks->valueint;
        } else if (!blocks) {
            g_Dbs.db[i].dbCfg.blocks = -1;
        } else {
4750
            errorPrint("%s", "failed to read json, block not found\n");
4751
            goto PARSE_OVER;
4752 4753
        }

4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769
        //cJSON* maxtablesPerVnode= cJSON_GetObjectItem(dbinfo, "maxtablesPerVnode");
        //if (maxtablesPerVnode && maxtablesPerVnode->type == cJSON_Number) {
        //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = maxtablesPerVnode->valueint;
        //} else if (!maxtablesPerVnode) {
        //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = TSDB_DEFAULT_TABLES;
        //} else {
        // printf("failed to read json, maxtablesPerVnode not found");
        // goto PARSE_OVER;
        //}

        cJSON* minRows= cJSON_GetObjectItem(dbinfo, "minRows");
        if (minRows && minRows->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.minRows = minRows->valueint;
        } else if (!minRows) {
            g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
        } else {
4770
            errorPrint("%s", "failed to read json, minRows not found\n");
4771 4772
            goto PARSE_OVER;
        }
4773

4774 4775 4776 4777 4778 4779
        cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
        if (maxRows && maxRows->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
        } else if (!maxRows) {
            g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
        } else {
4780
            errorPrint("%s", "failed to read json, maxRows not found\n");
4781 4782
            goto PARSE_OVER;
        }
4783

4784 4785 4786 4787 4788 4789
        cJSON* comp= cJSON_GetObjectItem(dbinfo, "comp");
        if (comp && comp->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.comp = comp->valueint;
        } else if (!comp) {
            g_Dbs.db[i].dbCfg.comp = -1;
        } else {
4790
            errorPrint("%s", "failed to read json, comp not found\n");
4791 4792
            goto PARSE_OVER;
        }
4793

4794 4795 4796 4797 4798 4799
        cJSON* walLevel= cJSON_GetObjectItem(dbinfo, "walLevel");
        if (walLevel && walLevel->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.walLevel = walLevel->valueint;
        } else if (!walLevel) {
            g_Dbs.db[i].dbCfg.walLevel = -1;
        } else {
4800
            errorPrint("%s", "failed to read json, walLevel not found\n");
4801 4802
            goto PARSE_OVER;
        }
4803

4804 4805 4806 4807 4808
        cJSON* cacheLast= cJSON_GetObjectItem(dbinfo, "cachelast");
        if (cacheLast && cacheLast->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.cacheLast = cacheLast->valueint;
        } else if (!cacheLast) {
            g_Dbs.db[i].dbCfg.cacheLast = -1;
4809
        } else {
4810
            errorPrint("%s", "failed to read json, cacheLast not found\n");
4811
            goto PARSE_OVER;
4812
        }
4813

4814 4815 4816 4817 4818
        cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
        if (quorum && quorum->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
        } else if (!quorum) {
            g_Dbs.db[i].dbCfg.quorum = 1;
4819
        } else {
4820 4821
            printf("failed to read json, quorum input mistake");
            goto PARSE_OVER;
4822
        }
4823 4824 4825 4826 4827 4828 4829

        cJSON* fsync= cJSON_GetObjectItem(dbinfo, "fsync");
        if (fsync && fsync->type == cJSON_Number) {
            g_Dbs.db[i].dbCfg.fsync = fsync->valueint;
        } else if (!fsync) {
            g_Dbs.db[i].dbCfg.fsync = -1;
        } else {
4830
            errorPrint("%s", "failed to read json, fsync input mistake\n");
4831
            goto PARSE_OVER;
4832 4833
        }

4834 4835 4836
        // super_talbes
        cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
        if (!stables || stables->type != cJSON_Array) {
4837
            errorPrint("%s", "failed to read json, super_tables not found\n");
4838
            goto PARSE_OVER;
4839
        }
4840

4841 4842 4843
        int stbSize = cJSON_GetArraySize(stables);
        if (stbSize > MAX_SUPER_TABLE_COUNT) {
            errorPrint(
4844 4845
                    "failed to read json, supertable size overflow, max supertable is %d\n",
                    MAX_SUPER_TABLE_COUNT);
4846
            goto PARSE_OVER;
4847
        }
4848

4849 4850 4851 4852
        g_Dbs.db[i].superTblCount = stbSize;
        for (int j = 0; j < stbSize; ++j) {
            cJSON* stbInfo = cJSON_GetArrayItem(stables, j);
            if (stbInfo == NULL) continue;
4853

4854 4855 4856 4857
            // dbinfo
            cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
            if (!stbName || stbName->type != cJSON_String
                    || stbName->valuestring == NULL) {
4858
                errorPrint("%s", "failed to read json, stb name not found\n");
4859 4860 4861 4862
                goto PARSE_OVER;
            }
            tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring,
                    TSDB_TABLE_NAME_LEN);
4863

4864 4865
            cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
            if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
4866
                errorPrint("%s", "failed to read json, childtable_prefix not found\n");
4867 4868 4869
                goto PARSE_OVER;
            }
            tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring,
4870
                    TBNAME_PREFIX_LEN);
4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886

            cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table");
            if (autoCreateTbl
                    && autoCreateTbl->type == cJSON_String
                    && autoCreateTbl->valuestring != NULL) {
                if ((0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3))
                        && (TBL_ALREADY_EXISTS != g_Dbs.db[i].superTbls[j].childTblExists)) {
                    g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL;
                } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) {
                    g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
                } else {
                    g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
                }
            } else if (!autoCreateTbl) {
                g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
            } else {
4887
                errorPrint("%s", "failed to read json, auto_create_table not found\n");
4888 4889
                goto PARSE_OVER;
            }
4890

4891 4892 4893 4894
            cJSON* batchCreateTbl = cJSON_GetObjectItem(stbInfo, "batch_create_tbl_num");
            if (batchCreateTbl && batchCreateTbl->type == cJSON_Number) {
                g_Dbs.db[i].superTbls[j].batchCreateTableNum = batchCreateTbl->valueint;
            } else if (!batchCreateTbl) {
4895
                g_Dbs.db[i].superTbls[j].batchCreateTableNum = 10;
4896
            } else {
4897
                errorPrint("%s", "failed to read json, batch_create_tbl_num not found\n");
4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916
                goto PARSE_OVER;
            }

            cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
            if (childTblExists
                    && childTblExists->type == cJSON_String
                    && childTblExists->valuestring != NULL) {
                if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
                        && (g_Dbs.db[i].drop == false)) {
                    g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
                } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
                            || (g_Dbs.db[i].drop == true))) {
                    g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
                } else {
                    g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
                }
            } else if (!childTblExists) {
                g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
            } else {
4917 4918
                errorPrint("%s",
                        "failed to read json, child_table_exists not found\n");
4919 4920 4921 4922 4923 4924 4925 4926 4927
                goto PARSE_OVER;
            }

            if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
            }

            cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
            if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
4928 4929
                errorPrint("%s",
                        "failed to read json, childtable_count input mistake\n");
4930 4931 4932
                goto PARSE_OVER;
            }
            g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;
4933
            g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;
4934 4935 4936 4937 4938

            cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
            if (dataSource && dataSource->type == cJSON_String
                    && dataSource->valuestring != NULL) {
                tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
4939 4940
                        dataSource->valuestring,
                        min(SMALL_BUFF_LEN, strlen(dataSource->valuestring) + 1));
4941
            } else if (!dataSource) {
4942 4943
                tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand",
                        min(SMALL_BUFF_LEN, strlen("rand") + 1));
4944
            } else {
4945
                errorPrint("%s", "failed to read json, data_source not found\n");
4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958
                goto PARSE_OVER;
            }

            cJSON *stbIface = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest, stmt
            if (stbIface && stbIface->type == cJSON_String
                    && stbIface->valuestring != NULL) {
                if (0 == strcasecmp(stbIface->valuestring, "taosc")) {
                    g_Dbs.db[i].superTbls[j].iface= TAOSC_IFACE;
                } else if (0 == strcasecmp(stbIface->valuestring, "rest")) {
                    g_Dbs.db[i].superTbls[j].iface= REST_IFACE;
                } else if (0 == strcasecmp(stbIface->valuestring, "stmt")) {
                    g_Dbs.db[i].superTbls[j].iface= STMT_IFACE;
                } else {
4959 4960
                    errorPrint("failed to read json, insert_mode %s not recognized\n",
                            stbIface->valuestring);
4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973
                    goto PARSE_OVER;
                }
            } else if (!stbIface) {
                g_Dbs.db[i].superTbls[j].iface = TAOSC_IFACE;
            } else {
                errorPrint("%s", "failed to read json, insert_mode not found\n");
                goto PARSE_OVER;
            }

            cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
            if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
                    && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
                if (childTbl_limit->type != cJSON_Number) {
4974
                    errorPrint("%s", "failed to read json, childtable_limit\n");
4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986
                    goto PARSE_OVER;
                }
                g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
            } else {
                g_Dbs.db[i].superTbls[j].childTblLimit = -1;    // select ... limit -1 means all query result, drop = yes mean all table need recreate, limit value is invalid.
            }

            cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
            if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
                    && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
                if ((childTbl_offset->type != cJSON_Number)
                        || (0 > childTbl_offset->valueint)) {
4987
                    errorPrint("%s", "failed to read json, childtable_offset\n");
4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002
                    goto PARSE_OVER;
                }
                g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
            } else {
                g_Dbs.db[i].superTbls[j].childTblOffset = 0;
            }

            cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
            if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
                tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                        ts->valuestring, TSDB_DB_NAME_LEN);
            } else if (!ts) {
                tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                        "now", TSDB_DB_NAME_LEN);
            } else {
5003
                errorPrint("%s", "failed to read json, start_timestamp not found\n");
5004 5005 5006 5007 5008 5009 5010
                goto PARSE_OVER;
            }

            cJSON* timestampStep = cJSON_GetObjectItem(stbInfo, "timestamp_step");
            if (timestampStep && timestampStep->type == cJSON_Number) {
                g_Dbs.db[i].superTbls[j].timeStampStep = timestampStep->valueint;
            } else if (!timestampStep) {
5011
                g_Dbs.db[i].superTbls[j].timeStampStep = g_args.timestamp_step;
5012
            } else {
5013
                errorPrint("%s", "failed to read json, timestamp_step not found\n");
5014 5015 5016 5017 5018 5019 5020
                goto PARSE_OVER;
            }

            cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
            if (sampleFormat && sampleFormat->type
                    == cJSON_String && sampleFormat->valuestring != NULL) {
                tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
5021 5022 5023
                        sampleFormat->valuestring,
                        min(SMALL_BUFF_LEN,
                            strlen(sampleFormat->valuestring) + 1));
5024
            } else if (!sampleFormat) {
5025 5026
                tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv",
                        SMALL_BUFF_LEN);
5027
            } else {
5028
                errorPrint("%s", "failed to read json, sample_format not found\n");
5029 5030 5031 5032 5033 5034 5035
                goto PARSE_OVER;
            }

            cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
            if (sampleFile && sampleFile->type == cJSON_String
                    && sampleFile->valuestring != NULL) {
                tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
5036 5037 5038
                        sampleFile->valuestring,
                        min(MAX_FILE_NAME_LEN,
                            strlen(sampleFile->valuestring) + 1));
5039
            } else if (!sampleFile) {
5040 5041
                memset(g_Dbs.db[i].superTbls[j].sampleFile, 0,
                        MAX_FILE_NAME_LEN);
5042
            } else {
5043
                errorPrint("%s", "failed to read json, sample_file not found\n");
5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060
                goto PARSE_OVER;
            }

            cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
            if ((tagsFile && tagsFile->type == cJSON_String)
                    && (tagsFile->valuestring != NULL)) {
                tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
                        tagsFile->valuestring, MAX_FILE_NAME_LEN);
                if (0 == g_Dbs.db[i].superTbls[j].tagsFile[0]) {
                    g_Dbs.db[i].superTbls[j].tagSource = 0;
                } else {
                    g_Dbs.db[i].superTbls[j].tagSource = 1;
                }
            } else if (!tagsFile) {
                memset(g_Dbs.db[i].superTbls[j].tagsFile, 0, MAX_FILE_NAME_LEN);
                g_Dbs.db[i].superTbls[j].tagSource = 0;
            } else {
5061
                errorPrint("%s", "failed to read json, tags_file not found\n");
5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076
                goto PARSE_OVER;
            }

            cJSON* stbMaxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
            if (stbMaxSqlLen && stbMaxSqlLen->type == cJSON_Number) {
                int32_t len = stbMaxSqlLen->valueint;
                if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
                    len = TSDB_MAX_ALLOWED_SQL_LEN;
                } else if (len < 5) {
                    len = 5;
                }
                g_Dbs.db[i].superTbls[j].maxSqlLen = len;
            } else if (!maxSqlLen) {
                g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
            } else {
5077
                errorPrint("%s", "failed to read json, stbMaxSqlLen input mistake\n");
5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093
                goto PARSE_OVER;
            }
            /*
               cJSON *multiThreadWriteOneTbl =
               cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
               if (multiThreadWriteOneTbl
               && multiThreadWriteOneTbl->type == cJSON_String
               && multiThreadWriteOneTbl->valuestring != NULL) {
               if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
               g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
               } else {
               g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
               }
               } else if (!multiThreadWriteOneTbl) {
               g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
               } else {
5094
               errorPrint("%s", "failed to read json, multiThreadWriteOneTbl not found\n");
5095 5096 5097 5098 5099 5100
               goto PARSE_OVER;
               }
               */
            cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
            if (insertRows && insertRows->type == cJSON_Number) {
                if (insertRows->valueint < 0) {
5101
                    errorPrint("%s", "failed to read json, insert_rows input mistake\n");
5102 5103 5104 5105 5106 5107
                    goto PARSE_OVER;
                }
                g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
            } else if (!insertRows) {
                g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
            } else {
5108
                errorPrint("%s", "failed to read json, insert_rows input mistake\n");
5109 5110 5111 5112 5113 5114
                goto PARSE_OVER;
            }

            cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
            if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) {
                if (stbInterlaceRows->valueint < 0) {
5115
                    errorPrint("%s", "failed to read json, interlace rows input mistake\n");
5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132
                    goto PARSE_OVER;
                }
                g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint;

                if (g_Dbs.db[i].superTbls[j].interlaceRows > g_Dbs.db[i].superTbls[j].insertRows) {
                    printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %u > insert_rows %"PRId64"\n\n",
                            i, j, g_Dbs.db[i].superTbls[j].interlaceRows,
                            g_Dbs.db[i].superTbls[j].insertRows);
                    printf("        interlace rows value will be set to insert_rows %"PRId64"\n\n",
                            g_Dbs.db[i].superTbls[j].insertRows);
                    prompt();
                    g_Dbs.db[i].superTbls[j].interlaceRows = g_Dbs.db[i].superTbls[j].insertRows;
                }
            } else if (!stbInterlaceRows) {
                g_Dbs.db[i].superTbls[j].interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
            } else {
                errorPrint(
5133
                        "%s", "failed to read json, interlace rows input mistake\n");
5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148
                goto PARSE_OVER;
            }

            cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
            if (disorderRatio && disorderRatio->type == cJSON_Number) {
                if (disorderRatio->valueint > 50)
                    disorderRatio->valueint = 50;

                if (disorderRatio->valueint < 0)
                    disorderRatio->valueint = 0;

                g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
            } else if (!disorderRatio) {
                g_Dbs.db[i].superTbls[j].disorderRatio = 0;
            } else {
5149
                errorPrint("%s", "failed to read json, disorderRatio not found\n");
5150 5151 5152 5153 5154 5155 5156 5157 5158
                goto PARSE_OVER;
            }

            cJSON* disorderRange = cJSON_GetObjectItem(stbInfo, "disorder_range");
            if (disorderRange && disorderRange->type == cJSON_Number) {
                g_Dbs.db[i].superTbls[j].disorderRange = disorderRange->valueint;
            } else if (!disorderRange) {
                g_Dbs.db[i].superTbls[j].disorderRange = 1000;
            } else {
5159
                errorPrint("%s", "failed to read json, disorderRange not found\n");
5160 5161 5162 5163 5164 5165 5166
                goto PARSE_OVER;
            }

            cJSON* insertInterval = cJSON_GetObjectItem(stbInfo, "insert_interval");
            if (insertInterval && insertInterval->type == cJSON_Number) {
                g_Dbs.db[i].superTbls[j].insertInterval = insertInterval->valueint;
                if (insertInterval->valueint < 0) {
5167
                    errorPrint("%s", "failed to read json, insert_interval input mistake\n");
5168 5169 5170 5171 5172 5173 5174
                    goto PARSE_OVER;
                }
            } else if (!insertInterval) {
                verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
                        __func__, __LINE__, g_args.insert_interval);
                g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
            } else {
5175
                errorPrint("%s", "failed to read json, insert_interval input mistake\n");
5176 5177
                goto PARSE_OVER;
            }
5178

5179 5180 5181 5182 5183
            int retVal = getColumnAndTagTypeFromInsertJsonFile(
                    stbInfo, &g_Dbs.db[i].superTbls[j]);
            if (false == retVal) {
                goto PARSE_OVER;
            }
5184
        }
5185
    }
5186

5187
    ret = true;
5188

5189
PARSE_OVER:
5190
    return ret;
5191 5192 5193
}

static bool getMetaFromQueryJsonFile(cJSON* root) {
5194
    bool  ret = false;
5195

5196 5197 5198 5199
    cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
    if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
        tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
    }
H
hzcheng 已提交
5200

5201 5202 5203 5204 5205
    cJSON* host = cJSON_GetObjectItem(root, "host");
    if (host && host->type == cJSON_String && host->valuestring != NULL) {
        tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
    } else if (!host) {
        tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
H
hzcheng 已提交
5206
    } else {
5207
        errorPrint("%s", "failed to read json, host not found\n");
5208
        goto PARSE_OVER;
H
hzcheng 已提交
5209
    }
5210

5211 5212 5213 5214 5215
    cJSON* port = cJSON_GetObjectItem(root, "port");
    if (port && port->type == cJSON_Number) {
        g_queryInfo.port = port->valueint;
    } else if (!port) {
        g_queryInfo.port = 6030;
5216
    }
5217

5218 5219 5220 5221 5222
    cJSON* user = cJSON_GetObjectItem(root, "user");
    if (user && user->type == cJSON_String && user->valuestring != NULL) {
        tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
    } else if (!user) {
        tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
5223 5224
    }

5225 5226
    cJSON* password = cJSON_GetObjectItem(root, "password");
    if (password && password->type == cJSON_String && password->valuestring != NULL) {
5227
        tstrncpy(g_queryInfo.password, password->valuestring, SHELL_MAX_PASSWORD_LEN);
5228
    } else if (!password) {
5229
        tstrncpy(g_queryInfo.password, "taosdata", SHELL_MAX_PASSWORD_LEN);;
5230
    }
5231

5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243
    cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
    if (answerPrompt && answerPrompt->type == cJSON_String
            && answerPrompt->valuestring != NULL) {
        if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
            g_args.answer_yes = false;
        } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
            g_args.answer_yes = true;
        } else {
            g_args.answer_yes = false;
        }
    } else if (!answerPrompt) {
        g_args.answer_yes = false;
5244
    } else {
5245
        errorPrint("%s", "failed to read json, confirm_parameter_prompt not found\n");
5246
        goto PARSE_OVER;
5247
    }
5248

5249 5250 5251
    cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
    if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
        if (gQueryTimes->valueint <= 0) {
5252
            errorPrint("%s()", "failed to read json, query_times input mistake\n");
5253 5254 5255 5256 5257
            goto PARSE_OVER;
        }
        g_args.query_times = gQueryTimes->valueint;
    } else if (!gQueryTimes) {
        g_args.query_times = 1;
5258
    } else {
5259
        errorPrint("%s", "failed to read json, query_times input mistake\n");
5260
        goto PARSE_OVER;
5261
    }
5262

5263 5264 5265 5266
    cJSON* dbs = cJSON_GetObjectItem(root, "databases");
    if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
        tstrncpy(g_queryInfo.dbName, dbs->valuestring, TSDB_DB_NAME_LEN);
    } else if (!dbs) {
5267
        errorPrint("%s", "failed to read json, databases not found\n");
5268
        goto PARSE_OVER;
5269
    }
5270

5271
    cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
5272 5273 5274 5275 5276
    if (queryMode
            && queryMode->type == cJSON_String
            && queryMode->valuestring != NULL) {
        tstrncpy(g_queryInfo.queryMode, queryMode->valuestring,
                min(SMALL_BUFF_LEN, strlen(queryMode->valuestring) + 1));
5277
    } else if (!queryMode) {
5278 5279
        tstrncpy(g_queryInfo.queryMode, "taosc",
                min(SMALL_BUFF_LEN, strlen("taosc") + 1));
5280
    } else {
5281
        errorPrint("%s", "failed to read json, query_mode not found\n");
5282
        goto PARSE_OVER;
5283
    }
5284

5285 5286 5287 5288 5289 5290
    // specified_table_query
    cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
    if (!specifiedQuery) {
        g_queryInfo.specifiedQueryInfo.concurrent = 1;
        g_queryInfo.specifiedQueryInfo.sqlCount = 0;
    } else if (specifiedQuery->type != cJSON_Object) {
5291
        errorPrint("%s", "failed to read json, super_table_query not found\n");
5292 5293
        goto PARSE_OVER;
    } else {
5294 5295 5296 5297 5298 5299
        cJSON* queryInterval = cJSON_GetObjectItem(specifiedQuery, "query_interval");
        if (queryInterval && queryInterval->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.queryInterval = queryInterval->valueint;
        } else if (!queryInterval) {
            g_queryInfo.specifiedQueryInfo.queryInterval = 0;
        }
5300

5301 5302 5303 5304 5305
        cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
                "query_times");
        if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
            if (specifiedQueryTimes->valueint <= 0) {
                errorPrint(
5306 5307
                        "failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                        specifiedQueryTimes->valueint);
5308
                goto PARSE_OVER;
5309

5310 5311 5312 5313
            }
            g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
        } else if (!specifiedQueryTimes) {
            g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
5314
        } else {
5315 5316 5317
            errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
                    __func__, __LINE__);
            goto PARSE_OVER;
5318
        }
5319

5320 5321 5322 5323
        cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
        if (concurrent && concurrent->type == cJSON_Number) {
            if (concurrent->valueint <= 0) {
                errorPrint(
5324
                        "query sqlCount %d or concurrent %d is not correct.\n",
5325 5326 5327 5328 5329 5330 5331 5332
                        g_queryInfo.specifiedQueryInfo.sqlCount,
                        g_queryInfo.specifiedQueryInfo.concurrent);
                goto PARSE_OVER;
            }
            g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
        } else if (!concurrent) {
            g_queryInfo.specifiedQueryInfo.concurrent = 1;
        }
5333

5334 5335 5336 5337 5338 5339 5340 5341
        cJSON* specifiedAsyncMode = cJSON_GetObjectItem(specifiedQuery, "mode");
        if (specifiedAsyncMode && specifiedAsyncMode->type == cJSON_String
                && specifiedAsyncMode->valuestring != NULL) {
            if (0 == strcmp("sync", specifiedAsyncMode->valuestring)) {
                g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
            } else if (0 == strcmp("async", specifiedAsyncMode->valuestring)) {
                g_queryInfo.specifiedQueryInfo.asyncMode = ASYNC_MODE;
            } else {
5342
                errorPrint("%s", "failed to read json, async mode input error\n");
5343 5344 5345 5346 5347
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
        }
5348

5349 5350 5351 5352 5353 5354 5355 5356
        cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
        if (interval && interval->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
        } else if (!interval) {
            //printf("failed to read json, subscribe interval no found\n");
            //goto PARSE_OVER;
            g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
        }
5357

5358 5359 5360 5361 5362 5363 5364
        cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
        if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
            if (0 == strcmp("yes", restart->valuestring)) {
                g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
            } else if (0 == strcmp("no", restart->valuestring)) {
                g_queryInfo.specifiedQueryInfo.subscribeRestart = false;
            } else {
5365
                errorPrint("%s", "failed to read json, subscribe restart error\n");
5366 5367 5368 5369 5370
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
        }
5371

5372 5373 5374 5375 5376 5377 5378 5379 5380
        cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
        if (keepProgress
                && keepProgress->type == cJSON_String
                && keepProgress->valuestring != NULL) {
            if (0 == strcmp("yes", keepProgress->valuestring)) {
                g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
            } else if (0 == strcmp("no", keepProgress->valuestring)) {
                g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
            } else {
5381
                errorPrint("%s", "failed to read json, subscribe keepProgress error\n");
5382 5383 5384 5385 5386
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
        }
5387

5388 5389 5390 5391 5392
        // sqls
        cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
        if (!specifiedSqls) {
            g_queryInfo.specifiedQueryInfo.sqlCount = 0;
        } else if (specifiedSqls->type != cJSON_Array) {
5393
            errorPrint("%s", "failed to read json, super sqls not found\n");
5394 5395 5396 5397 5398
            goto PARSE_OVER;
        } else {
            int superSqlSize = cJSON_GetArraySize(specifiedSqls);
            if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent
                    > MAX_QUERY_SQL_COUNT) {
5399
                errorPrint("failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n",
5400 5401 5402 5403 5404
                        superSqlSize,
                        g_queryInfo.specifiedQueryInfo.concurrent,
                        MAX_QUERY_SQL_COUNT);
                goto PARSE_OVER;
            }
5405

5406 5407 5408 5409 5410 5411 5412
            g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
            for (int j = 0; j < superSqlSize; ++j) {
                cJSON* sql = cJSON_GetArrayItem(specifiedSqls, j);
                if (sql == NULL) continue;

                cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
                if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
5413
                    errorPrint("%s", "failed to read json, sql not found\n");
5414 5415 5416
                    goto PARSE_OVER;
                }
                tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
5417
                        sqlStr->valuestring, BUFFER_SIZE);
5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452

                // default value is -1, which mean infinite loop
                g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;
                cJSON* endAfterConsume =
                    cJSON_GetObjectItem(specifiedQuery, "endAfterConsume");
                if (endAfterConsume
                        && endAfterConsume->type == cJSON_Number) {
                    g_queryInfo.specifiedQueryInfo.endAfterConsume[j]
                        = endAfterConsume->valueint;
                }
                if (g_queryInfo.specifiedQueryInfo.endAfterConsume[j] < -1)
                    g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;

                g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
                cJSON* resubAfterConsume =
                    cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
                if ((resubAfterConsume)
                        && (resubAfterConsume->type == cJSON_Number)
                        && (resubAfterConsume->valueint >= 0)) {
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
                        = resubAfterConsume->valueint;
                }

                if (g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] < -1)
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;

                cJSON *result = cJSON_GetObjectItem(sql, "result");
                if ((NULL != result) && (result->type == cJSON_String)
                        && (result->valuestring != NULL)) {
                    tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                            result->valuestring, MAX_FILE_NAME_LEN);
                } else if (NULL == result) {
                    memset(g_queryInfo.specifiedQueryInfo.result[j],
                            0, MAX_FILE_NAME_LEN);
                } else {
5453 5454
                    errorPrint("%s",
                            "failed to read json, super query result file not found\n");
5455 5456 5457 5458
                    goto PARSE_OVER;
                }
            }
        }
5459
    }
5460

5461 5462 5463 5464 5465 5466
    // super_table_query
    cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
    if (!superQuery) {
        g_queryInfo.superQueryInfo.threadCnt = 1;
        g_queryInfo.superQueryInfo.sqlCount = 0;
    } else if (superQuery->type != cJSON_Object) {
5467
        errorPrint("%s", "failed to read json, sub_table_query not found\n");
5468
        ret = true;
5469 5470
        goto PARSE_OVER;
    } else {
5471 5472 5473 5474 5475 5476 5477 5478 5479 5480
        cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
        if (subrate && subrate->type == cJSON_Number) {
            g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
        } else if (!subrate) {
            g_queryInfo.superQueryInfo.queryInterval = 0;
        }

        cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
        if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
            if (superQueryTimes->valueint <= 0) {
5481 5482
                errorPrint("failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                        superQueryTimes->valueint);
5483 5484 5485 5486 5487 5488
                goto PARSE_OVER;
            }
            g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
        } else if (!superQueryTimes) {
            g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
        } else {
5489
            errorPrint("%s", "failed to read json, query_times input mistake\n");
5490 5491
            goto PARSE_OVER;
        }
5492

5493 5494 5495
        cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
        if (threads && threads->type == cJSON_Number) {
            if (threads->valueint <= 0) {
5496
                errorPrint("%s", "failed to read json, threads input mistake\n");
5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517
                goto PARSE_OVER;

            }
            g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
        } else if (!threads) {
            g_queryInfo.superQueryInfo.threadCnt = 1;
        }

        //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
        //if (subTblCnt && subTblCnt->type == cJSON_Number) {
        //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
        //} else if (!subTblCnt) {
        //  g_queryInfo.superQueryInfo.childTblCount = 0;
        //}

        cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
        if (stblname && stblname->type == cJSON_String
                && stblname->valuestring != NULL) {
            tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
                    TSDB_TABLE_NAME_LEN);
        } else {
5518
            errorPrint("%s", "failed to read json, super table name input error\n");
5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529
            goto PARSE_OVER;
        }

        cJSON* superAsyncMode = cJSON_GetObjectItem(superQuery, "mode");
        if (superAsyncMode && superAsyncMode->type == cJSON_String
                && superAsyncMode->valuestring != NULL) {
            if (0 == strcmp("sync", superAsyncMode->valuestring)) {
                g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
            } else if (0 == strcmp("async", superAsyncMode->valuestring)) {
                g_queryInfo.superQueryInfo.asyncMode = ASYNC_MODE;
            } else {
5530
                errorPrint("%s", "failed to read json, async mode input error\n");
5531 5532 5533 5534 5535 5536 5537 5538 5539
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
        }

        cJSON* superInterval = cJSON_GetObjectItem(superQuery, "interval");
        if (superInterval && superInterval->type == cJSON_Number) {
            if (superInterval->valueint < 0) {
5540
                errorPrint("%s", "failed to read json, interval input mistake\n");
5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557
                goto PARSE_OVER;
            }
            g_queryInfo.superQueryInfo.subscribeInterval = superInterval->valueint;
        } else if (!superInterval) {
            //printf("failed to read json, subscribe interval no found\n");
            //goto PARSE_OVER;
            g_queryInfo.superQueryInfo.subscribeInterval = 10000;
        }

        cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
        if (subrestart && subrestart->type == cJSON_String
                && subrestart->valuestring != NULL) {
            if (0 == strcmp("yes", subrestart->valuestring)) {
                g_queryInfo.superQueryInfo.subscribeRestart = true;
            } else if (0 == strcmp("no", subrestart->valuestring)) {
                g_queryInfo.superQueryInfo.subscribeRestart = false;
            } else {
5558
                errorPrint("%s", "failed to read json, subscribe restart error\n");
5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.superQueryInfo.subscribeRestart = true;
        }

        cJSON* superkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
        if (superkeepProgress &&
                superkeepProgress->type == cJSON_String
                && superkeepProgress->valuestring != NULL) {
            if (0 == strcmp("yes", superkeepProgress->valuestring)) {
                g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
            } else if (0 == strcmp("no", superkeepProgress->valuestring)) {
                g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
            } else {
5574 5575
                errorPrint("%s",
                        "failed to read json, subscribe super table keepProgress error\n");
5576 5577 5578 5579 5580 5581 5582
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
        }

        // default value is -1, which mean do not resub
5583
        g_queryInfo.superQueryInfo.endAfterConsume = -1;
5584 5585 5586 5587 5588 5589 5590 5591 5592
        cJSON* superEndAfterConsume =
            cJSON_GetObjectItem(superQuery, "endAfterConsume");
        if (superEndAfterConsume
                && superEndAfterConsume->type == cJSON_Number) {
            g_queryInfo.superQueryInfo.endAfterConsume =
                superEndAfterConsume->valueint;
        }
        if (g_queryInfo.superQueryInfo.endAfterConsume < -1)
            g_queryInfo.superQueryInfo.endAfterConsume = -1;
5593

5594
        // default value is -1, which mean do not resub
5595
        g_queryInfo.superQueryInfo.resubAfterConsume = -1;
5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611
        cJSON* superResubAfterConsume =
            cJSON_GetObjectItem(superQuery, "resubAfterConsume");
        if ((superResubAfterConsume)
                && (superResubAfterConsume->type == cJSON_Number)
                && (superResubAfterConsume->valueint >= 0)) {
            g_queryInfo.superQueryInfo.resubAfterConsume =
                superResubAfterConsume->valueint;
        }
        if (g_queryInfo.superQueryInfo.resubAfterConsume < -1)
            g_queryInfo.superQueryInfo.resubAfterConsume = -1;

        // supert table sqls
        cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
        if (!superSqls) {
            g_queryInfo.superQueryInfo.sqlCount = 0;
        } else if (superSqls->type != cJSON_Array) {
5612
            errorPrint("%s", "failed to read json, super sqls not found\n");
5613 5614 5615 5616
            goto PARSE_OVER;
        } else {
            int superSqlSize = cJSON_GetArraySize(superSqls);
            if (superSqlSize > MAX_QUERY_SQL_COUNT) {
5617 5618
                errorPrint("failed to read json, query sql size overflow, max is %d\n",
                        MAX_QUERY_SQL_COUNT);
5619 5620
                goto PARSE_OVER;
            }
5621

5622 5623 5624 5625
            g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
            for (int j = 0; j < superSqlSize; ++j) {
                cJSON* sql = cJSON_GetArrayItem(superSqls, j);
                if (sql == NULL) continue;
5626

5627 5628 5629
                cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
                if (!sqlStr || sqlStr->type != cJSON_String
                        || sqlStr->valuestring == NULL) {
5630
                    errorPrint("%s", "failed to read json, sql not found\n");
5631 5632 5633
                    goto PARSE_OVER;
                }
                tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
5634
                        BUFFER_SIZE);
5635 5636 5637

                cJSON *result = cJSON_GetObjectItem(sql, "result");
                if (result != NULL && result->type == cJSON_String
5638
                        && result->valuestring != NULL) {
5639 5640 5641 5642 5643
                    tstrncpy(g_queryInfo.superQueryInfo.result[j],
                            result->valuestring, MAX_FILE_NAME_LEN);
                } else if (NULL == result) {
                    memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
                }  else {
5644
                    errorPrint("%s", "failed to read json, sub query result file not found\n");
5645 5646 5647
                    goto PARSE_OVER;
                }
            }
5648
        }
5649
    }
H
hzcheng 已提交
5650

5651
    ret = true;
H
hzcheng 已提交
5652

5653
PARSE_OVER:
5654
    return ret;
5655
}
H
hzcheng 已提交
5656

5657
static bool getInfoFromJsonFile(char* file) {
5658
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
5659

5660 5661
    FILE *fp = fopen(file, "r");
    if (!fp) {
5662
        errorPrint("failed to read %s, reason:%s\n", file, strerror(errno));
5663 5664
        return false;
    }
H
Hui Li 已提交
5665

5666 5667 5668 5669 5670 5671 5672
    bool  ret = false;
    int   maxLen = 6400000;
    char *content = calloc(1, maxLen + 1);
    int   len = fread(content, 1, maxLen, fp);
    if (len <= 0) {
        free(content);
        fclose(fp);
5673
        errorPrint("failed to read %s, content is null", file);
5674 5675
        return false;
    }
H
Hui Li 已提交
5676

5677 5678 5679
    content[len] = 0;
    cJSON* root = cJSON_Parse(content);
    if (root == NULL) {
5680
        errorPrint("failed to cjson parse %s, invalid json format\n", file);
5681 5682
        goto PARSE_OVER;
    }
H
Hui Li 已提交
5683

5684 5685 5686 5687 5688 5689 5690 5691 5692
    cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
    if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
        if (0 == strcasecmp("insert", filetype->valuestring)) {
            g_args.test_mode = INSERT_TEST;
        } else if (0 == strcasecmp("query", filetype->valuestring)) {
            g_args.test_mode = QUERY_TEST;
        } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
            g_args.test_mode = SUBSCRIBE_TEST;
        } else {
5693
            errorPrint("%s", "failed to read json, filetype not support\n");
5694 5695 5696 5697
            goto PARSE_OVER;
        }
    } else if (!filetype) {
        g_args.test_mode = INSERT_TEST;
5698
    } else {
5699
        errorPrint("%s", "failed to read json, filetype not found\n");
5700
        goto PARSE_OVER;
5701
    }
H
hzcheng 已提交
5702

5703 5704 5705 5706 5707 5708
    if (INSERT_TEST == g_args.test_mode) {
        ret = getMetaFromInsertJsonFile(root);
    } else if ((QUERY_TEST == g_args.test_mode)
            || (SUBSCRIBE_TEST == g_args.test_mode)) {
        ret = getMetaFromQueryJsonFile(root);
    } else {
5709 5710
        errorPrint("%s",
                "input json file type error! please input correct file type: insert or query or subscribe\n");
5711 5712
        goto PARSE_OVER;
    }
5713

5714
PARSE_OVER:
5715 5716 5717 5718
    free(content);
    cJSON_Delete(root);
    fclose(fp);
    return ret;
5719
}
H
hzcheng 已提交
5720

5721
static int prepareSampleData() {
5722 5723 5724 5725 5726 5727 5728
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) {
                if (readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]) != 0) {
                    return -1;
                }
            }
5729
        }
5730
    }
5731

5732
    return 0;
5733 5734
}

5735
static void postFreeResource() {
5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746
    tmfclose(g_fpOfInsertResult);
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            if (0 != g_Dbs.db[i].superTbls[j].colsOfCreateChildTable) {
                free(g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
                g_Dbs.db[i].superTbls[j].colsOfCreateChildTable = NULL;
            }
            if (0 != g_Dbs.db[i].superTbls[j].sampleDataBuf) {
                free(g_Dbs.db[i].superTbls[j].sampleDataBuf);
                g_Dbs.db[i].superTbls[j].sampleDataBuf = NULL;
            }
5747

5748 5749 5750 5751 5752 5753 5754 5755 5756
            if (0 != g_Dbs.db[i].superTbls[j].tagDataBuf) {
                free(g_Dbs.db[i].superTbls[j].tagDataBuf);
                g_Dbs.db[i].superTbls[j].tagDataBuf = NULL;
            }
            if (0 != g_Dbs.db[i].superTbls[j].childTblName) {
                free(g_Dbs.db[i].superTbls[j].childTblName);
                g_Dbs.db[i].superTbls[j].childTblName = NULL;
            }
        }
S
Shuaiqiang Chang 已提交
5757
    }
5758 5759 5760 5761 5762 5763 5764 5765 5766 5767

    tmfree(g_randbool_buff);
    tmfree(g_randint_buff);
    tmfree(g_rand_voltage_buff);
    tmfree(g_randbigint_buff);
    tmfree(g_randsmallint_buff);
    tmfree(g_randtinyint_buff);
    tmfree(g_randfloat_buff);
    tmfree(g_rand_current_buff);
    tmfree(g_rand_phase_buff);
5768

5769
}
S
Shuaiqiang Chang 已提交
5770

5771 5772
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
5773
        SSuperTable* stbInfo, int64_t* sampleUsePos)
5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784
{
    if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
        *sampleUsePos = 0;
    }

    int    dataLen = 0;

    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "(%" PRId64 ", ", timestamp);
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "%s",
5785 5786
            stbInfo->sampleDataBuf
            + stbInfo->lenOfOneRow * (*sampleUsePos));
5787 5788 5789 5790 5791
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");

    (*sampleUsePos)++;

    return dataLen;
5792
}
S
Shuaiqiang Chang 已提交
5793

5794 5795
static int64_t generateStbRowData(
        SSuperTable* stbInfo,
5796 5797 5798
        char* recBuf,
        int64_t remainderBufLen,
        int64_t timestamp)
5799
{
5800 5801 5802
    int64_t   dataLen = 0;
    char  *pstr = recBuf;
    int64_t maxLen = MAX_DATA_SIZE;
5803
    int tmpLen;
5804 5805 5806 5807 5808 5809

    dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
            "(%" PRId64 ",", timestamp);

    for (int i = 0; i < stbInfo->columnCount; i++) {
        if ((0 == strncasecmp(stbInfo->columns[i].dataType,
5810
                        "BINARY", 6))
5811
                || (0 == strncasecmp(stbInfo->columns[i].dataType,
5812
                        "NCHAR", 5))) {
5813
            if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
5814
                errorPrint2("binary or nchar length overflow, max size:%u\n",
5815 5816 5817
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
5818

5819 5820 5821 5822 5823
            if ((stbInfo->columns[i].dataLen + 1) >
                    /* need count 3 extra chars \', \', and , */
                    (remainderBufLen - dataLen - 3)) {
                return 0;
            }
5824 5825
            char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
            if (NULL == buf) {
5826
                errorPrint2("calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
5827 5828 5829 5830 5831
                return -1;
            }
            rand_string(buf, stbInfo->columns[i].dataLen);
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
            tmfree(buf);
5832

5833 5834 5835 5836
        } else {
            char *tmp;

            if (0 == strncasecmp(stbInfo->columns[i].dataType,
5837
                        "INT", 3)) {
5838 5839
                if ((g_args.demo_mode) && (i == 1)) {
                    tmp = demo_voltage_int_str();
5840
                } else {
5841
                    tmp = rand_int_str();
5842
                }
5843 5844
                tmpLen = strlen(tmp);
                tstrncpy(pstr + dataLen, tmp, min(tmpLen + 1, INT_BUFF_LEN));
5845
            } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5846
                        "BIGINT", 6)) {
5847 5848 5849
                tmp = rand_bigint_str();
                tstrncpy(pstr + dataLen, tmp, BIGINT_BUFF_LEN);
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5850
                        "FLOAT", 5)) {
5851 5852 5853 5854 5855 5856 5857 5858 5859
                if (g_args.demo_mode) {
                    if (i == 0) {
                        tmp = demo_current_float_str();
                    } else {
                        tmp = demo_phase_float_str();
                    }
                } else {
                    tmp = rand_float_str();
                }
5860 5861
                tmpLen = strlen(tmp);
                tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, FLOAT_BUFF_LEN));
5862
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5863
                        "DOUBLE", 6)) {
5864
                tmp = rand_double_str();
5865 5866
                tmpLen = strlen(tmp);
                tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, DOUBLE_BUFF_LEN));
5867
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5868
                        "SMALLINT", 8)) {
5869
                tmp = rand_smallint_str();
5870
                tmpLen = strlen(tmp);
5871 5872
                tstrncpy(pstr + dataLen, tmp,
                        min(tmpLen + 1, SMALLINT_BUFF_LEN));
5873
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5874
                        "TINYINT", 7)) {
5875
                tmp = rand_tinyint_str();
5876 5877
                tmpLen = strlen(tmp);
                tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, TINYINT_BUFF_LEN));
5878
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5879
                        "BOOL", 4)) {
5880
                tmp = rand_bool_str();
5881 5882
                tmpLen = strlen(tmp);
                tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BOOL_BUFF_LEN));
5883
            }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
5884
                        "TIMESTAMP", 9)) {
5885
                tmp = rand_bigint_str();
5886
                tmpLen = strlen(tmp);
5887
                tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BIGINT_BUFF_LEN));
5888
            }  else {
5889
                errorPrint2("Not support data type: %s\n",
5890
                        stbInfo->columns[i].dataType);
5891
                return -1;
5892
            }
5893 5894 5895 5896

            dataLen += strlen(tmp);
            tstrncpy(pstr + dataLen, ",", 2);
            dataLen += 1;
5897
        }
5898

5899
        if (dataLen > (remainderBufLen - (128)))
5900
            return 0;
5901
    }
5902

5903
    tstrncpy(pstr + dataLen - 1, ")", 2);
5904

5905 5906
    verbosePrint("%s() LN%d, dataLen:%"PRId64"\n", __func__, __LINE__, dataLen);
    verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);
5907

5908
    return strlen(recBuf);
5909
}
S
Shuaiqiang Chang 已提交
5910

5911
static int64_t generateData(char *recBuf, char **data_type,
5912
        int64_t timestamp, int lenOfBinary) {
5913 5914
    memset(recBuf, 0, MAX_DATA_SIZE);
    char *pstr = recBuf;
5915
    pstr += sprintf(pstr, "(%"PRId64"", timestamp);
5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926

    int columnCount = g_args.num_of_CPR;

    for (int i = 0; i < columnCount; i++) {
        if (strcasecmp(data_type[i % columnCount], "TINYINT") == 0) {
            pstr += sprintf(pstr, ",%d", rand_tinyint() );
        } else if (strcasecmp(data_type[i % columnCount], "SMALLINT") == 0) {
            pstr += sprintf(pstr, ",%d", rand_smallint());
        } else if (strcasecmp(data_type[i % columnCount], "INT") == 0) {
            pstr += sprintf(pstr, ",%d", rand_int());
        } else if (strcasecmp(data_type[i % columnCount], "BIGINT") == 0) {
5927
            pstr += sprintf(pstr, ",%"PRId64"", rand_bigint());
5928
        } else if (strcasecmp(data_type[i % columnCount], "TIMESTAMP") == 0) {
5929
            pstr += sprintf(pstr, ",%"PRId64"", rand_bigint());
5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940
        } else if (strcasecmp(data_type[i % columnCount], "FLOAT") == 0) {
            pstr += sprintf(pstr, ",%10.4f", rand_float());
        } else if (strcasecmp(data_type[i % columnCount], "DOUBLE") == 0) {
            double t = rand_double();
            pstr += sprintf(pstr, ",%20.8f", t);
        } else if (strcasecmp(data_type[i % columnCount], "BOOL") == 0) {
            bool b = rand_bool() & 1;
            pstr += sprintf(pstr, ",%s", b ? "true" : "false");
        } else if (strcasecmp(data_type[i % columnCount], "BINARY") == 0) {
            char *s = malloc(lenOfBinary + 1);
            if (s == NULL) {
5941
                errorPrint2("%s() LN%d, memory allocation %d bytes failed\n",
5942
                        __func__, __LINE__, lenOfBinary + 1);
5943
                exit(EXIT_FAILURE);
5944 5945 5946 5947 5948 5949 5950
            }
            rand_string(s, lenOfBinary);
            pstr += sprintf(pstr, ",\"%s\"", s);
            free(s);
        } else if (strcasecmp(data_type[i % columnCount], "NCHAR") == 0) {
            char *s = malloc(lenOfBinary + 1);
            if (s == NULL) {
5951
                errorPrint2("%s() LN%d, memory allocation %d bytes failed\n",
5952
                        __func__, __LINE__, lenOfBinary + 1);
5953
                exit(EXIT_FAILURE);
5954 5955 5956 5957 5958
            }
            rand_string(s, lenOfBinary);
            pstr += sprintf(pstr, ",\"%s\"", s);
            free(s);
        }
5959

5960
        if (strlen(recBuf) > MAX_DATA_SIZE) {
5961
            ERROR_EXIT("column length too long, abort");
5962
        }
5963 5964
    }

5965
    pstr += sprintf(pstr, ")");
5966

5967
    verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);
5968

5969
    return (int32_t)strlen(recBuf);
5970 5971
}

5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045
static int generateSampleMemoryFromRand(SSuperTable *stbInfo)
{
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);

    char *buff = malloc(stbInfo->lenOfOneRow);
    if (NULL == buff) {
        errorPrint2("%s() LN%d, memory allocation %"PRId64" bytes failed\n",
                __func__, __LINE__, stbInfo->lenOfOneRow);
        exit(EXIT_FAILURE);
    }

    for (int i=0; i < MAX_SAMPLES_ONCE_FROM_FILE; i++) {
        uint64_t pos = 0;
        memset(buff, 0, stbInfo->lenOfOneRow);

        for (int c = 0; c < stbInfo->columnCount; c++) {
            char *tmp;
            if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "BINARY", strlen("BINARY"))) {
                rand_string(data, stbInfo->columns[c].dataLen);
                pos += sprintf(buff + pos, "%s,", data);
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "NCHAR", strlen("NCHAR"))) {
                rand_string(data, stbInfo->columns[c].dataLen);
                pos += sprintf(buff + pos, "%s,", data);
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "INT", strlen("INT"))) {
                if ((g_args.demo_mode) && (c == 1)) {
                    tmp = demo_voltage_int_str();
                } else {
                    tmp = rand_int_str();
                }
                pos += sprintf(buff + pos, "%s,", tmp);
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "BIGINT", strlen("BIGINT"))) {
                pos += sprintf(buff + pos, "%s,", rand_bigint_str());
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "FLOAT", strlen("FLOAT"))) {
                if (g_args.demo_mode) {
                    if (c == 0) {
                        tmp = demo_current_float_str();
                    } else {
                        tmp = demo_phase_float_str();
                    }
                } else {
                    tmp = rand_float_str();
                }
                pos += sprintf(buff + pos, "%s,", tmp);
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "DOUBLE", strlen("DOUBLE"))) {
                pos += sprintf(buff + pos, "%s,", rand_double_str());
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "SMALLINT", strlen("SMALLINT"))) {
                pos += sprintf(buff + pos, "%s,", rand_smallint_str());
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "TINYINT", strlen("TINYINT"))) {
                pos += sprintf(buff + pos, "%s,", rand_tinyint_str());
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "BOOL", strlen("BOOL"))) {
                pos += sprintf(buff + pos, "%s,", rand_bool_str());
            } else if (0 == strncasecmp(stbInfo->columns[c].dataType,
                        "TIMESTAMP", strlen("TIMESTAMP"))) {
                pos += sprintf(buff + pos, "%s,", rand_bigint_str());
            }
        }
        *(buff + pos - 1) = 0;
        memcpy(stbInfo->sampleDataBuf + i * stbInfo->lenOfOneRow, buff, pos);
    }

    free(buff);
    return 0;
}

6046
static int prepareSampleDataForSTable(SSuperTable *stbInfo) {
6047

6048
    stbInfo->sampleDataBuf = calloc(
6049
            stbInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
6050
    if (NULL == stbInfo->sampleDataBuf) {
6051
        errorPrint2("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
6052
                __func__, __LINE__,
6053
                stbInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
6054 6055 6056
                strerror(errno));
        return -1;
    }
6057

6058 6059 6060 6061 6062
    int ret;
    if (0 == strncasecmp(stbInfo->dataSource, "sample", strlen("sample"))) 
        ret = readSampleFromCsvFileToMem(stbInfo);
    else
        ret = generateSampleMemoryFromRand(stbInfo);
6063

6064
    if (0 != ret) {
6065
        errorPrint2("%s() LN%d, read sample from csv file failed.\n",
6066
                __func__, __LINE__);
6067
        tmfree(stbInfo->sampleDataBuf);
6068
        stbInfo->sampleDataBuf = NULL;
6069 6070
        return -1;
    }
6071

6072
    return 0;
6073 6074
}

6075
static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k)
6076
{
6077
    int32_t affectedRows;
6078
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
6079

6080
    uint16_t iface;
6081 6082
    if (stbInfo)
        iface = stbInfo->iface;
6083 6084 6085 6086 6087 6088
    else {
        if (g_args.iface == INTERFACE_BUT)
            iface = TAOSC_IFACE;
        else
            iface = g_args.iface;
    }
6089 6090 6091

    debugPrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__,
6092 6093
            (iface==TAOSC_IFACE)?
            "taosc":(iface==REST_IFACE)?"rest":"stmt");
6094 6095 6096

    switch(iface) {
        case TAOSC_IFACE:
6097 6098 6099
            verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
                    __func__, __LINE__, pThreadInfo->buffer);

6100 6101 6102 6103 6104 6105
            affectedRows = queryDbExec(
                    pThreadInfo->taos,
                    pThreadInfo->buffer, INSERT_TYPE, false);
            break;

        case REST_IFACE:
6106 6107 6108
            verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
                    __func__, __LINE__, pThreadInfo->buffer);

6109
            if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
6110
                        pThreadInfo->buffer, pThreadInfo)) {
6111 6112 6113 6114 6115 6116 6117 6118 6119
                affectedRows = -1;
                printf("========restful return fail, threadID[%d]\n",
                        pThreadInfo->threadID);
            } else {
                affectedRows = k;
            }
            break;

        case STMT_IFACE:
6120 6121
            debugPrint("%s() LN%d, stmt=%p",
                    __func__, __LINE__, pThreadInfo->stmt);
6122
            if (0 != taos_stmt_execute(pThreadInfo->stmt)) {
6123
                errorPrint2("%s() LN%d, failied to execute insert statement. reason: %s\n",
6124
                        __func__, __LINE__, taos_stmt_errstr(pThreadInfo->stmt));
6125 6126

                fprintf(stderr, "\n\033[31m === Please reduce batch number if WAL size exceeds limit. ===\033[0m\n\n");
6127
                exit(EXIT_FAILURE);
6128 6129 6130 6131 6132
            }
            affectedRows = k;
            break;

        default:
6133
            errorPrint2("%s() LN%d: unknown insert mode: %d\n",
6134
                    __func__, __LINE__, stbInfo->iface);
6135
            affectedRows = 0;
6136
    }
6137

6138
    return affectedRows;
6139 6140
}

6141 6142
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
6143
{
6144 6145 6146 6147
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
    if (stbInfo) {
        if (AUTO_CREATE_SUBTBL != stbInfo->autoCreateTable) {
            if (stbInfo->childTblLimit > 0) {
6148
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
6149 6150
                        stbInfo->childTblName +
                        (tableSeq - stbInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
6151 6152 6153 6154 6155 6156
            } else {
                verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
                        pThreadInfo->threadID, __func__, __LINE__,
                        pThreadInfo->start_table_from,
                        pThreadInfo->ntables, tableSeq);
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
6157
                        stbInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
6158 6159 6160
            }
        } else {
            snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
6161
                    stbInfo->childTblPrefix, tableSeq);
6162
        }
6163
    } else {
6164 6165
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                g_args.tb_prefix, tableSeq);
6166 6167 6168
    }
}

6169
static int32_t generateDataTailWithoutStb(
6170
        uint32_t batch, char* buffer,
6171
        int64_t remainderBufLen, int64_t insertRows,
6172
        uint64_t recordFrom, int64_t startTime,
6173
        /* int64_t *pSamplePos, */int64_t *dataLen) {
6174

6175 6176
    uint64_t len = 0;
    char *pstr = buffer;
6177

6178
    verbosePrint("%s() LN%d batch=%d\n", __func__, __LINE__, batch);
6179

6180 6181
    int32_t k = 0;
    for (k = 0; k < batch;) {
6182
        char *data = pstr;
6183
        memset(data, 0, MAX_DATA_SIZE);
6184

6185
        int64_t retLen = 0;
6186

6187
        char **data_type = g_args.datatype;
6188
        int lenOfBinary = g_args.binwidth;
6189

6190 6191 6192
        if (g_args.disorderRatio) {
            retLen = generateData(data, data_type,
                    startTime + getTSRandTail(
6193
                        g_args.timestamp_step, k,
6194 6195 6196 6197 6198
                        g_args.disorderRatio,
                        g_args.disorderRange),
                    lenOfBinary);
        } else {
            retLen = generateData(data, data_type,
6199
                    startTime + g_args.timestamp_step * k,
6200 6201
                    lenOfBinary);
        }
6202

6203 6204
        if (len > remainderBufLen)
            break;
6205

6206
        pstr += retLen;
6207 6208 6209
        k++;
        len += retLen;
        remainderBufLen -= retLen;
6210

6211 6212
        verbosePrint("%s() LN%d len=%"PRIu64" k=%d \nbuffer=%s\n",
                __func__, __LINE__, len, k, buffer);
6213

6214
        recordFrom ++;
6215

6216 6217 6218
        if (recordFrom >= insertRows) {
            break;
        }
6219
    }
6220

6221 6222
    *dataLen = len;
    return k;
6223 6224
}

6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
        int disorderRatio, int disorderRange)
{
    int64_t randTail = timeStampStep * seq;
    if (disorderRatio > 0) {
        int rand_num = taosRandom() % 100;
        if(rand_num < disorderRatio) {
            randTail = (randTail +
                    (taosRandom() % disorderRange + 1)) * (-1);
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
    }

    return randTail;
}

static int32_t generateStbDataTail(
6242
        SSuperTable* stbInfo,
6243
        uint32_t batch, char* buffer,
6244
        int64_t remainderBufLen, int64_t insertRows,
6245
        uint64_t recordFrom, int64_t startTime,
6246
        int64_t *pSamplePos, int64_t *dataLen) {
6247
    uint64_t len = 0;
6248

6249
    char *pstr = buffer;
6250

6251
    bool tsRand;
6252
    if (0 == strncasecmp(stbInfo->dataSource, "rand", strlen("rand"))) {
6253 6254 6255 6256 6257 6258
        tsRand = true;
    } else {
        tsRand = false;
    }
    verbosePrint("%s() LN%d batch=%u buflen=%"PRId64"\n",
            __func__, __LINE__, batch, remainderBufLen);
6259

6260 6261
    int32_t k;
    for (k = 0; k < batch;) {
6262
        char *data = pstr;
6263

6264
        int64_t lenOfRow = 0;
6265

6266
        if (tsRand) {
6267 6268
            if (stbInfo->disorderRatio > 0) {
                lenOfRow = generateStbRowData(stbInfo, data,
6269
                        remainderBufLen,
6270
                        startTime + getTSRandTail(
6271 6272 6273
                            stbInfo->timeStampStep, k,
                            stbInfo->disorderRatio,
                            stbInfo->disorderRange)
6274 6275
                        );
            } else {
6276
                lenOfRow = generateStbRowData(stbInfo, data,
6277
                        remainderBufLen,
6278
                        startTime + stbInfo->timeStampStep * k
6279 6280 6281 6282 6283 6284
                        );
            }
        } else {
            lenOfRow = getRowDataFromSample(
                    data,
                    (remainderBufLen < MAX_DATA_SIZE)?remainderBufLen:MAX_DATA_SIZE,
6285 6286
                    startTime + stbInfo->timeStampStep * k,
                    stbInfo,
6287 6288
                    pSamplePos);
        }
6289

6290 6291 6292 6293
        if (lenOfRow == 0) {
            data[0] = '\0';
            break;
        }
6294 6295 6296
        if ((lenOfRow + 1) > remainderBufLen) {
            break;
        }
6297

6298
        pstr += lenOfRow;
6299 6300 6301
        k++;
        len += lenOfRow;
        remainderBufLen -= lenOfRow;
6302

6303 6304
        verbosePrint("%s() LN%d len=%"PRIu64" k=%u \nbuffer=%s\n",
                __func__, __LINE__, len, k, buffer);
6305

6306
        recordFrom ++;
6307

6308 6309 6310
        if (recordFrom >= insertRows) {
            break;
        }
6311
    }
6312

6313 6314
    *dataLen = len;
    return k;
6315
}
6316

6317 6318 6319

static int generateSQLHeadWithoutStb(char *tableName,
        char *dbName,
6320
        char *buffer, int remainderBufLen)
6321
{
6322
    int len;
6323

6324
    char headBuf[HEAD_BUFF_LEN];
6325

6326 6327 6328 6329 6330 6331
    len = snprintf(
            headBuf,
            HEAD_BUFF_LEN,
            "%s.%s values",
            dbName,
            tableName);
6332

6333 6334
    if (len > remainderBufLen)
        return -1;
6335

6336
    tstrncpy(buffer, headBuf, len + 1);
6337

6338
    return len;
6339 6340 6341
}

static int generateStbSQLHead(
6342
        SSuperTable* stbInfo,
6343
        char *tableName, int64_t tableSeq,
6344 6345 6346
        char *dbName,
        char *buffer, int remainderBufLen)
{
6347
    int len;
6348

6349
    char headBuf[HEAD_BUFF_LEN];
6350

6351
    if (AUTO_CREATE_SUBTBL == stbInfo->autoCreateTable) {
6352
        char* tagsValBuf = NULL;
6353 6354
        if (0 == stbInfo->tagSource) {
            tagsValBuf = generateTagValuesForStb(stbInfo, tableSeq);
6355
        } else {
6356
            tagsValBuf = getTagValueFromTagSample(
6357 6358
                    stbInfo,
                    tableSeq % stbInfo->tagSampleCount);
6359 6360
        }
        if (NULL == tagsValBuf) {
6361
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
6362 6363 6364
                    __func__, __LINE__);
            return -1;
        }
6365

6366 6367 6368 6369 6370 6371 6372
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s using %s.%s TAGS%s values",
                dbName,
                tableName,
                dbName,
6373
                stbInfo->sTblName,
6374 6375
                tagsValBuf);
        tmfree(tagsValBuf);
6376
    } else if (TBL_ALREADY_EXISTS == stbInfo->childTblExists) {
6377 6378 6379 6380 6381 6382
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s values",
                dbName,
                tableName);
6383
    } else {
6384 6385 6386 6387 6388 6389 6390
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s values",
                dbName,
                tableName);
    }
6391

6392 6393
    if (len > remainderBufLen)
        return -1;
6394

6395
    tstrncpy(buffer, headBuf, len + 1);
6396

6397
    return len;
6398 6399
}

6400
static int32_t generateStbInterlaceData(
6401
        threadInfo *pThreadInfo,
6402 6403 6404
        char *tableName, uint32_t batchPerTbl,
        uint64_t i,
        uint32_t batchPerTblTimes,
6405
        uint64_t tableSeq,
6406
        char *buffer,
6407
        int64_t insertRows,
6408
        int64_t startTime,
6409
        uint64_t *pRemainderBufLen)
6410
{
6411 6412
    assert(buffer);
    char *pstr = buffer;
6413

6414
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
6415
    int headLen = generateStbSQLHead(
6416
            stbInfo,
6417 6418
            tableName, tableSeq, pThreadInfo->db_name,
            pstr, *pRemainderBufLen);
6419

6420 6421 6422 6423 6424
    if (headLen <= 0) {
        return 0;
    }
    // generate data buffer
    verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
6425
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
6426

6427 6428
    pstr += headLen;
    *pRemainderBufLen -= headLen;
6429

6430
    int64_t dataLen = 0;
6431

6432
    verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%u batchPerTbl = %u\n",
6433 6434
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
6435

6436
    if (0 == strncasecmp(stbInfo->startTimestamp, "now", 3)) {
6437 6438
        startTime = taosGetTimestamp(pThreadInfo->time_precision);
    }
6439

6440
    int32_t k = generateStbDataTail(
6441
            stbInfo,
6442 6443 6444
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &(pThreadInfo->samplePos), &dataLen);
6445

6446 6447 6448 6449 6450 6451 6452 6453 6454 6455
    if (k == batchPerTbl) {
        pstr += dataLen;
        *pRemainderBufLen -= dataLen;
    } else {
        debugPrint("%s() LN%d, generated data tail: %u, not equal batch per table: %u\n",
                __func__, __LINE__, k, batchPerTbl);
        pstr -= headLen;
        pstr[0] = '\0';
        k = 0;
    }
6456

6457
    return k;
6458 6459 6460
}

static int64_t generateInterlaceDataWithoutStb(
6461
        char *tableName, uint32_t batch,
6462 6463 6464
        uint64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
6465
        int64_t startTime,
6466 6467
        uint64_t *pRemainderBufLen)
{
6468 6469
    assert(buffer);
    char *pstr = buffer;
6470

6471 6472
    int headLen = generateSQLHeadWithoutStb(
            tableName, dbName,
6473 6474
            pstr, *pRemainderBufLen);

6475 6476 6477
    if (headLen <= 0) {
        return 0;
    }
6478

6479 6480
    pstr += headLen;
    *pRemainderBufLen -= headLen;
6481

6482
    int64_t dataLen = 0;
6483

6484
    int32_t k = generateDataTailWithoutStb(
6485
            batch, pstr, *pRemainderBufLen, insertRows, 0,
6486
            startTime,
6487
            &dataLen);
6488

6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500
    if (k == batch) {
        pstr += dataLen;
        *pRemainderBufLen -= dataLen;
    } else {
        debugPrint("%s() LN%d, generated data tail: %d, not equal batch per table: %u\n",
                __func__, __LINE__, k, batch);
        pstr -= headLen;
        pstr[0] = '\0';
        k = 0;
    }

    return k;
6501 6502
}

6503 6504 6505 6506 6507 6508 6509 6510 6511
static int32_t prepareStmtBindArrayByType(
        TAOS_BIND *bind,
        char *dataType, int32_t dataLen,
        int32_t timePrec,
        char *value)
{
    if (0 == strncasecmp(dataType,
                "BINARY", strlen("BINARY"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
6512
            errorPrint2("binary length overflow, max size:%u\n",
6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_binary;

        bind->buffer_type = TSDB_DATA_TYPE_BINARY;
        if (value) {
            bind_binary = calloc(1, strlen(value) + 1);
            strncpy(bind_binary, value, strlen(value));
            bind->buffer_length = strlen(bind_binary);
        } else {
            bind_binary = calloc(1, dataLen + 1);
            rand_string(bind_binary, dataLen);
            bind->buffer_length = dataLen;
        }

        bind->length = &bind->buffer_length;
        bind->buffer = bind_binary;
        bind->is_null = NULL;
    } else if (0 == strncasecmp(dataType,
                "NCHAR", strlen("NCHAR"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
6535
            errorPrint2("nchar length overflow, max size:%u\n",
6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_nchar;

        bind->buffer_type = TSDB_DATA_TYPE_NCHAR;
        if (value) {
            bind_nchar = calloc(1, strlen(value) + 1);
            strncpy(bind_nchar, value, strlen(value));
        } else {
            bind_nchar = calloc(1, dataLen + 1);
            rand_string(bind_nchar, dataLen);
        }

        bind->buffer_length = strlen(bind_nchar);
        bind->buffer = bind_nchar;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    } else if (0 == strncasecmp(dataType,
                "INT", strlen("INT"))) {
        int32_t *bind_int = malloc(sizeof(int32_t));
6557
        assert(bind_int);
6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571

        if (value) {
            *bind_int = atoi(value);
        } else {
            *bind_int = rand_int();
        }
        bind->buffer_type = TSDB_DATA_TYPE_INT;
        bind->buffer_length = sizeof(int32_t);
        bind->buffer = bind_int;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    } else if (0 == strncasecmp(dataType,
                "BIGINT", strlen("BIGINT"))) {
        int64_t *bind_bigint = malloc(sizeof(int64_t));
6572
        assert(bind_bigint);
6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586

        if (value) {
            *bind_bigint = atoll(value);
        } else {
            *bind_bigint = rand_bigint();
        }
        bind->buffer_type = TSDB_DATA_TYPE_BIGINT;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_bigint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else if (0 == strncasecmp(dataType,
                "FLOAT", strlen("FLOAT"))) {
        float *bind_float = malloc(sizeof(float));
6587
        assert(bind_float);
6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601

        if (value) {
            *bind_float = (float)atof(value);
        } else {
            *bind_float = rand_float();
        }
        bind->buffer_type = TSDB_DATA_TYPE_FLOAT;
        bind->buffer_length = sizeof(float);
        bind->buffer = bind_float;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else if (0 == strncasecmp(dataType,
                "DOUBLE", strlen("DOUBLE"))) {
        double *bind_double = malloc(sizeof(double));
6602
        assert(bind_double);
6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616

        if (value) {
            *bind_double = atof(value);
        } else {
            *bind_double = rand_double();
        }
        bind->buffer_type = TSDB_DATA_TYPE_DOUBLE;
        bind->buffer_length = sizeof(double);
        bind->buffer = bind_double;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else if (0 == strncasecmp(dataType,
                "SMALLINT", strlen("SMALLINT"))) {
        int16_t *bind_smallint = malloc(sizeof(int16_t));
6617
        assert(bind_smallint);
6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631

        if (value) {
            *bind_smallint = (int16_t)atoi(value);
        } else {
            *bind_smallint = rand_smallint();
        }
        bind->buffer_type = TSDB_DATA_TYPE_SMALLINT;
        bind->buffer_length = sizeof(int16_t);
        bind->buffer = bind_smallint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else if (0 == strncasecmp(dataType,
                "TINYINT", strlen("TINYINT"))) {
        int8_t *bind_tinyint = malloc(sizeof(int8_t));
6632
        assert(bind_tinyint);
6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646

        if (value) {
            *bind_tinyint = (int8_t)atoi(value);
        } else {
            *bind_tinyint = rand_tinyint();
        }
        bind->buffer_type = TSDB_DATA_TYPE_TINYINT;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_tinyint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else if (0 == strncasecmp(dataType,
                "BOOL", strlen("BOOL"))) {
        int8_t *bind_bool = malloc(sizeof(int8_t));
6647
        assert(bind_bool);
6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666

        if (value) {
            if (strncasecmp(value, "true", 4)) {
                *bind_bool = true;
            } else {
                *bind_bool = false;
            }
        } else {
            *bind_bool = rand_bool();
        }
        bind->buffer_type = TSDB_DATA_TYPE_BOOL;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_bool;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

    }  else if (0 == strncasecmp(dataType,
                "TIMESTAMP", strlen("TIMESTAMP"))) {
        int64_t *bind_ts2 = malloc(sizeof(int64_t));
6667
        assert(bind_ts2);
6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681

        if (value) {
            if (strchr(value, ':') && strchr(value, '-')) {
                int i = 0;
                while(value[i] != '\0') {
                    if (value[i] == '\"' || value[i] == '\'') {
                        value[i] = ' ';
                    }
                    i++;
                }
                int64_t tmpEpoch;
                if (TSDB_CODE_SUCCESS != taosParseTime(
                            value, &tmpEpoch, strlen(value),
                            timePrec, 0)) {
6682
                    free(bind_ts2);
6683
                    errorPrint2("Input %s, time format error!\n", value);
6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698
                    return -1;
                }
                *bind_ts2 = tmpEpoch;
            } else {
                *bind_ts2 = atoll(value);
            }
        } else {
            *bind_ts2 = rand_bigint();
        }
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts2;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
    }  else {
6699
        errorPrint2("Not support data type: %s\n", dataType);
6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711
        return -1;
    }

    return 0;
}

static int32_t prepareStmtBindArrayByTypeForRand(
        TAOS_BIND *bind,
        char *dataType, int32_t dataLen,
        int32_t timePrec,
        char **ptr,
        char *value)
6712 6713 6714 6715
{
    if (0 == strncasecmp(dataType,
                "BINARY", strlen("BINARY"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
6716
            errorPrint2("binary length overflow, max size:%u\n",
6717 6718 6719 6720 6721 6722
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_binary = (char *)*ptr;

        bind->buffer_type = TSDB_DATA_TYPE_BINARY;
6723 6724 6725 6726 6727 6728 6729 6730
        if (value) {
            strncpy(bind_binary, value, strlen(value));
            bind->buffer_length = strlen(bind_binary);
        } else {
            rand_string(bind_binary, dataLen);
            bind->buffer_length = dataLen;
        }

6731
        bind->length = &bind->buffer_length;
6732
        bind->buffer = bind_binary;
6733 6734 6735 6736 6737 6738
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "NCHAR", strlen("NCHAR"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
6739
            errorPrint2("nchar length overflow, max size: %u\n",
6740 6741 6742 6743 6744 6745
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_nchar = (char *)*ptr;

        bind->buffer_type = TSDB_DATA_TYPE_NCHAR;
6746 6747 6748 6749 6750 6751
        if (value) {
            strncpy(bind_nchar, value, strlen(value));
        } else {
            rand_string(bind_nchar, dataLen);
        }

6752 6753 6754 6755 6756 6757 6758 6759 6760 6761
        bind->buffer_length = strlen(bind_nchar);
        bind->buffer = bind_nchar;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "INT", strlen("INT"))) {
        int32_t *bind_int = (int32_t *)*ptr;

6762 6763 6764 6765 6766
        if (value) {
            *bind_int = atoi(value);
        } else {
            *bind_int = rand_int();
        }
6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777
        bind->buffer_type = TSDB_DATA_TYPE_INT;
        bind->buffer_length = sizeof(int32_t);
        bind->buffer = bind_int;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "BIGINT", strlen("BIGINT"))) {
        int64_t *bind_bigint = (int64_t *)*ptr;

6778 6779 6780 6781 6782
        if (value) {
            *bind_bigint = atoll(value);
        } else {
            *bind_bigint = rand_bigint();
        }
6783 6784 6785 6786 6787 6788 6789 6790 6791
        bind->buffer_type = TSDB_DATA_TYPE_BIGINT;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_bigint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "FLOAT", strlen("FLOAT"))) {
6792
        float *bind_float = (float *)*ptr;
6793

6794 6795 6796 6797 6798
        if (value) {
            *bind_float = (float)atof(value);
        } else {
            *bind_float = rand_float();
        }
6799 6800 6801 6802 6803 6804 6805 6806 6807
        bind->buffer_type = TSDB_DATA_TYPE_FLOAT;
        bind->buffer_length = sizeof(float);
        bind->buffer = bind_float;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "DOUBLE", strlen("DOUBLE"))) {
6808
        double *bind_double = (double *)*ptr;
6809

6810 6811 6812 6813 6814
        if (value) {
            *bind_double = atof(value);
        } else {
            *bind_double = rand_double();
        }
6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825
        bind->buffer_type = TSDB_DATA_TYPE_DOUBLE;
        bind->buffer_length = sizeof(double);
        bind->buffer = bind_double;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "SMALLINT", strlen("SMALLINT"))) {
        int16_t *bind_smallint = (int16_t *)*ptr;

6826 6827 6828 6829 6830
        if (value) {
            *bind_smallint = (int16_t)atoi(value);
        } else {
            *bind_smallint = rand_smallint();
        }
6831 6832 6833 6834 6835 6836 6837 6838 6839
        bind->buffer_type = TSDB_DATA_TYPE_SMALLINT;
        bind->buffer_length = sizeof(int16_t);
        bind->buffer = bind_smallint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TINYINT", strlen("TINYINT"))) {
6840
        int8_t *bind_tinyint = (int8_t *)*ptr;
6841

6842 6843 6844 6845 6846
        if (value) {
            *bind_tinyint = (int8_t)atoi(value);
        } else {
            *bind_tinyint = rand_tinyint();
        }
6847 6848 6849 6850 6851
        bind->buffer_type = TSDB_DATA_TYPE_TINYINT;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_tinyint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
6852

6853 6854 6855
        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "BOOL", strlen("BOOL"))) {
6856
        int8_t *bind_bool = (int8_t *)*ptr;
6857

6858 6859 6860 6861 6862 6863 6864 6865 6866
        if (value) {
            if (strncasecmp(value, "true", 4)) {
                *bind_bool = true;
            } else {
                *bind_bool = false;
            }
        } else {
            *bind_bool = rand_bool();
        }
6867 6868 6869 6870 6871 6872 6873 6874 6875
        bind->buffer_type = TSDB_DATA_TYPE_BOOL;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_bool;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TIMESTAMP", strlen("TIMESTAMP"))) {
6876
        int64_t *bind_ts2 = (int64_t *)*ptr;
6877

6878
        if (value) {
6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890
            if (strchr(value, ':') && strchr(value, '-')) {
                int i = 0;
                while(value[i] != '\0') {
                    if (value[i] == '\"' || value[i] == '\'') {
                        value[i] = ' ';
                    }
                    i++;
                }
                int64_t tmpEpoch;
                if (TSDB_CODE_SUCCESS != taosParseTime(
                            value, &tmpEpoch, strlen(value),
                            timePrec, 0)) {
6891
                    errorPrint2("Input %s, time format error!\n", value);
6892 6893 6894 6895 6896 6897
                    return -1;
                }
                *bind_ts2 = tmpEpoch;
            } else {
                *bind_ts2 = atoll(value);
            }
6898 6899 6900
        } else {
            *bind_ts2 = rand_bigint();
        }
6901 6902 6903 6904 6905 6906 6907 6908
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts2;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else {
6909
        errorPrint2("No support data type: %s\n", dataType);
6910 6911 6912 6913 6914 6915 6916
        return -1;
    }

    return 0;
}

static int32_t prepareStmtWithoutStb(
6917
        threadInfo *pThreadInfo,
6918 6919 6920 6921 6922
        char *tableName,
        uint32_t batch,
        int64_t insertRows,
        int64_t recordFrom,
        int64_t startTime)
6923
{
6924
    TAOS_STMT *stmt = pThreadInfo->stmt;
6925 6926
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
6927
        errorPrint2("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
6928
                tableName, ret, taos_stmt_errstr(stmt));
6929 6930 6931 6932
        return ret;
    }

    char **data_type = g_args.datatype;
6933

6934 6935
    char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.num_of_CPR + 1));
    if (bindArray == NULL) {
6936
        errorPrint2("Failed to allocate %d bind params\n",
6937 6938
                (g_args.num_of_CPR + 1));
        return -1;
6939 6940
    }

6941 6942 6943 6944 6945 6946
    int32_t k = 0;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */

        TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0);

6947
        int64_t *bind_ts = pThreadInfo->bind_ts;
6948 6949

        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
6950 6951 6952

        if (g_args.disorderRatio) {
            *bind_ts = startTime + getTSRandTail(
6953
                    g_args.timestamp_step, k,
6954 6955 6956
                    g_args.disorderRatio,
                    g_args.disorderRange);
        } else {
6957
            *bind_ts = startTime + g_args.timestamp_step * k;
6958
        }
6959 6960 6961 6962 6963 6964
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        for (int i = 0; i < g_args.num_of_CPR; i ++) {
6965 6966
            bind = (TAOS_BIND *)((char *)bindArray
                    + (sizeof(TAOS_BIND) * (i + 1)));
6967 6968 6969
            if ( -1 == prepareStmtBindArrayByType(
                        bind,
                        data_type[i],
6970
                        g_args.binwidth,
6971 6972
                        pThreadInfo->time_precision,
                        NULL)) {
6973 6974 6975
                return -1;
            }
        }
6976
        if (0 != taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray)) {
6977
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
6978 6979 6980
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            break;
        }
6981
        // if msg > 3MB, break
6982
        if (0 != taos_stmt_add_batch(stmt)) {
6983
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
6984 6985 6986
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            break;
        }
6987 6988 6989 6990 6991 6992 6993 6994

        k++;
        recordFrom ++;
        if (recordFrom >= insertRows) {
            break;
        }
    }

6995
    free(bindArray);
6996 6997 6998
    return k;
}

6999 7000 7001 7002 7003
static int32_t prepareStbStmtBindTag(
        char *bindArray, SSuperTable *stbInfo,
        char *tagsVal,
        int32_t timePrec)
{
7004
    char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.binwidth);
7005
    if (bindBuffer == NULL) {
7006
        errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n",
7007
                __func__, __LINE__, DOUBLE_BUFF_LEN);
7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032
        return -1;
    }

    TAOS_BIND *tag;

    for (int t = 0; t < stbInfo->tagCount; t ++) {
        tag = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * t));
        if ( -1 == prepareStmtBindArrayByType(
                    tag,
                    stbInfo->tags[t].dataType,
                    stbInfo->tags[t].dataLen,
                    timePrec,
                    NULL)) {
            free(bindBuffer);
            return -1;
        }
    }

    free(bindBuffer);
    return 0;
}

static int32_t prepareStbStmtBindRand(
        int64_t *ts,
        char *bindArray, SSuperTable *stbInfo,
7033
        int64_t startTime, int32_t recSeq,
7034
        int32_t timePrec)
7035
{
7036
    char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.binwidth);
7037
    if (bindBuffer == NULL) {
7038
        errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n",
7039
                __func__, __LINE__, DOUBLE_BUFF_LEN);
7040 7041 7042 7043 7044 7045 7046 7047 7048
        return -1;
    }

    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);
    char *ptr = data;

    TAOS_BIND *bind;

7049 7050
    for (int i = 0; i < stbInfo->columnCount + 1; i ++) {
        bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * i));
7051

7052 7053
        if (i == 0) {
            int64_t *bind_ts = ts;
7054

7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080
            bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
            if (stbInfo->disorderRatio) {
                *bind_ts = startTime + getTSRandTail(
                        stbInfo->timeStampStep, recSeq,
                        stbInfo->disorderRatio,
                        stbInfo->disorderRange);
            } else {
                *bind_ts = startTime + stbInfo->timeStampStep * recSeq;
            }
            bind->buffer_length = sizeof(int64_t);
            bind->buffer = bind_ts;
            bind->length = &bind->buffer_length;
            bind->is_null = NULL;

            ptr += bind->buffer_length;
        } else if ( -1 == prepareStmtBindArrayByTypeForRand(
                    bind,
                    stbInfo->columns[i-1].dataType,
                    stbInfo->columns[i-1].dataLen,
                    timePrec,
                    &ptr,
                    NULL)) {
            tmfree(bindBuffer);
            return -1;
        }
    }
7081

7082 7083 7084
    tmfree(bindBuffer);
    return 0;
}
7085

7086 7087
static int32_t prepareStbStmtBindStartTime(
        char *tableName,
7088 7089 7090
        int64_t *ts,
        char *bindArray, SSuperTable *stbInfo,
        int64_t startTime, int32_t recSeq,
7091
        int32_t timePrec)
7092 7093
{
    TAOS_BIND *bind;
7094

7095
    bind = (TAOS_BIND *)bindArray;
7096

7097
    int64_t *bind_ts = ts;
7098

7099 7100 7101 7102 7103 7104 7105 7106
    bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
    if (stbInfo->disorderRatio) {
        *bind_ts = startTime + getTSRandTail(
                stbInfo->timeStampStep, recSeq,
                stbInfo->disorderRatio,
                stbInfo->disorderRange);
    } else {
        *bind_ts = startTime + stbInfo->timeStampStep * recSeq;
7107
    }
7108 7109 7110 7111

    verbosePrint("%s() LN%d, tableName: %s, bind_ts=%"PRId64"\n",
            __func__, __LINE__, tableName, *bind_ts);

7112 7113 7114 7115
    bind->buffer_length = sizeof(int64_t);
    bind->buffer = bind_ts;
    bind->length = &bind->buffer_length;
    bind->is_null = NULL;
7116 7117 7118 7119

    return 0;
}

7120
UNUSED_FUNC static int32_t prepareStbStmtRand(
7121
        threadInfo *pThreadInfo,
7122 7123 7124
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
7125 7126
        uint64_t insertRows,
        uint64_t recordFrom,
7127
        int64_t startTime)
7128
{
7129
    int ret;
7130 7131
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    TAOS_STMT *stmt = pThreadInfo->stmt;
7132

7133 7134
    if (AUTO_CREATE_SUBTBL == stbInfo->autoCreateTable) {
        char* tagsValBuf = NULL;
7135

7136 7137 7138 7139 7140 7141 7142
        if (0 == stbInfo->tagSource) {
            tagsValBuf = generateTagValuesForStb(stbInfo, tableSeq);
        } else {
            tagsValBuf = getTagValueFromTagSample(
                    stbInfo,
                    tableSeq % stbInfo->tagSampleCount);
        }
7143

7144
        if (NULL == tagsValBuf) {
7145
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
7146 7147 7148
                    __func__, __LINE__);
            return -1;
        }
7149

7150 7151 7152
        char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount);
        if (NULL == tagsArray) {
            tmfree(tagsValBuf);
7153
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
7154 7155 7156
                    __func__, __LINE__);
            return -1;
        }
7157

7158 7159 7160
        if (-1 == prepareStbStmtBindTag(
                    tagsArray, stbInfo, tagsValBuf, pThreadInfo->time_precision
                    /* is tag */)) {
7161 7162
            tmfree(tagsValBuf);
            tmfree(tagsArray);
7163
            return -1;
7164 7165
        }

7166
        ret = taos_stmt_set_tbname_tags(stmt, tableName, (TAOS_BIND *)tagsArray);
7167

7168
        tmfree(tagsValBuf);
7169
        tmfree(tagsArray);
7170 7171

        if (0 != ret) {
7172
            errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n",
7173 7174 7175
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
7176 7177
    } else {
        ret = taos_stmt_set_tbname(stmt, tableName);
7178
        if (0 != ret) {
7179
            errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n",
7180 7181 7182
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
7183
    }
7184

7185 7186
    char *bindArray = calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1));
    if (bindArray == NULL) {
7187
        errorPrint2("%s() LN%d, Failed to allocate %d bind params\n",
7188 7189 7190 7191 7192 7193 7194
                __func__, __LINE__, (stbInfo->columnCount + 1));
        return -1;
    }

    uint32_t k;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */
7195 7196 7197 7198 7199 7200
        if (-1 == prepareStbStmtBindRand(
                    pThreadInfo->bind_ts,
                    bindArray, stbInfo,
                    startTime, k,
                    pThreadInfo->time_precision
                    /* is column */)) {
7201 7202
            free(bindArray);
            return -1;
7203
        }
7204 7205
        ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        if (0 != ret) {
7206
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
7207
                    __func__, __LINE__, taos_stmt_errstr(stmt));
7208
            free(bindArray);
7209 7210
            return -1;
        }
7211
        // if msg > 3MB, break
7212 7213
        ret = taos_stmt_add_batch(stmt);
        if (0 != ret) {
7214
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
7215
                    __func__, __LINE__, taos_stmt_errstr(stmt));
7216
            free(bindArray);
7217 7218
            return -1;
        }
7219

7220 7221
        k++;
        recordFrom ++;
7222

7223 7224 7225 7226
        if (recordFrom >= insertRows) {
            break;
        }
    }
7227

7228
    free(bindArray);
7229 7230
    return k;
}
7231

7232 7233
static int32_t prepareStbStmtWithSample(
        threadInfo *pThreadInfo,
7234 7235 7236
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
7237 7238 7239 7240 7241
        uint64_t insertRows,
        uint64_t recordFrom,
        int64_t startTime,
        int64_t *pSamplePos)
{
7242 7243 7244
    int ret;
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    TAOS_STMT *stmt = pThreadInfo->stmt;
7245

7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257
    if (AUTO_CREATE_SUBTBL == stbInfo->autoCreateTable) {
        char* tagsValBuf = NULL;

        if (0 == stbInfo->tagSource) {
            tagsValBuf = generateTagValuesForStb(stbInfo, tableSeq);
        } else {
            tagsValBuf = getTagValueFromTagSample(
                    stbInfo,
                    tableSeq % stbInfo->tagSampleCount);
        }

        if (NULL == tagsValBuf) {
7258
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
7259 7260 7261 7262 7263 7264 7265
                    __func__, __LINE__);
            return -1;
        }

        char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount);
        if (NULL == tagsArray) {
            tmfree(tagsValBuf);
7266
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284
                    __func__, __LINE__);
            return -1;
        }

        if (-1 == prepareStbStmtBindTag(
                    tagsArray, stbInfo, tagsValBuf, pThreadInfo->time_precision
                    /* is tag */)) {
            tmfree(tagsValBuf);
            tmfree(tagsArray);
            return -1;
        }

        ret = taos_stmt_set_tbname_tags(stmt, tableName, (TAOS_BIND *)tagsArray);

        tmfree(tagsValBuf);
        tmfree(tagsArray);

        if (0 != ret) {
7285
            errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n",
7286 7287 7288 7289 7290 7291
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    } else {
        ret = taos_stmt_set_tbname(stmt, tableName);
        if (0 != ret) {
7292
            errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n",
7293 7294 7295 7296 7297 7298 7299 7300
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    }

    uint32_t k;
    for (k = 0; k < batch;) {
        char *bindArray = (char *)(*((uintptr_t *)
7301
                    (pThreadInfo->sampleBindArray + (sizeof(char *)) * (*pSamplePos))));
7302
        /* columnCount + 1 (ts) */
7303 7304
        if (-1 == prepareStbStmtBindStartTime(
                    tableName,
7305 7306 7307
                    pThreadInfo->bind_ts,
                    bindArray, stbInfo,
                    startTime, k,
7308
                    pThreadInfo->time_precision
7309 7310 7311 7312 7313
                    /* is column */)) {
            return -1;
        }
        ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        if (0 != ret) {
7314
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
7315 7316 7317 7318 7319 7320
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
        // if msg > 3MB, break
        ret = taos_stmt_add_batch(stmt);
        if (0 != ret) {
7321
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
7322 7323 7324
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
7325

7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340
        k++;
        recordFrom ++;

        (*pSamplePos) ++;
        if ((*pSamplePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
            *pSamplePos = 0;
        }

        if (recordFrom >= insertRows) {
            break;
        }
    }

    return k;
}
7341 7342

static int32_t generateStbProgressiveData(
7343
        SSuperTable *stbInfo,
7344
        char *tableName,
7345
        int64_t tableSeq,
7346
        char *dbName, char *buffer,
7347
        int64_t insertRows,
7348
        uint64_t recordFrom, int64_t startTime, int64_t *pSamplePos,
7349
        int64_t *pRemainderBufLen)
7350
{
7351 7352
    assert(buffer != NULL);
    char *pstr = buffer;
7353

7354
    memset(pstr, 0, *pRemainderBufLen);
7355

7356
    int64_t headLen = generateStbSQLHead(
7357
            stbInfo,
7358 7359
            tableName, tableSeq, dbName,
            buffer, *pRemainderBufLen);
7360

7361 7362 7363 7364 7365
    if (headLen <= 0) {
        return 0;
    }
    pstr += headLen;
    *pRemainderBufLen -= headLen;
7366

7367
    int64_t dataLen;
7368

7369
    return generateStbDataTail(stbInfo,
7370 7371 7372 7373
            g_args.num_of_RPR, pstr, *pRemainderBufLen,
            insertRows, recordFrom,
            startTime,
            pSamplePos, &dataLen);
7374 7375
}

7376
static int32_t generateProgressiveDataWithoutStb(
7377
        char *tableName,
7378
        /* int64_t tableSeq, */
7379 7380
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
7381
        uint64_t recordFrom, int64_t startTime, /*int64_t *pSamplePos, */
7382 7383
        int64_t *pRemainderBufLen)
{
7384 7385
    assert(buffer != NULL);
    char *pstr = buffer;
7386

7387
    memset(buffer, 0, *pRemainderBufLen);
7388

7389 7390 7391
    int64_t headLen = generateSQLHeadWithoutStb(
            tableName, pThreadInfo->db_name,
            buffer, *pRemainderBufLen);
7392

7393 7394 7395 7396 7397
    if (headLen <= 0) {
        return 0;
    }
    pstr += headLen;
    *pRemainderBufLen -= headLen;
7398

7399
    int64_t dataLen;
7400

7401 7402 7403 7404
    return generateDataTailWithoutStb(
            g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, recordFrom,
            startTime,
            /*pSamplePos, */&dataLen);
7405
}
7406

7407 7408
static void printStatPerThread(threadInfo *pThreadInfo)
{
7409
    fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
7410 7411 7412
            pThreadInfo->threadID,
            pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows,
7413 7414
            (pThreadInfo->totalDelay)?
            (double)(pThreadInfo->totalAffectedRows/((double)pThreadInfo->totalDelay/1000000.0)):
7415
            FLT_MAX);
7416 7417
}

7418
// sync write interlace data
7419
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
7420 7421
    debugPrint("[%d] %s() LN%d: ### interlace write\n",
            pThreadInfo->threadID, __func__, __LINE__);
7422

7423 7424 7425 7426 7427
    int64_t insertRows;
    uint32_t interlaceRows;
    uint64_t maxSqlLen;
    int64_t nTimeStampStep;
    uint64_t insert_interval;
7428

7429
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
7430

7431 7432
    if (stbInfo) {
        insertRows = stbInfo->insertRows;
7433

7434
        if ((stbInfo->interlaceRows == 0)
7435 7436 7437
                && (g_args.interlace_rows > 0)) {
            interlaceRows = g_args.interlace_rows;
        } else {
7438 7439 7440 7441 7442
            interlaceRows = stbInfo->interlaceRows;
        }
        maxSqlLen = stbInfo->maxSqlLen;
        nTimeStampStep = stbInfo->timeStampStep;
        insert_interval = stbInfo->insertInterval;
7443
    } else {
7444 7445 7446
        insertRows = g_args.num_of_DPT;
        interlaceRows = g_args.interlace_rows;
        maxSqlLen = g_args.max_sql_len;
7447
        nTimeStampStep = g_args.timestamp_step;
7448
        insert_interval = g_args.insert_interval;
7449
    }
7450

7451 7452 7453 7454
    debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n",
            pThreadInfo->threadID, __func__, __LINE__,
            pThreadInfo->start_table_from,
            pThreadInfo->ntables, insertRows);
7455

7456 7457
    if (interlaceRows > insertRows)
        interlaceRows = insertRows;
7458

7459 7460
    if (interlaceRows > g_args.num_of_RPR)
        interlaceRows = g_args.num_of_RPR;
7461

7462 7463
    uint32_t batchPerTbl = interlaceRows;
    uint32_t batchPerTblTimes;
7464

7465 7466 7467 7468 7469 7470
    if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
        batchPerTblTimes =
            g_args.num_of_RPR / interlaceRows;
    } else {
        batchPerTblTimes = 1;
    }
7471

7472 7473
    pThreadInfo->buffer = calloc(maxSqlLen, 1);
    if (NULL == pThreadInfo->buffer) {
7474
        errorPrint2( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
7475 7476 7477
                __func__, __LINE__, maxSqlLen, strerror(errno));
        return NULL;
    }
7478

7479 7480
    pThreadInfo->totalInsertRows = 0;
    pThreadInfo->totalAffectedRows = 0;
7481

7482 7483
    uint64_t st = 0;
    uint64_t et = UINT64_MAX;
7484

7485 7486 7487
    uint64_t lastPrintTime = taosGetTimestampMs();
    uint64_t startTs = taosGetTimestampMs();
    uint64_t endTs;
7488

7489 7490
    uint64_t tableSeq = pThreadInfo->start_table_from;
    int64_t startTime = pThreadInfo->start_time;
7491

7492 7493 7494
    uint64_t generatedRecPerTbl = 0;
    bool flagSleep = true;
    uint64_t sleepTimeTotal = 0;
7495

7496 7497 7498
    int percentComplete = 0;
    int64_t totalRows = insertRows * pThreadInfo->ntables;

7499 7500 7501 7502 7503 7504 7505 7506
    while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
        if ((flagSleep) && (insert_interval)) {
            st = taosGetTimestampMs();
            flagSleep = false;
        }
        // generate data
        memset(pThreadInfo->buffer, 0, maxSqlLen);
        uint64_t remainderBufLen = maxSqlLen;
7507

7508
        char *pstr = pThreadInfo->buffer;
7509

7510 7511 7512 7513
        int len = snprintf(pstr,
                strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
        pstr += len;
        remainderBufLen -= len;
7514

7515
        uint32_t recOfBatch = 0;
7516

7517 7518
        for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
            char tableName[TSDB_TABLE_NAME_LEN];
7519

7520 7521
            getTableName(tableName, pThreadInfo, tableSeq);
            if (0 == strlen(tableName)) {
7522
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
7523 7524 7525 7526
                        pThreadInfo->threadID, __func__, __LINE__);
                free(pThreadInfo->buffer);
                return NULL;
            }
7527

7528
            uint64_t oldRemainderLen = remainderBufLen;
7529

7530
            int32_t generated;
7531 7532
            if (stbInfo) {
                if (stbInfo->iface == STMT_IFACE) {
7533 7534 7535 7536 7537 7538 7539 7540
                    generated = prepareStbStmtWithSample(
                            pThreadInfo,
                            tableName,
                            tableSeq,
                            batchPerTbl,
                            insertRows, 0,
                            startTime,
                            &(pThreadInfo->samplePos));
7541 7542
                } else {
                    generated = generateStbInterlaceData(
7543
                            pThreadInfo,
7544 7545 7546
                            tableName, batchPerTbl, i,
                            batchPerTblTimes,
                            tableSeq,
7547
                            pstr,
7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558
                            insertRows,
                            startTime,
                            &remainderBufLen);
                }
            } else {
                if (g_args.iface == STMT_IFACE) {
                    debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n",
                            pThreadInfo->threadID,
                            __func__, __LINE__,
                            tableName, batchPerTbl, startTime);
                    generated = prepareStmtWithoutStb(
7559 7560
                            pThreadInfo,
                            tableName,
7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573
                            batchPerTbl,
                            insertRows, i,
                            startTime);
                } else {
                    generated = generateInterlaceDataWithoutStb(
                            tableName, batchPerTbl,
                            tableSeq,
                            pThreadInfo->db_name, pstr,
                            insertRows,
                            startTime,
                            &remainderBufLen);
                }
            }
7574

7575 7576 7577
            debugPrint("[%d] %s() LN%d, generated records is %d\n",
                    pThreadInfo->threadID, __func__, __LINE__, generated);
            if (generated < 0) {
7578
                errorPrint2("[%d] %s() LN%d, generated records is %d\n",
7579 7580 7581 7582 7583
                        pThreadInfo->threadID, __func__, __LINE__, generated);
                goto free_of_interlace;
            } else if (generated == 0) {
                break;
            }
7584

7585 7586
            tableSeq ++;
            recOfBatch += batchPerTbl;
7587

7588 7589
            pstr += (oldRemainderLen - remainderBufLen);
            pThreadInfo->totalInsertRows += batchPerTbl;
7590

7591 7592 7593
            verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
                    pThreadInfo->threadID, __func__, __LINE__,
                    batchPerTbl, recOfBatch);
7594

7595 7596 7597 7598
            if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
                // turn to first table
                tableSeq = pThreadInfo->start_table_from;
                generatedRecPerTbl += batchPerTbl;
7599

7600 7601
                startTime = pThreadInfo->start_time
                    + generatedRecPerTbl * nTimeStampStep;
7602

7603 7604 7605
                flagSleep = true;
                if (generatedRecPerTbl >= insertRows)
                    break;
7606

7607 7608 7609
                int64_t remainRows = insertRows - generatedRecPerTbl;
                if ((remainRows > 0) && (batchPerTbl > remainRows))
                    batchPerTbl = remainRows;
7610

7611 7612 7613
                if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                    break;
            }
7614

7615 7616 7617
            verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
                    pThreadInfo->threadID, __func__, __LINE__,
                    generatedRecPerTbl, insertRows);
7618

7619 7620
            if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
                break;
7621
        }
7622

7623 7624 7625 7626 7627 7628
        verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRIu64"\n",
                pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
                pThreadInfo->totalInsertRows);
        verbosePrint("[%d] %s() LN%d, buffer=%s\n",
                pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer);

7629
        startTs = taosGetTimestampUs();
7630 7631

        if (recOfBatch == 0) {
7632
            errorPrint2("[%d] %s() LN%d Failed to insert records of batch %d\n",
7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644
                    pThreadInfo->threadID, __func__, __LINE__,
                    batchPerTbl);
            if (batchPerTbl > 0) {
                errorPrint("\tIf the batch is %d, the length of the SQL to insert a row must be less then %"PRId64"\n",
                        batchPerTbl, maxSqlLen / batchPerTbl);
            }
            errorPrint("\tPlease check if the buffer length(%"PRId64") or batch(%d) is set with proper value!\n",
                    maxSqlLen, batchPerTbl);
            goto free_of_interlace;
        }
        int64_t affectedRows = execInsert(pThreadInfo, recOfBatch);

7645
        endTs = taosGetTimestampUs();
7646
        uint64_t delay = endTs - startTs;
7647 7648
        performancePrint("%s() LN%d, insert execution time is %10.2f ms\n",
                __func__, __LINE__, delay / 1000.0);
7649 7650 7651
        verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
                pThreadInfo->threadID,
                __func__, __LINE__, affectedRows);
7652

7653 7654 7655 7656
        if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
        if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
        pThreadInfo->cntDelay++;
        pThreadInfo->totalDelay += delay;
7657

7658
        if (recOfBatch != affectedRows) {
7659
            errorPrint2("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n",
7660 7661 7662 7663
                    pThreadInfo->threadID, __func__, __LINE__,
                    recOfBatch, affectedRows, pThreadInfo->buffer);
            goto free_of_interlace;
        }
7664

7665
        pThreadInfo->totalAffectedRows += affectedRows;
7666

7667 7668 7669 7670 7671
        int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
        if (currentPercent > percentComplete ) {
            printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
            percentComplete = currentPercent;
        }
7672 7673 7674
        int64_t  currentPrintTime = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
            printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
7675 7676 7677
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
7678 7679
            lastPrintTime = currentPrintTime;
        }
7680

7681 7682
        if ((insert_interval) && flagSleep) {
            et = taosGetTimestampMs();
7683

7684 7685 7686 7687 7688 7689 7690 7691
            if (insert_interval > (et - st) ) {
                uint64_t sleepTime = insert_interval - (et -st);
                performancePrint("%s() LN%d sleep: %"PRId64" ms for insert interval\n",
                        __func__, __LINE__, sleepTime);
                taosMsleep(sleepTime); // ms
                sleepTimeTotal += insert_interval;
            }
        }
7692
    }
7693 7694
    if (percentComplete < 100)
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);
7695

7696
free_of_interlace:
7697 7698 7699
    tmfree(pThreadInfo->buffer);
    printStatPerThread(pThreadInfo);
    return NULL;
7700 7701
}

7702
// sync insertion progressive data
7703
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
7704
    debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
7705

7706 7707
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
    uint64_t maxSqlLen = stbInfo?stbInfo->maxSqlLen:g_args.max_sql_len;
7708
    int64_t timeStampStep =
7709
        stbInfo?stbInfo->timeStampStep:g_args.timestamp_step;
7710
    int64_t insertRows =
7711
        (stbInfo)?stbInfo->insertRows:g_args.num_of_DPT;
7712
    verbosePrint("%s() LN%d insertRows=%"PRId64"\n",
7713
            __func__, __LINE__, insertRows);
7714

7715 7716
    pThreadInfo->buffer = calloc(maxSqlLen, 1);
    if (NULL == pThreadInfo->buffer) {
7717
        errorPrint2("Failed to alloc %"PRIu64" bytes, reason:%s\n",
7718 7719
                maxSqlLen,
                strerror(errno));
7720
        return NULL;
7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731
    }

    uint64_t lastPrintTime = taosGetTimestampMs();
    uint64_t startTs = taosGetTimestampMs();
    uint64_t endTs;

    pThreadInfo->totalInsertRows = 0;
    pThreadInfo->totalAffectedRows = 0;

    pThreadInfo->samplePos = 0;

7732 7733 7734
    int percentComplete = 0;
    int64_t totalRows = insertRows * pThreadInfo->ntables;

7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746
    for (uint64_t tableSeq = pThreadInfo->start_table_from;
            tableSeq <= pThreadInfo->end_table_to;
            tableSeq ++) {
        int64_t start_time = pThreadInfo->start_time;

        for (uint64_t i = 0; i < insertRows;) {
            char tableName[TSDB_TABLE_NAME_LEN];
            getTableName(tableName, pThreadInfo, tableSeq);
            verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
                    __func__, __LINE__,
                    pThreadInfo->threadID, tableSeq, tableName);
            if (0 == strlen(tableName)) {
7747
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
7748 7749 7750 7751
                        pThreadInfo->threadID, __func__, __LINE__);
                free(pThreadInfo->buffer);
                return NULL;
            }
7752

7753
            int64_t remainderBufLen = maxSqlLen - 2000;
7754
            char *pstr = pThreadInfo->buffer;
7755

7756 7757
            int len = snprintf(pstr,
                    strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
7758

7759 7760
            pstr += len;
            remainderBufLen -= len;
7761

7762 7763 7764
            // measure prepare + insert
            startTs = taosGetTimestampUs();

7765
            int32_t generated;
7766 7767
            if (stbInfo) {
                if (stbInfo->iface == STMT_IFACE) {
7768 7769 7770 7771 7772 7773 7774
                    generated = prepareStbStmtWithSample(
                            pThreadInfo,
                            tableName,
                            tableSeq,
                            g_args.num_of_RPR,
                            insertRows, i, start_time,
                            &(pThreadInfo->samplePos));
7775 7776
                } else {
                    generated = generateStbProgressiveData(
7777 7778 7779
                            stbInfo,
                            tableName, tableSeq,
                            pThreadInfo->db_name, pstr,
7780 7781 7782 7783 7784 7785 7786
                            insertRows, i, start_time,
                            &(pThreadInfo->samplePos),
                            &remainderBufLen);
                }
            } else {
                if (g_args.iface == STMT_IFACE) {
                    generated = prepareStmtWithoutStb(
7787
                            pThreadInfo,
7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801
                            tableName,
                            g_args.num_of_RPR,
                            insertRows, i,
                            start_time);
                } else {
                    generated = generateProgressiveDataWithoutStb(
                            tableName,
                            /*  tableSeq, */
                            pThreadInfo, pstr, insertRows,
                            i, start_time,
                            /* &(pThreadInfo->samplePos), */
                            &remainderBufLen);
                }
            }
7802 7803 7804 7805 7806

            verbosePrint("[%d] %s() LN%d generated=%d\n",
                    pThreadInfo->threadID,
                    __func__, __LINE__, generated);

7807 7808 7809 7810
            if (generated > 0)
                i += generated;
            else
                goto free_of_progressive;
7811

7812 7813
            start_time +=  generated * timeStampStep;
            pThreadInfo->totalInsertRows += generated;
7814

7815 7816
            // only measure insert
            // startTs = taosGetTimestampUs();
7817

7818
            int32_t affectedRows = execInsert(pThreadInfo, generated);
7819

7820
            endTs = taosGetTimestampUs();
7821
            uint64_t delay = endTs - startTs;
7822 7823
            performancePrint("%s() LN%d, insert execution time is %10.f ms\n",
                    __func__, __LINE__, delay/1000.0);
7824 7825 7826
            verbosePrint("[%d] %s() LN%d affectedRows=%d\n",
                    pThreadInfo->threadID,
                    __func__, __LINE__, affectedRows);
7827

7828 7829 7830 7831
            if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
            if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
            pThreadInfo->cntDelay++;
            pThreadInfo->totalDelay += delay;
7832

7833
            if (affectedRows < 0) {
7834
                errorPrint2("%s() LN%d, affected rows: %d\n",
7835 7836 7837
                        __func__, __LINE__, affectedRows);
                goto free_of_progressive;
            }
7838

7839
            pThreadInfo->totalAffectedRows += affectedRows;
7840

7841 7842 7843 7844 7845
            int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
            if (currentPercent > percentComplete ) {
                printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
                percentComplete = currentPercent;
            }
7846 7847 7848 7849 7850 7851 7852 7853
            int64_t  currentPrintTime = taosGetTimestampMs();
            if (currentPrintTime - lastPrintTime > 30*1000) {
                printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
                        pThreadInfo->threadID,
                        pThreadInfo->totalInsertRows,
                        pThreadInfo->totalAffectedRows);
                lastPrintTime = currentPrintTime;
            }
7854

7855 7856 7857
            if (i >= insertRows)
                break;
        }   // num_of_DPT
7858

7859
        if ((g_args.verbose_print) &&
7860
                (tableSeq == pThreadInfo->ntables - 1) && (stbInfo)
7861
                && (0 == strncasecmp(
7862
                        stbInfo->dataSource,
7863
                        "sample", strlen("sample")))) {
7864 7865 7866 7867
            verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
                    __func__, __LINE__, pThreadInfo->samplePos);
        }
    } // tableSeq
7868 7869
    if (percentComplete < 100)
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);
7870

7871
free_of_progressive:
7872 7873 7874
    tmfree(pThreadInfo->buffer);
    printStatPerThread(pThreadInfo);
    return NULL;
H
Hui Li 已提交
7875 7876
}

7877 7878
static void* syncWrite(void *sarg) {

7879
    threadInfo *pThreadInfo = (threadInfo *)sarg;
7880
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
7881

7882 7883
    setThreadName("syncWrite");

7884
    uint32_t interlaceRows;
7885

7886 7887
    if (stbInfo) {
        if ((stbInfo->interlaceRows == 0)
7888 7889 7890
                && (g_args.interlace_rows > 0)) {
            interlaceRows = g_args.interlace_rows;
        } else {
7891
            interlaceRows = stbInfo->interlaceRows;
7892
        }
7893
    } else {
7894
        interlaceRows = g_args.interlace_rows;
7895
    }
7896

7897 7898 7899 7900 7901 7902 7903
    if (interlaceRows > 0) {
        // interlace mode
        return syncWriteInterlace(pThreadInfo);
    } else {
        // progressive mode
        return syncWriteProgressive(pThreadInfo);
    }
7904 7905
}

7906
static void callBack(void *param, TAOS_RES *res, int code) {
7907
    threadInfo* pThreadInfo = (threadInfo*)param;
7908
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
7909 7910

    int insert_interval =
7911
        stbInfo?stbInfo->insertInterval:g_args.insert_interval;
7912 7913 7914 7915 7916
    if (insert_interval) {
        pThreadInfo->et = taosGetTimestampMs();
        if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
            taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
        }
H
Hui Li 已提交
7917 7918
    }

7919
    char *buffer = calloc(1, pThreadInfo->stbInfo->maxSqlLen);
7920 7921 7922 7923 7924
    char data[MAX_DATA_SIZE];
    char *pstr = buffer;
    pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
            pThreadInfo->db_name, pThreadInfo->tb_prefix,
            pThreadInfo->start_table_from);
7925
    //  if (pThreadInfo->counter >= pThreadInfo->stbInfo->insertRows) {
7926 7927 7928 7929 7930 7931 7932 7933 7934
    if (pThreadInfo->counter >= g_args.num_of_RPR) {
        pThreadInfo->start_table_from++;
        pThreadInfo->counter = 0;
    }
    if (pThreadInfo->start_table_from > pThreadInfo->end_table_to) {
        tsem_post(&pThreadInfo->lock_sem);
        free(buffer);
        taos_free_result(res);
        return;
H
Hui Li 已提交
7935
    }
7936

7937 7938
    for (int i = 0; i < g_args.num_of_RPR; i++) {
        int rand_num = taosRandom() % 100;
7939 7940
        if (0 != pThreadInfo->stbInfo->disorderRatio
                && rand_num < pThreadInfo->stbInfo->disorderRatio) {
7941
            int64_t d = pThreadInfo->lastTs
7942 7943
                - (taosRandom() % pThreadInfo->stbInfo->disorderRange + 1);
            generateStbRowData(pThreadInfo->stbInfo, data,
7944 7945
                    MAX_DATA_SIZE,
                    d);
7946
        } else {
7947
            generateStbRowData(pThreadInfo->stbInfo,
7948 7949 7950
                    data,
                    MAX_DATA_SIZE,
                    pThreadInfo->lastTs += 1000);
7951 7952 7953
        }
        pstr += sprintf(pstr, "%s", data);
        pThreadInfo->counter++;
H
Hui Li 已提交
7954

7955
        if (pThreadInfo->counter >= pThreadInfo->stbInfo->insertRows) {
7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966
            break;
        }
    }

    if (insert_interval) {
        pThreadInfo->st = taosGetTimestampMs();
    }
    taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
    free(buffer);

    taos_free_result(res);
H
Hui Li 已提交
7967 7968
}

7969
static void *asyncWrite(void *sarg) {
7970
    threadInfo *pThreadInfo = (threadInfo *)sarg;
7971
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
7972

7973
    setThreadName("asyncWrite");
7974

7975 7976 7977
    pThreadInfo->st = 0;
    pThreadInfo->et = 0;
    pThreadInfo->lastTs = pThreadInfo->start_time;
7978

7979
    int insert_interval =
7980
        stbInfo?stbInfo->insertInterval:g_args.insert_interval;
7981 7982 7983 7984
    if (insert_interval) {
        pThreadInfo->st = taosGetTimestampMs();
    }
    taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
7985

7986
    tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
7987

7988
    return NULL;
H
Hui Li 已提交
7989 7990
}

7991 7992
static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in *serv_addr)
{
7993 7994 7995
    uint16_t rest_port = port + TSDB_PORT_HTTP;
    struct hostent *server = gethostbyname(host);
    if ((server == NULL) || (server->h_addr == NULL)) {
7996
        errorPrint2("%s", "no such host");
7997 7998
        return -1;
    }
7999

8000
    debugPrint("h_name: %s\nh_addr=%p\nh_addretype: %s\nh_length: %d\n",
8001 8002 8003 8004 8005
            server->h_name,
            server->h_addr,
            (server->h_addrtype == AF_INET)?"ipv4":"ipv6",
            server->h_length);

8006 8007 8008
    memset(serv_addr, 0, sizeof(struct sockaddr_in));
    serv_addr->sin_family = AF_INET;
    serv_addr->sin_port = htons(rest_port);
8009
#ifdef WINDOWS
8010
    serv_addr->sin_addr.s_addr = inet_addr(host);
8011
#else
8012
    memcpy(&(serv_addr->sin_addr.s_addr), server->h_addr, server->h_length);
8013
#endif
8014
    return 0;
8015 8016
}

8017 8018 8019
static int parseSampleFileToStmt(
        threadInfo *pThreadInfo,
        SSuperTable *stbInfo, uint32_t timePrec)
8020
{
8021 8022 8023
    pThreadInfo->sampleBindArray =
        calloc(1, sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE);
    if (pThreadInfo->sampleBindArray == NULL) {
8024
        errorPrint2("%s() LN%d, Failed to allocate %"PRIu64" bind array buffer\n",
8025 8026
                __func__, __LINE__,
                (uint64_t)sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE);
8027 8028 8029 8030
        return -1;
    }

    for (int i=0; i < MAX_SAMPLES_ONCE_FROM_FILE; i++) {
8031 8032
        char *bindArray =
            calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1));
8033
        if (bindArray == NULL) {
8034
            errorPrint2("%s() LN%d, Failed to allocate %d bind params\n",
8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064
                    __func__, __LINE__, (stbInfo->columnCount + 1));
            return -1;
        }

        TAOS_BIND *bind;
        int cursor = 0;

        for (int c = 0; c < stbInfo->columnCount + 1; c++) {
            bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * c));

            if (c == 0) {
                bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
                bind->buffer_length = sizeof(int64_t);
                bind->buffer = NULL; //bind_ts;
                bind->length = &bind->buffer_length;
                bind->is_null = NULL;
            } else {
                char *restStr = stbInfo->sampleDataBuf
                    + stbInfo->lenOfOneRow * i + cursor;
                int lengthOfRest = strlen(restStr);

                int index = 0;
                for (index = 0; index < lengthOfRest; index ++) {
                    if (restStr[index] == ',') {
                        break;
                    }
                }

                char *bindBuffer = calloc(1, index + 1);
                if (bindBuffer == NULL) {
8065
                    errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n",
8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084
                            __func__, __LINE__, DOUBLE_BUFF_LEN);
                    return -1;
                }

                strncpy(bindBuffer, restStr, index);
                cursor += index + 1; // skip ',' too

                if (-1 == prepareStmtBindArrayByType(
                            bind,
                            stbInfo->columns[c-1].dataType,
                            stbInfo->columns[c-1].dataLen,
                            timePrec,
                            bindBuffer)) {
                    free(bindBuffer);
                    return -1;
                }
                free(bindBuffer);
            }
        }
8085 8086
        *((uintptr_t *)(pThreadInfo->sampleBindArray + (sizeof(char *)) * i)) =
            (uintptr_t)bindArray;
8087 8088 8089 8090 8091
    }

    return 0;
}

8092
static void startMultiThreadInsertData(int threads, char* db_name,
8093
        char* precision, SSuperTable* stbInfo) {
8094

8095 8096 8097 8098 8099 8100 8101 8102 8103
    int32_t timePrec = TSDB_TIME_PRECISION_MILLI;
    if (0 != precision[0]) {
        if (0 == strncasecmp(precision, "ms", 2)) {
            timePrec = TSDB_TIME_PRECISION_MILLI;
        } else if (0 == strncasecmp(precision, "us", 2)) {
            timePrec = TSDB_TIME_PRECISION_MICRO;
        } else if (0 == strncasecmp(precision, "ns", 2)) {
            timePrec = TSDB_TIME_PRECISION_NANO;
        } else {
8104
            errorPrint2("Not support precision: %s\n", precision);
8105
            exit(EXIT_FAILURE);
8106
        }
8107 8108
    }

8109
    int64_t start_time;
8110 8111
    if (stbInfo) {
        if (0 == strncasecmp(stbInfo->startTimestamp, "now", 3)) {
8112 8113 8114
            start_time = taosGetTimestamp(timePrec);
        } else {
            if (TSDB_CODE_SUCCESS != taosParseTime(
8115
                        stbInfo->startTimestamp,
8116
                        &start_time,
8117
                        strlen(stbInfo->startTimestamp),
8118 8119 8120 8121
                        timePrec, 0)) {
                ERROR_EXIT("failed to parse time!\n");
            }
        }
8122
    } else {
8123
        start_time = DEFAULT_START_TIME;
8124
    }
8125 8126
    debugPrint("%s() LN%d, start_time= %"PRId64"\n",
            __func__, __LINE__, start_time);
8127

8128
    // read sample data from file first
8129
    if (stbInfo) {
8130
        if (0 != prepareSampleDataForSTable(stbInfo)) {
8131
            errorPrint2("%s() LN%d, prepare sample data for stable failed!\n",
8132
                    __func__, __LINE__);
8133
            exit(EXIT_FAILURE);
8134
        }
8135 8136
    }

8137 8138 8139 8140
    TAOS* taos0 = taos_connect(
            g_Dbs.host, g_Dbs.user,
            g_Dbs.password, db_name, g_Dbs.port);
    if (NULL == taos0) {
8141
        errorPrint2("%s() LN%d, connect to server fail , reason: %s\n",
8142
                __func__, __LINE__, taos_errstr(NULL));
8143
        exit(EXIT_FAILURE);
8144
    }
8145

8146 8147
    int64_t ntables = 0;
    uint64_t tableFrom;
8148

8149
    if (stbInfo) {
8150 8151
        int64_t limit;
        uint64_t offset;
8152

8153
        if ((NULL != g_args.sqlFile)
8154 8155 8156
                && (stbInfo->childTblExists == TBL_NO_EXISTS)
                && ((stbInfo->childTblOffset != 0)
                    || (stbInfo->childTblLimit >= 0))) {
8157 8158
            printf("WARNING: offset and limit will not be used since the child tables not exists!\n");
        }
8159

8160 8161 8162 8163 8164 8165 8166
        if (stbInfo->childTblExists == TBL_ALREADY_EXISTS) {
            if ((stbInfo->childTblLimit < 0)
                    || ((stbInfo->childTblOffset
                            + stbInfo->childTblLimit)
                        > (stbInfo->childTblCount))) {
                stbInfo->childTblLimit =
                    stbInfo->childTblCount - stbInfo->childTblOffset;
8167
            }
8168

8169 8170
            offset = stbInfo->childTblOffset;
            limit = stbInfo->childTblLimit;
8171
        } else {
8172
            limit = stbInfo->childTblCount;
8173 8174
            offset = 0;
        }
8175

8176 8177
        ntables = limit;
        tableFrom = offset;
8178

8179 8180 8181
        if ((stbInfo->childTblExists != TBL_NO_EXISTS)
                && ((stbInfo->childTblOffset + stbInfo->childTblLimit)
                    > stbInfo->childTblCount)) {
8182 8183 8184
            printf("WARNING: specified offset + limit > child table count!\n");
            prompt();
        }
8185

8186 8187
        if ((stbInfo->childTblExists != TBL_NO_EXISTS)
                && (0 == stbInfo->childTblLimit)) {
8188 8189 8190
            printf("WARNING: specified limit = 0, which cannot find table name to insert or query! \n");
            prompt();
        }
8191

8192
        stbInfo->childTblName = (char*)calloc(1,
8193
                limit * TSDB_TABLE_NAME_LEN);
8194
        if (stbInfo->childTblName == NULL) {
8195
            taos_close(taos0);
8196
            errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
8197
            exit(EXIT_FAILURE);
8198
        }
8199

8200 8201 8202
        int64_t childTblCount;
        getChildNameOfSuperTableWithLimitAndOffset(
                taos0,
8203 8204
                db_name, stbInfo->sTblName,
                &stbInfo->childTblName, &childTblCount,
8205 8206 8207 8208 8209 8210
                limit,
                offset);
    } else {
        ntables = g_args.num_of_tables;
        tableFrom = 0;
    }
8211

8212
    taos_close(taos0);
8213

8214 8215 8216 8217 8218
    int64_t a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
    }
8219

8220 8221 8222 8223
    int64_t b = 0;
    if (threads != 0) {
        b = ntables % threads;
    }
8224

8225 8226
    if ((stbInfo)
            && (stbInfo->iface == REST_IFACE)) {
8227 8228
        if (convertHostToServAddr(
                    g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0) {
8229
            ERROR_EXIT("convert host to server address");
8230 8231
        }
    }
8232

8233 8234
    pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
    assert(pids != NULL);
8235

8236 8237
    threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
    assert(infos != NULL);
8238

8239 8240
    memset(pids, 0, threads * sizeof(pthread_t));
    memset(infos, 0, threads * sizeof(threadInfo));
8241

8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277
    char *stmtBuffer = calloc(1, BUFFER_SIZE);
    assert(stmtBuffer);
    if ((g_args.iface == STMT_IFACE)
            || ((stbInfo)
                && (stbInfo->iface == STMT_IFACE))) {
        char *pstr = stmtBuffer;

        if ((stbInfo)
                && (AUTO_CREATE_SUBTBL
                    == stbInfo->autoCreateTable)) {
            pstr += sprintf(pstr, "INSERT INTO ? USING %s TAGS(?",
                    stbInfo->sTblName);
            for (int tag = 0; tag < (stbInfo->tagCount - 1);
                    tag ++ ) {
                pstr += sprintf(pstr, ",?");
            }
            pstr += sprintf(pstr, ") VALUES(?");
        } else {
            pstr += sprintf(pstr, "INSERT INTO ? VALUES(?");
        }

        int columnCount;
        if (stbInfo) {
            columnCount = stbInfo->columnCount;
        } else {
            columnCount = g_args.num_of_CPR;
        }

        for (int col = 0; col < columnCount; col ++) {
            pstr += sprintf(pstr, ",?");
        }
        pstr += sprintf(pstr, ")");

        debugPrint("%s() LN%d, stmtBuffer: %s", __func__, __LINE__, stmtBuffer);
    }

8278 8279 8280
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
        pThreadInfo->threadID = i;
8281

8282 8283
        tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
        pThreadInfo->time_precision = timePrec;
8284
        pThreadInfo->stbInfo = stbInfo;
8285 8286 8287 8288

        pThreadInfo->start_time = start_time;
        pThreadInfo->minDelay = UINT64_MAX;

8289 8290
        if ((NULL == stbInfo) ||
                (stbInfo->iface != REST_IFACE)) {
8291 8292 8293 8294 8295
            //t_info->taos = taos;
            pThreadInfo->taos = taos_connect(
                    g_Dbs.host, g_Dbs.user,
                    g_Dbs.password, db_name, g_Dbs.port);
            if (NULL == pThreadInfo->taos) {
8296
                free(infos);
8297
                errorPrint2(
8298 8299 8300
                        "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n",
                        __func__, __LINE__,
                        taos_errstr(NULL));
8301
                exit(EXIT_FAILURE);
8302
            }
8303

8304
            if ((g_args.iface == STMT_IFACE)
8305 8306
                    || ((stbInfo)
                        && (stbInfo->iface == STMT_IFACE))) {
8307

8308 8309
                pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos);
                if (NULL == pThreadInfo->stmt) {
8310 8311
                    free(pids);
                    free(infos);
8312
                    errorPrint2(
8313 8314 8315
                            "%s() LN%d, failed init stmt, reason: %s\n",
                            __func__, __LINE__,
                            taos_errstr(NULL));
8316
                    exit(EXIT_FAILURE);
8317
                }
8318

8319
                int ret = taos_stmt_prepare(pThreadInfo->stmt, stmtBuffer, 0);
8320
                if (ret != 0) {
8321 8322
                    free(pids);
                    free(infos);
8323
                    free(stmtBuffer);
8324
                    errorPrint2("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n",
8325 8326
                            ret, taos_stmt_errstr(pThreadInfo->stmt));
                    exit(EXIT_FAILURE);
8327
                }
8328
                pThreadInfo->bind_ts = malloc(sizeof(int64_t));
8329 8330 8331 8332

                if (stbInfo) {
                    parseSampleFileToStmt(pThreadInfo, stbInfo, timePrec);
                }
8333 8334
            }
        } else {
8335
            pThreadInfo->taos = NULL;
8336
        }
8337

8338 8339
        /*    if ((NULL == stbInfo)
              || (0 == stbInfo->multiThreadWriteOneTbl)) {
8340 8341 8342 8343 8344 8345 8346
              */
        pThreadInfo->start_table_from = tableFrom;
        pThreadInfo->ntables = i<b?a+1:a;
        pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
        tableFrom = pThreadInfo->end_table_to + 1;
        /*    } else {
              pThreadInfo->start_table_from = 0;
8347
              pThreadInfo->ntables = stbInfo->childTblCount;
8348 8349 8350 8351 8352 8353 8354 8355
              pThreadInfo->start_time = pThreadInfo->start_time + rand_int() % 10000 - rand_tinyint();
              }
              */
        tsem_init(&(pThreadInfo->lock_sem), 0, 0);
        if (ASYNC_MODE == g_Dbs.asyncMode) {
            pthread_create(pids + i, NULL, asyncWrite, pThreadInfo);
        } else {
            pthread_create(pids + i, NULL, syncWrite, pThreadInfo);
8356
        }
8357 8358
    }

8359 8360
    free(stmtBuffer);

8361
    int64_t start = taosGetTimestampUs();
8362

8363 8364
    for (int i = 0; i < threads; i++) {
        pthread_join(pids[i], NULL);
8365
    }
H
Hui Li 已提交
8366

8367 8368 8369 8370 8371
    uint64_t totalDelay = 0;
    uint64_t maxDelay = 0;
    uint64_t minDelay = UINT64_MAX;
    uint64_t cntDelay = 1;
    double  avgDelay = 0;
8372

8373 8374
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
8375

8376 8377
        if (pThreadInfo->stmt) {
            taos_stmt_close(pThreadInfo->stmt);
8378
            tmfree((char *)pThreadInfo->bind_ts);
8379 8380 8381
        }
        tsem_destroy(&(pThreadInfo->lock_sem));
        taos_close(pThreadInfo->taos);
8382

8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397
        if (pThreadInfo->sampleBindArray) {
            for (int k = 0; k < MAX_SAMPLES_ONCE_FROM_FILE; k++) {
                uintptr_t *tmp = (uintptr_t *)(*(uintptr_t *)(
                            pThreadInfo->sampleBindArray
                            + sizeof(uintptr_t *) * k));
                for (int c = 1; c < pThreadInfo->stbInfo->columnCount + 1; c++) {
                    TAOS_BIND *bind = (TAOS_BIND *)((char *)tmp + (sizeof(TAOS_BIND) * c));
                    if (bind)
                        tmfree(bind->buffer);
                }
                tmfree((char *)tmp);
            }
            tmfree(pThreadInfo->sampleBindArray);
        }

8398 8399 8400 8401
        debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
                __func__, __LINE__,
                pThreadInfo->threadID, pThreadInfo->totalInsertRows,
                pThreadInfo->totalAffectedRows);
8402 8403 8404
        if (stbInfo) {
            stbInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
            stbInfo->totalInsertRows += pThreadInfo->totalInsertRows;
8405 8406 8407 8408
        } else {
            g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
            g_args.totalInsertRows += pThreadInfo->totalInsertRows;
        }
H
Hui Li 已提交
8409

8410 8411 8412 8413 8414 8415
        totalDelay  += pThreadInfo->totalDelay;
        cntDelay   += pThreadInfo->cntDelay;
        if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
        if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
    }
    cntDelay -= 1;
8416

8417 8418
    if (cntDelay == 0)    cntDelay = 1;
    avgDelay = (double)totalDelay / cntDelay;
8419

8420
    int64_t end = taosGetTimestampUs();
8421
    int64_t t = end - start;
8422
    if (0 == t) t = 1;
8423

8424
    double tInMs = (double) t / 1000000.0;
8425

8426
    if (stbInfo) {
8427
        fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
8428 8429 8430
                tInMs, stbInfo->totalInsertRows,
                stbInfo->totalAffectedRows,
                threads, db_name, stbInfo->sTblName,
8431
                (double)(stbInfo->totalInsertRows/tInMs));
8432 8433 8434

        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
8435
                    "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
8436 8437 8438
                    tInMs, stbInfo->totalInsertRows,
                    stbInfo->totalAffectedRows,
                    threads, db_name, stbInfo->sTblName,
8439
                    (double)(stbInfo->totalInsertRows/tInMs));
8440 8441
        }
    } else {
8442
        fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
8443 8444 8445
                tInMs, g_args.totalInsertRows,
                g_args.totalAffectedRows,
                threads, db_name,
8446
                (double)(g_args.totalInsertRows/tInMs));
8447 8448
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
8449
                    "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
8450 8451 8452
                    tInMs, g_args.totalInsertRows,
                    g_args.totalAffectedRows,
                    threads, db_name,
8453
                    (double)(g_args.totalInsertRows/tInMs));
8454
        }
8455
    }
8456

8457 8458 8459 8460
    fprintf(stderr, "insert delay, avg: %10.2fms, max: %10.2fms, min: %10.2fms\n\n",
            (double)avgDelay/1000.0,
            (double)maxDelay/1000.0,
            (double)minDelay/1000.0);
8461
    if (g_fpOfInsertResult) {
8462 8463 8464 8465
        fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %10.2fms, min: %10.2fms\n\n",
            (double)avgDelay/1000.0,
            (double)maxDelay/1000.0,
            (double)minDelay/1000.0);
8466
    }
8467

8468
    //taos_close(taos);
8469

8470 8471
    free(pids);
    free(infos);
H
Hui Li 已提交
8472 8473
}

8474
static void *readTable(void *sarg) {
8475
#if 1
8476 8477 8478
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    TAOS *taos = pThreadInfo->taos;
    setThreadName("readTable");
8479 8480 8481
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);

8482 8483 8484 8485
    uint64_t sTime = pThreadInfo->start_time;
    char *tb_prefix = pThreadInfo->tb_prefix;
    FILE *fp = fopen(pThreadInfo->filePath, "a");
    if (NULL == fp) {
8486
        errorPrint2("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
8487
        free(command);
8488
        return NULL;
8489
    }
H
hzcheng 已提交
8490

8491
    int64_t num_of_DPT;
8492 8493
    /*  if (pThreadInfo->stbInfo) {
        num_of_DPT = pThreadInfo->stbInfo->insertRows; //  nrecords_per_table;
8494 8495 8496 8497 8498 8499 8500 8501 8502
        } else {
        */
    num_of_DPT = g_args.num_of_DPT;
    //  }

    int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
    int64_t totalData = num_of_DPT * num_of_tables;
    bool do_aggreFunc = g_Dbs.do_aggreFunc;

8503
    int n = do_aggreFunc ? (sizeof(g_aggreFunc) / sizeof(g_aggreFunc[0])) : 2;
8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514
    if (!do_aggreFunc) {
        printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n");
    }
    printf("%"PRId64" records:\n", totalData);
    fprintf(fp, "| QFunctions |    QRecords    |   QSpeed(R/s)   |  QLatency(ms) |\n");

    for (int j = 0; j < n; j++) {
        double totalT = 0;
        uint64_t count = 0;
        for (int64_t i = 0; i < num_of_tables; i++) {
            sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
8515
                    g_aggreFunc[j], tb_prefix, i, sTime);
8516 8517 8518 8519 8520 8521

            double t = taosGetTimestampMs();
            TAOS_RES *pSql = taos_query(taos, command);
            int32_t code = taos_errno(pSql);

            if (code != 0) {
8522
                errorPrint2("Failed to query:%s\n", taos_errstr(pSql));
8523 8524 8525
                taos_free_result(pSql);
                taos_close(taos);
                fclose(fp);
8526
                free(command);
8527 8528
                return NULL;
            }
H
hzcheng 已提交
8529

8530 8531 8532
            while(taos_fetch_row(pSql) != NULL) {
                count++;
            }
H
hzcheng 已提交
8533

8534 8535 8536 8537 8538
            t = taosGetTimestampMs() - t;
            totalT += t;

            taos_free_result(pSql);
        }
H
hzcheng 已提交
8539

8540
        fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
8541
                g_aggreFunc[j][0] == '*' ? "   *   " : g_aggreFunc[j], totalData,
8542
                (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
8543
        printf("select %10s took %.6f second(s)\n", g_aggreFunc[j], totalT * 1000);
8544 8545 8546
    }
    fprintf(fp, "\n");
    fclose(fp);
8547
    free(command);
8548
#endif
8549
    return NULL;
H
hzcheng 已提交
8550 8551
}

8552
static void *readMetric(void *sarg) {
8553
#if 1
8554 8555 8556
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    TAOS *taos = pThreadInfo->taos;
    setThreadName("readMetric");
8557 8558 8559
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);

8560 8561 8562
    FILE *fp = fopen(pThreadInfo->filePath, "a");
    if (NULL == fp) {
        printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
8563
        free(command);
8564 8565
        return NULL;
    }
8566

8567
    int64_t num_of_DPT = pThreadInfo->stbInfo->insertRows;
8568 8569 8570
    int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
    int64_t totalData = num_of_DPT * num_of_tables;
    bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
8571

8572
    int n = do_aggreFunc ? (sizeof(g_aggreFunc) / sizeof(g_aggreFunc[0])) : 2;
8573 8574 8575 8576 8577
    if (!do_aggreFunc) {
        printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n");
    }
    printf("%"PRId64" records:\n", totalData);
    fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
8578

8579 8580 8581
    for (int j = 0; j < n; j++) {
        char condition[COND_BUF_LEN] = "\0";
        char tempS[64] = "\0";
H
hzcheng 已提交
8582

8583
        int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
8584

8585 8586 8587 8588 8589 8590 8591
        for (int64_t i = 1; i <= m; i++) {
            if (i == 1) {
                sprintf(tempS, "t1 = %"PRId64"", i);
            } else {
                sprintf(tempS, " or t1 = %"PRId64" ", i);
            }
            strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
8592

8593
            sprintf(command, "select %s from meters where %s", g_aggreFunc[j], condition);
H
hzcheng 已提交
8594

8595 8596
            printf("Where condition: %s\n", condition);
            fprintf(fp, "%s\n", command);
H
hzcheng 已提交
8597

8598
            double t = taosGetTimestampMs();
H
hzcheng 已提交
8599

8600 8601
            TAOS_RES *pSql = taos_query(taos, command);
            int32_t code = taos_errno(pSql);
S
Shuaiqiang Chang 已提交
8602

8603
            if (code != 0) {
8604
                errorPrint2("Failed to query:%s\n", taos_errstr(pSql));
8605 8606 8607
                taos_free_result(pSql);
                taos_close(taos);
                fclose(fp);
8608
                free(command);
8609 8610 8611 8612 8613 8614 8615
                return NULL;
            }
            int count = 0;
            while(taos_fetch_row(pSql) != NULL) {
                count++;
            }
            t = taosGetTimestampMs() - t;
H
hzcheng 已提交
8616

8617 8618
            fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
                    num_of_tables * num_of_DPT / (t * 1000.0), t);
8619
            printf("select %10s took %.6f second(s)\n\n", g_aggreFunc[j], t * 1000.0);
H
hzcheng 已提交
8620

8621 8622 8623
            taos_free_result(pSql);
        }
        fprintf(fp, "\n");
H
hzcheng 已提交
8624
    }
8625
    fclose(fp);
8626
    free(command);
8627
#endif
8628
    return NULL;
H
hzcheng 已提交
8629 8630
}

8631 8632
static void prompt()
{
8633 8634 8635 8636
    if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
    }
8637
}
H
Hui Li 已提交
8638

8639
static int insertTestProcess() {
8640

8641 8642 8643
    setupForAnsiEscape();
    int ret = printfInsertMeta();
    resetAfterAnsiEscape();
8644

8645 8646
    if (ret == -1)
        exit(EXIT_FAILURE);
8647

8648 8649 8650
    debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
    g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
    if (NULL == g_fpOfInsertResult) {
8651
        errorPrint("Failed to open %s for save result\n", g_Dbs.resultFile);
8652 8653
        return -1;
    }
8654

8655 8656
    if (g_fpOfInsertResult)
        printfInsertMetaToFile(g_fpOfInsertResult);
8657

8658
    prompt();
8659

8660
    init_rand_data();
8661

8662
    // create database and super tables
8663 8664 8665 8666
    char *cmdBuffer = calloc(1, BUFFER_SIZE);
    assert(cmdBuffer);

    if(createDatabasesAndStables(cmdBuffer) != 0) {
8667 8668
        if (g_fpOfInsertResult)
            fclose(g_fpOfInsertResult);
8669
        free(cmdBuffer);
8670 8671
        return -1;
    }
8672
    free(cmdBuffer);
8673

8674 8675 8676 8677 8678 8679
    // pretreatement
    if (prepareSampleData() != 0) {
        if (g_fpOfInsertResult)
            fclose(g_fpOfInsertResult);
        return -1;
    }
8680

8681 8682
    double start;
    double end;
8683

8684
    if (g_totalChildTables > 0) {
8685 8686
        fprintf(stderr,
                "creating %"PRId64" table(s) with %d thread(s)\n\n",
8687
                g_totalChildTables, g_Dbs.threadCountForCreateTbl);
8688 8689 8690
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
                "creating %"PRId64" table(s) with %d thread(s)\n\n",
8691
                g_totalChildTables, g_Dbs.threadCountForCreateTbl);
8692 8693 8694 8695 8696 8697 8698 8699
        }

        // create child tables
        start = taosGetTimestampMs();
        createChildTables();
        end = taosGetTimestampMs();

        fprintf(stderr,
8700
                "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n",
8701
                (end - start)/1000.0, g_totalChildTables,
8702
                g_Dbs.threadCountForCreateTbl, g_actualChildTables);
8703 8704
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
8705
                "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n",
8706
                (end - start)/1000.0, g_totalChildTables,
8707
                g_Dbs.threadCountForCreateTbl, g_actualChildTables);
8708
        }
8709
    }
8710

8711 8712 8713 8714 8715 8716
    // create sub threads for inserting data
    //start = taosGetTimestampMs();
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        if (g_Dbs.use_metric) {
            if (g_Dbs.db[i].superTblCount > 0) {
                for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
8717

8718
                    SSuperTable* stbInfo = &g_Dbs.db[i].superTbls[j];
8719

8720
                    if (stbInfo && (stbInfo->insertRows > 0)) {
8721 8722 8723 8724
                        startMultiThreadInsertData(
                                g_Dbs.threadCount,
                                g_Dbs.db[i].dbName,
                                g_Dbs.db[i].dbCfg.precision,
8725
                                stbInfo);
8726 8727 8728 8729
                    }
                }
            }
        } else {
8730
            startMultiThreadInsertData(
8731 8732 8733 8734
                    g_Dbs.threadCount,
                    g_Dbs.db[i].dbName,
                    g_Dbs.db[i].dbCfg.precision,
                    NULL);
8735
        }
H
Hui Li 已提交
8736
    }
8737
    //end = taosGetTimestampMs();
8738

8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749
    //int64_t    totalInsertRows = 0;
    //int64_t    totalAffectedRows = 0;
    //for (int i = 0; i < g_Dbs.dbCount; i++) {
    //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
    //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
    //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
    //}
    //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
    postFreeResource();

    return 0;
8750 8751
}

8752
static void *specifiedTableQuery(void *sarg) {
8753
    threadInfo *pThreadInfo = (threadInfo *)sarg;
8754

8755
    setThreadName("specTableQuery");
8756

8757 8758 8759 8760 8761 8762 8763 8764
    if (pThreadInfo->taos == NULL) {
        TAOS * taos = NULL;
        taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                NULL,
                g_queryInfo.port);
        if (taos == NULL) {
8765
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
8766 8767 8768 8769 8770
                    pThreadInfo->threadID, taos_errstr(NULL));
            return NULL;
        } else {
            pThreadInfo->taos = taos;
        }
8771 8772
    }

8773 8774 8775 8776
    char sqlStr[TSDB_DB_NAME_LEN + 5];
    sprintf(sqlStr, "use %s", g_queryInfo.dbName);
    if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
        taos_close(pThreadInfo->taos);
8777
        errorPrint("use database %s failed!\n\n",
8778
                g_queryInfo.dbName);
8779 8780
        return NULL;
    }
8781

8782 8783
    uint64_t st = 0;
    uint64_t et = 0;
8784

8785
    uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
8786

8787 8788 8789
    uint64_t totalQueried = 0;
    uint64_t lastPrintTime = taosGetTimestampMs();
    uint64_t startTs = taosGetTimestampMs();
8790

8791 8792
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
        sprintf(pThreadInfo->filePath, "%s-%d",
8793 8794
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
8795 8796
    }

8797 8798 8799 8800 8801 8802 8803
    while(queryTimes --) {
        if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
                (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
            taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
        }

        st = taosGetTimestampMs();
8804

8805 8806
        selectAndGetResult(pThreadInfo,
                g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
8807

8808 8809 8810
        et = taosGetTimestampMs();
        printf("=thread[%"PRId64"] use %s complete one sql, Spent %10.3f s\n",
                taosGetSelfPthreadId(), g_queryInfo.queryMode, (et - st)/1000.0);
8811

8812 8813
        totalQueried ++;
        g_queryInfo.specifiedQueryInfo.totalQueried ++;
8814

8815 8816 8817
        uint64_t  currentPrintTime = taosGetTimestampMs();
        uint64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
8818
            debugPrint("%s() LN%d, endTs=%"PRIu64" ms, startTs=%"PRIu64" ms\n",
8819 8820
                    __func__, __LINE__, endTs, startTs);
            printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
8821 8822
                    pThreadInfo->threadID,
                    totalQueried,
8823
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
8824 8825
            lastPrintTime = currentPrintTime;
        }
8826
    }
8827
    return NULL;
8828
}
H
Hui Li 已提交
8829

8830
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
8831
    char sourceString[32] = "xxxx";
8832
    char subTblName[TSDB_TABLE_NAME_LEN];
8833 8834 8835
    sprintf(subTblName, "%s.%s",
            g_queryInfo.dbName,
            g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
8836

8837
    //printf("inSql: %s\n", inSql);
8838

8839 8840 8841 8842 8843 8844 8845
    char* pos = strstr(inSql, sourceString);
    if (0 == pos) {
        return;
    }

    tstrncpy(outSql, inSql, pos - inSql + 1);
    //printf("1: %s\n", outSql);
8846
    strncat(outSql, subTblName, BUFFER_SIZE - 1);
8847
    //printf("2: %s\n", outSql);
8848
    strncat(outSql, pos+strlen(sourceString), BUFFER_SIZE - 1);
8849
    //printf("3: %s\n", outSql);
H
Hui Li 已提交
8850 8851
}

8852
static void *superTableQuery(void *sarg) {
8853 8854 8855
    char *sqlstr = calloc(1, BUFFER_SIZE);
    assert(sqlstr);

8856
    threadInfo *pThreadInfo = (threadInfo *)sarg;
8857

8858
    setThreadName("superTableQuery");
8859

8860 8861 8862 8863 8864 8865 8866 8867 8868 8869
    if (pThreadInfo->taos == NULL) {
        TAOS * taos = NULL;
        taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                NULL,
                g_queryInfo.port);
        if (taos == NULL) {
            errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
                    pThreadInfo->threadID, taos_errstr(NULL));
8870
            free(sqlstr);
8871 8872 8873 8874
            return NULL;
        } else {
            pThreadInfo->taos = taos;
        }
8875
    }
8876

8877 8878
    uint64_t st = 0;
    uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
8879

8880 8881 8882
    uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
    uint64_t totalQueried = 0;
    uint64_t  startTs = taosGetTimestampMs();
H
Hui Li 已提交
8883

8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894
    uint64_t  lastPrintTime = taosGetTimestampMs();
    while(queryTimes --) {
        if (g_queryInfo.superQueryInfo.queryInterval
                && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
            taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
            //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
        }

        st = taosGetTimestampMs();
        for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
            for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
8895
                memset(sqlstr, 0, BUFFER_SIZE);
8896 8897 8898 8899 8900 8901 8902
                replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
                if (g_queryInfo.superQueryInfo.result[j][0] != '\0') {
                    sprintf(pThreadInfo->filePath, "%s-%d",
                            g_queryInfo.superQueryInfo.result[j],
                            pThreadInfo->threadID);
                }
                selectAndGetResult(pThreadInfo, sqlstr);
8903

8904 8905
                totalQueried++;
                g_queryInfo.superQueryInfo.totalQueried ++;
8906

8907 8908 8909 8910 8911 8912 8913 8914 8915 8916
                int64_t  currentPrintTime = taosGetTimestampMs();
                int64_t  endTs = taosGetTimestampMs();
                if (currentPrintTime - lastPrintTime > 30*1000) {
                    printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
                            pThreadInfo->threadID,
                            totalQueried,
                            (double)(totalQueried/((endTs-startTs)/1000.0)));
                    lastPrintTime = currentPrintTime;
                }
            }
8917
        }
8918 8919 8920 8921 8922 8923
        et = taosGetTimestampMs();
        printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
                taosGetSelfPthreadId(),
                pThreadInfo->start_table_from,
                pThreadInfo->end_table_to,
                (double)(et - st)/1000.0);
H
Hui Li 已提交
8924
    }
8925

8926
    free(sqlstr);
8927
    return NULL;
8928 8929
}

8930
static int queryTestProcess() {
8931

8932 8933 8934
    setupForAnsiEscape();
    printfQueryMeta();
    resetAfterAnsiEscape();
8935

8936 8937 8938 8939 8940 8941 8942
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
            g_queryInfo.user,
            g_queryInfo.password,
            NULL,
            g_queryInfo.port);
    if (taos == NULL) {
8943
        errorPrint("Failed to connect to TDengine, reason:%s\n",
8944
                taos_errstr(NULL));
8945
        exit(EXIT_FAILURE);
8946
    }
8947

8948 8949 8950 8951 8952 8953 8954
    if (0 != g_queryInfo.superQueryInfo.sqlCount) {
        getAllChildNameOfSuperTable(taos,
                g_queryInfo.dbName,
                g_queryInfo.superQueryInfo.sTblName,
                &g_queryInfo.superQueryInfo.childTblName,
                &g_queryInfo.superQueryInfo.childTblCount);
    }
8955

8956
    prompt();
8957

8958 8959 8960
    if (g_args.debug_print || g_args.verbose_print) {
        printfQuerySystemInfo(taos);
    }
8961

8962 8963 8964
    if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
        if (convertHostToServAddr(
                    g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
8965
            ERROR_EXIT("convert host to server address");
8966
    }
8967

8968 8969 8970 8971 8972
    pthread_t  *pids  = NULL;
    threadInfo *infos = NULL;
    //==== create sub threads for query from specify table
    int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
    uint64_t nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
8973

8974
    uint64_t startTs = taosGetTimestampMs();
8975

8976
    if ((nSqlCount > 0) && (nConcurrent > 0)) {
8977

8978 8979
        pids  = calloc(1, nConcurrent * nSqlCount * sizeof(pthread_t));
        infos = calloc(1, nConcurrent * nSqlCount * sizeof(threadInfo));
8980

8981 8982 8983 8984
        if ((NULL == pids) || (NULL == infos)) {
            taos_close(taos);
            ERROR_EXIT("memory allocation failed for create threads\n");
        }
8985

8986 8987 8988 8989 8990 8991 8992 8993 8994
        for (uint64_t i = 0; i < nSqlCount; i++) {
            for (int j = 0; j < nConcurrent; j++) {
                uint64_t seq = i * nConcurrent + j;
                threadInfo *pThreadInfo = infos + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;

                if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) {

8995 8996
                    char sqlStr[TSDB_DB_NAME_LEN + 5];
                    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
8997 8998 8999 9000
                    if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
                        taos_close(taos);
                        free(infos);
                        free(pids);
9001
                        errorPrint2("use database %s failed!\n\n",
9002 9003 9004
                                g_queryInfo.dbName);
                        return -1;
                    }
9005
                }
9006

9007
                pThreadInfo->taos = NULL;// TODO: workaround to use separate taos connection;
9008

9009 9010 9011
                pthread_create(pids + seq, NULL, specifiedTableQuery,
                        pThreadInfo);
            }
9012
        }
9013 9014
    } else {
        g_queryInfo.specifiedQueryInfo.concurrent = 0;
9015 9016
    }

9017
    taos_close(taos);
9018

9019 9020 9021 9022 9023 9024 9025
    pthread_t  *pidsOfSub  = NULL;
    threadInfo *infosOfSub = NULL;
    //==== create sub threads for query from all sub table of the super table
    if ((g_queryInfo.superQueryInfo.sqlCount > 0)
            && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
        pidsOfSub  = calloc(1, g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t));
        infosOfSub = calloc(1, g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo));
9026

9027 9028 9029
        if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
            free(infos);
            free(pids);
9030

9031 9032
            ERROR_EXIT("memory allocation failed for create threads\n");
        }
9033

9034 9035
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
9036

9037 9038 9039 9040 9041
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
9042

9043 9044 9045 9046
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
9047

9048 9049 9050 9051
        uint64_t tableFrom = 0;
        for (int i = 0; i < threads; i++) {
            threadInfo *pThreadInfo = infosOfSub + i;
            pThreadInfo->threadID = i;
9052

9053 9054 9055 9056 9057 9058 9059
            pThreadInfo->start_table_from = tableFrom;
            pThreadInfo->ntables = i<b?a+1:a;
            pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
            tableFrom = pThreadInfo->end_table_to + 1;
            pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
            pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
        }
9060

9061 9062 9063 9064
        g_queryInfo.superQueryInfo.threadCnt = threads;
    } else {
        g_queryInfo.superQueryInfo.threadCnt = 0;
    }
9065

9066 9067 9068 9069 9070 9071
    if ((nSqlCount > 0) && (nConcurrent > 0)) {
        for (int i = 0; i < nConcurrent; i++) {
            for (int j = 0; j < nSqlCount; j++) {
                pthread_join(pids[i * nSqlCount + j], NULL);
            }
        }
9072
    }
S
Shuaiqiang Chang 已提交
9073

9074 9075
    tmfree((char*)pids);
    tmfree((char*)infos);
9076

9077 9078 9079
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
        pthread_join(pidsOfSub[i], NULL);
    }
H
Hui Li 已提交
9080

9081 9082
    tmfree((char*)pidsOfSub);
    tmfree((char*)infosOfSub);
9083

9084 9085
    //  taos_close(taos);// TODO: workaround to use separate taos connection;
    uint64_t endTs = taosGetTimestampMs();
9086

9087 9088
    uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
        g_queryInfo.superQueryInfo.totalQueried;
9089

9090 9091 9092 9093
    fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
            totalQueried,
            (double)(totalQueried/((endTs-startTs)/1000.0)));
    return 0;
9094 9095
}

9096 9097
static void stable_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
9098
    if (res == NULL || taos_errno(res) != 0) {
9099
        errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
9100 9101 9102
                __func__, __LINE__, code, taos_errstr(res));
        return;
    }
9103

9104 9105 9106
    if (param)
        fetchResult(res, (threadInfo *)param);
    // tao_unscribe() will free result.
9107 9108 9109 9110
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
9111
    if (res == NULL || taos_errno(res) != 0) {
9112
        errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
9113 9114 9115
                __func__, __LINE__, code, taos_errstr(res));
        return;
    }
9116

9117 9118 9119
    if (param)
        fetchResult(res, (threadInfo *)param);
    // tao_unscribe() will free result.
H
hzcheng 已提交
9120 9121
}

9122
static TAOS_SUB* subscribeImpl(
9123 9124 9125 9126
        QUERY_CLASS class,
        threadInfo *pThreadInfo,
        char *sql, char* topic, bool restart, uint64_t interval)
{
9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150
    TAOS_SUB* tsub = NULL;

    if ((SPECIFIED_CLASS == class)
            && (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode)) {
        tsub = taos_subscribe(
                pThreadInfo->taos,
                restart,
                topic, sql, specified_sub_callback, (void*)pThreadInfo,
                g_queryInfo.specifiedQueryInfo.subscribeInterval);
    } else if ((STABLE_CLASS == class)
            && (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode)) {
        tsub = taos_subscribe(
                pThreadInfo->taos,
                restart,
                topic, sql, stable_sub_callback, (void*)pThreadInfo,
                g_queryInfo.superQueryInfo.subscribeInterval);
    } else {
        tsub = taos_subscribe(
                pThreadInfo->taos,
                restart,
                topic, sql, NULL, NULL, interval);
    }

    if (tsub == NULL) {
9151
        errorPrint2("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
9152 9153 9154 9155
        return NULL;
    }

    return tsub;
9156
}
H
hzcheng 已提交
9157

9158
static void *superSubscribe(void *sarg) {
9159
    threadInfo *pThreadInfo = (threadInfo *)sarg;
9160 9161 9162
    char *subSqlStr = calloc(1, BUFFER_SIZE);
    assert(subSqlStr);

9163 9164 9165
    TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
    uint64_t tsubSeq;

9166 9167
    setThreadName("superSub");

9168
    if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
9169
        free(subSqlStr);
9170 9171
        errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
                pThreadInfo->ntables, MAX_QUERY_SQL_COUNT);
9172
        exit(EXIT_FAILURE);
9173
    }
9174

9175
    if (pThreadInfo->taos == NULL) {
9176 9177 9178 9179 9180 9181
        pThreadInfo->taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                g_queryInfo.dbName,
                g_queryInfo.port);
        if (pThreadInfo->taos == NULL) {
9182
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
9183
                    pThreadInfo->threadID, taos_errstr(NULL));
9184
            free(subSqlStr);
9185 9186
            return NULL;
        }
9187 9188
    }

9189 9190
    char sqlStr[TSDB_DB_NAME_LEN + 5];
    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
9191 9192
    if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
        taos_close(pThreadInfo->taos);
9193
        errorPrint2("use database %s failed!\n\n",
9194
                g_queryInfo.dbName);
9195
        free(subSqlStr);
9196 9197
        return NULL;
    }
9198

9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209
    char topic[32] = {0};
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
        tsubSeq = i - pThreadInfo->start_table_from;
        verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n",
                __func__, __LINE__,
                pThreadInfo->threadID,
                pThreadInfo->start_table_from,
                pThreadInfo->end_table_to, i);
        sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"",
                i, pThreadInfo->querySeq);
9210
        memset(subSqlStr, 0, BUFFER_SIZE);
9211 9212
        replaceChildTblName(
                g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
9213
                subSqlStr, i);
9214 9215 9216 9217 9218
        if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
            sprintf(pThreadInfo->filePath, "%s-%d",
                    g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                    pThreadInfo->threadID);
        }
9219

9220 9221
        verbosePrint("%s() LN%d, [%d] subSqlStr: %s\n",
                __func__, __LINE__, pThreadInfo->threadID, subSqlStr);
9222 9223
        tsub[tsubSeq] = subscribeImpl(
                STABLE_CLASS,
9224
                pThreadInfo, subSqlStr, topic,
9225 9226 9227 9228
                g_queryInfo.superQueryInfo.subscribeRestart,
                g_queryInfo.superQueryInfo.subscribeInterval);
        if (NULL == tsub[tsubSeq]) {
            taos_close(pThreadInfo->taos);
9229
            free(subSqlStr);
9230 9231 9232
            return NULL;
        }
    }
9233

9234 9235 9236 9237 9238 9239
    // start loop to consume result
    int consumed[MAX_QUERY_SQL_COUNT];
    for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
        consumed[i] = 0;
    }
    TAOS_RES* res = NULL;
9240

9241
    uint64_t st = 0, et = 0;
9242

9243 9244 9245 9246
    while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
            || (g_queryInfo.superQueryInfo.endAfterConsume >
                consumed[pThreadInfo->end_table_to
                - pThreadInfo->start_table_from])) {
9247

9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285
        verbosePrint("super endAfterConsume: %d, consumed: %d\n",
                g_queryInfo.superQueryInfo.endAfterConsume,
                consumed[pThreadInfo->end_table_to
                - pThreadInfo->start_table_from]);
        for (uint64_t i = pThreadInfo->start_table_from;
                i <= pThreadInfo->end_table_to; i++) {
            tsubSeq = i - pThreadInfo->start_table_from;
            if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
                continue;
            }

            st = taosGetTimestampMs();
            performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
            res = taos_consume(tsub[tsubSeq]);
            et = taosGetTimestampMs();
            performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));

            if (res) {
                if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
                    sprintf(pThreadInfo->filePath, "%s-%d",
                            g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                            pThreadInfo->threadID);
                    fetchResult(res, pThreadInfo);
                }
                consumed[tsubSeq] ++;

                if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1)
                        && (consumed[tsubSeq] >=
                            g_queryInfo.superQueryInfo.resubAfterConsume)) {
                    verbosePrint("%s() LN%d, keepProgress:%d, resub super table query: %"PRIu64"\n",
                            __func__, __LINE__,
                            g_queryInfo.superQueryInfo.subscribeKeepProgress,
                            pThreadInfo->querySeq);
                    taos_unsubscribe(tsub[tsubSeq],
                            g_queryInfo.superQueryInfo.subscribeKeepProgress);
                    consumed[tsubSeq]= 0;
                    tsub[tsubSeq] = subscribeImpl(
                            STABLE_CLASS,
9286
                            pThreadInfo, subSqlStr, topic,
9287 9288 9289 9290 9291
                            g_queryInfo.superQueryInfo.subscribeRestart,
                            g_queryInfo.superQueryInfo.subscribeInterval
                            );
                    if (NULL == tsub[tsubSeq]) {
                        taos_close(pThreadInfo->taos);
9292
                        free(subSqlStr);
9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303
                        return NULL;
                    }
                }
            }
        }
    }
    verbosePrint("%s() LN%d, super endAfterConsume: %d, consumed: %d\n",
            __func__, __LINE__,
            g_queryInfo.superQueryInfo.endAfterConsume,
            consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from]);
    taos_free_result(res);
9304

9305 9306
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
9307 9308
        tsubSeq = i - pThreadInfo->start_table_from;
        taos_unsubscribe(tsub[tsubSeq], 0);
H
hzcheng 已提交
9309
    }
9310

9311
    taos_close(pThreadInfo->taos);
9312
    free(subSqlStr);
9313
    return NULL;
H
hzcheng 已提交
9314 9315
}

9316
static void *specifiedSubscribe(void *sarg) {
9317 9318
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    //  TAOS_SUB*  tsub = NULL;
9319

9320
    setThreadName("specSub");
9321

9322
    if (pThreadInfo->taos == NULL) {
9323 9324 9325 9326 9327 9328
        pThreadInfo->taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                g_queryInfo.dbName,
                g_queryInfo.port);
        if (pThreadInfo->taos == NULL) {
9329
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
9330 9331 9332
                    pThreadInfo->threadID, taos_errstr(NULL));
            return NULL;
        }
9333 9334
    }

9335 9336
    char sqlStr[TSDB_DB_NAME_LEN + 5];
    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347
    if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
        taos_close(pThreadInfo->taos);
        return NULL;
    }

    sprintf(g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
            "taosdemo-subscribe-%"PRIu64"-%d",
            pThreadInfo->querySeq,
            pThreadInfo->threadID);
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
        sprintf(pThreadInfo->filePath, "%s-%d",
9348 9349
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362
    }
    g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
            SPECIFIED_CLASS, pThreadInfo,
            g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
            g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
    if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
        taos_close(pThreadInfo->taos);
        return NULL;
    }

    // start loop to consume result
9363

9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419
    g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
    while((g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq] == -1)
            || (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] <
                g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) {

        printf("consumed[%d]: %d, endAfterConsum[%"PRId64"]: %d\n",
                pThreadInfo->threadID,
                g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID],
                pThreadInfo->querySeq,
                g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq]);
        if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
            continue;
        }

        g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
                g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]);
        if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) {
            if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0]
                    != 0) {
                sprintf(pThreadInfo->filePath, "%s-%d",
                        g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                        pThreadInfo->threadID);
            }
            fetchResult(
                    g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID],
                    pThreadInfo);

            g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++;
            if ((g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq] != -1)
                    && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >=
                        g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) {
                printf("keepProgress:%d, resub specified query: %"PRIu64"\n",
                        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress,
                        pThreadInfo->querySeq);
                g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
                taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID],
                        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
                g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] =
                    subscribeImpl(
                            SPECIFIED_CLASS,
                            pThreadInfo,
                            g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
                            g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
                            g_queryInfo.specifiedQueryInfo.subscribeRestart,
                            g_queryInfo.specifiedQueryInfo.subscribeInterval);
                if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
                    taos_close(pThreadInfo->taos);
                    return NULL;
                }
            }
        }
    }
    taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
    taos_close(pThreadInfo->taos);

    return NULL;
H
hzcheng 已提交
9420 9421
}

9422
static int subscribeTestProcess() {
9423 9424 9425 9426 9427 9428 9429 9430 9431 9432
    setupForAnsiEscape();
    printfQueryMeta();
    resetAfterAnsiEscape();

    prompt();

    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
            g_queryInfo.user,
            g_queryInfo.password,
9433
            g_queryInfo.dbName,
9434 9435
            g_queryInfo.port);
    if (taos == NULL) {
9436
        errorPrint2("Failed to connect to TDengine, reason:%s\n",
9437
                taos_errstr(NULL));
9438
        exit(EXIT_FAILURE);
S
Shengliang Guan 已提交
9439
    }
9440

9441 9442 9443 9444 9445 9446
    if (0 != g_queryInfo.superQueryInfo.sqlCount) {
        getAllChildNameOfSuperTable(taos,
                g_queryInfo.dbName,
                g_queryInfo.superQueryInfo.sTblName,
                &g_queryInfo.superQueryInfo.childTblName,
                &g_queryInfo.superQueryInfo.childTblCount);
S
Shengliang Guan 已提交
9447
    }
9448

9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463
    taos_close(taos); // TODO: workaround to use separate taos connection;

    pthread_t  *pids = NULL;
    threadInfo *infos = NULL;

    pthread_t  *pidsOfStable  = NULL;
    threadInfo *infosOfStable = NULL;

    //==== create threads for query for specified table
    if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
        debugPrint("%s() LN%d, sepcified query sqlCount %d.\n",
                __func__, __LINE__,
                g_queryInfo.specifiedQueryInfo.sqlCount);
    } else {
        if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
9464
            errorPrint2("%s() LN%d, sepcified query sqlCount %d.\n",
9465 9466
                    __func__, __LINE__,
                    g_queryInfo.specifiedQueryInfo.sqlCount);
9467
            exit(EXIT_FAILURE);
9468
        }
9469

9470
        pids  = calloc(
9471
                1,
9472 9473 9474 9475
                g_queryInfo.specifiedQueryInfo.sqlCount *
                g_queryInfo.specifiedQueryInfo.concurrent *
                sizeof(pthread_t));
        infos = calloc(
9476
                1,
9477 9478 9479 9480
                g_queryInfo.specifiedQueryInfo.sqlCount *
                g_queryInfo.specifiedQueryInfo.concurrent *
                sizeof(threadInfo));
        if ((NULL == pids) || (NULL == infos)) {
9481
            errorPrint2("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
9482
            exit(EXIT_FAILURE);
9483
        }
9484

9485 9486 9487 9488 9489 9490 9491 9492 9493
        for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
            for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
                uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
                threadInfo *pThreadInfo = infos + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;
                pThreadInfo->taos = NULL;  // TODO: workaround to use separate taos connection;
                pthread_create(pids + seq, NULL, specifiedSubscribe, pThreadInfo);
            }
9494
        }
9495
    }
9496

9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515
    //==== create threads for super table query
    if (g_queryInfo.superQueryInfo.sqlCount <= 0) {
        debugPrint("%s() LN%d, super table query sqlCount %d.\n",
                __func__, __LINE__,
                g_queryInfo.superQueryInfo.sqlCount);
    } else {
        if ((g_queryInfo.superQueryInfo.sqlCount > 0)
                && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
            pidsOfStable  = calloc(
                    1,
                    g_queryInfo.superQueryInfo.sqlCount *
                    g_queryInfo.superQueryInfo.threadCnt *
                    sizeof(pthread_t));
            infosOfStable = calloc(
                    1,
                    g_queryInfo.superQueryInfo.sqlCount *
                    g_queryInfo.superQueryInfo.threadCnt *
                    sizeof(threadInfo));
            if ((NULL == pidsOfStable) || (NULL == infosOfStable)) {
9516
                errorPrint2("%s() LN%d, malloc failed for create threads\n",
9517 9518
                        __func__, __LINE__);
                // taos_close(taos);
9519
                exit(EXIT_FAILURE);
9520
            }
9521

9522 9523
            int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
            int threads = g_queryInfo.superQueryInfo.threadCnt;
9524

9525 9526 9527 9528
            int64_t a = ntables / threads;
            if (a < 1) {
                threads = ntables;
                a = 1;
9529
            }
9530

9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552
            int64_t b = 0;
            if (threads != 0) {
                b = ntables % threads;
            }

            for (uint64_t i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
                uint64_t tableFrom = 0;
                for (int j = 0; j < threads; j++) {
                    uint64_t seq = i * threads + j;
                    threadInfo *pThreadInfo = infosOfStable + seq;
                    pThreadInfo->threadID = seq;
                    pThreadInfo->querySeq = i;

                    pThreadInfo->start_table_from = tableFrom;
                    pThreadInfo->ntables = j<b?a+1:a;
                    pThreadInfo->end_table_to = j<b?tableFrom+a:tableFrom+a-1;
                    tableFrom = pThreadInfo->end_table_to + 1;
                    pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
                    pthread_create(pidsOfStable + seq,
                            NULL, superSubscribe, pThreadInfo);
                }
            }
9553

9554 9555 9556 9557 9558 9559 9560
            g_queryInfo.superQueryInfo.threadCnt = threads;

            for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
                for (int j = 0; j < threads; j++) {
                    uint64_t seq = i * threads + j;
                    pthread_join(pidsOfStable[seq], NULL);
                }
9561 9562
            }
        }
9563
    }
9564

9565 9566 9567 9568 9569
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
            uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
            pthread_join(pids[seq], NULL);
        }
9570
    }
H
hzcheng 已提交
9571

9572 9573
    tmfree((char*)pids);
    tmfree((char*)infos);
H
hzcheng 已提交
9574

9575 9576 9577 9578
    tmfree((char*)pidsOfStable);
    tmfree((char*)infosOfStable);
    //   taos_close(taos);
    return 0;
H
hzcheng 已提交
9579 9580
}

9581
static void initOfInsertMeta() {
9582
    memset(&g_Dbs, 0, sizeof(SDbs));
9583

9584 9585 9586 9587
    // set default values
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
    g_Dbs.port = 6030;
    tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
9588
    tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, SHELL_MAX_PASSWORD_LEN);
9589
    g_Dbs.threadCount = 2;
9590

9591
    g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
9592 9593
}

9594
static void initOfQueryMeta() {
9595
    memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
9596

9597 9598 9599 9600
    // set default values
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
    g_queryInfo.port = 6030;
    tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
9601
    tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, SHELL_MAX_PASSWORD_LEN);
L
Liu Tao 已提交
9602 9603
}

9604
static void setParaFromArg() {
9605 9606 9607 9608 9609
    if (g_args.host) {
        tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
    } else {
        tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
    }
9610

9611 9612 9613
    if (g_args.user) {
        tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
    }
9614

9615
    tstrncpy(g_Dbs.password, g_args.password, SHELL_MAX_PASSWORD_LEN);
L
Liu Tao 已提交
9616

9617 9618 9619
    if (g_args.port) {
        g_Dbs.port = g_args.port;
    }
9620

9621
    g_Dbs.threadCount = g_args.num_of_threads;
9622
    g_Dbs.threadCountForCreateTbl = g_args.num_of_threads;
9623

9624 9625
    g_Dbs.dbCount = 1;
    g_Dbs.db[0].drop = true;
L
Liu Tao 已提交
9626

9627 9628
    tstrncpy(g_Dbs.db[0].dbName, g_args.database, TSDB_DB_NAME_LEN);
    g_Dbs.db[0].dbCfg.replica = g_args.replica;
9629
    tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", SMALL_BUFF_LEN);
9630

9631
    tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
9632

9633 9634
    g_Dbs.use_metric = g_args.use_metric;
    g_Dbs.insert_only = g_args.insert_only;
L
Liu Tao 已提交
9635

9636
    g_Dbs.do_aggreFunc = true;
9637

9638
    char dataString[TSDB_MAX_BYTES_PER_ROW];
9639
    char **data_type = g_args.datatype;
L
Liu Tao 已提交
9640

9641
    memset(dataString, 0, TSDB_MAX_BYTES_PER_ROW);
H
hzcheng 已提交
9642

9643 9644 9645 9646
    if (strcasecmp(data_type[0], "BINARY") == 0
            || strcasecmp(data_type[0], "BOOL") == 0
            || strcasecmp(data_type[0], "NCHAR") == 0 ) {
        g_Dbs.do_aggreFunc = false;
9647
    }
9648

9649 9650 9651 9652 9653
    if (g_args.use_metric) {
        g_Dbs.db[0].superTblCount = 1;
        tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", TSDB_TABLE_NAME_LEN);
        g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
        g_Dbs.threadCount = g_args.num_of_threads;
9654
        g_Dbs.threadCountForCreateTbl = g_args.num_of_threads;
9655
        g_Dbs.asyncMode = g_args.async_mode;
9656

9657 9658 9659 9660 9661
        g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL;
        g_Dbs.db[0].superTbls[0].childTblExists = TBL_NO_EXISTS;
        g_Dbs.db[0].superTbls[0].disorderRange = g_args.disorderRange;
        g_Dbs.db[0].superTbls[0].disorderRatio = g_args.disorderRatio;
        tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
9662 9663
                g_args.tb_prefix, TBNAME_PREFIX_LEN);
        tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", SMALL_BUFF_LEN);
9664

9665 9666 9667 9668 9669 9670 9671
        if (g_args.iface == INTERFACE_BUT) {
            g_Dbs.db[0].superTbls[0].iface = TAOSC_IFACE;
        } else {
            g_Dbs.db[0].superTbls[0].iface = g_args.iface;
        }
        tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
                "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
9672
        g_Dbs.db[0].superTbls[0].timeStampStep = g_args.timestamp_step;
9673

9674 9675
        g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
        g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
9676

9677 9678 9679 9680 9681
        g_Dbs.db[0].superTbls[0].columnCount = 0;
        for (int i = 0; i < MAX_NUM_COLUMNS; i++) {
            if (data_type[i] == NULL) {
                break;
            }
9682

9683
            tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
9684
                    data_type[i], min(DATATYPE_BUFF_LEN, strlen(data_type[i]) + 1));
9685
            g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.binwidth;
9686 9687 9688 9689 9690 9691 9692 9693 9694
            g_Dbs.db[0].superTbls[0].columnCount++;
        }

        if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) {
            g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR;
        } else {
            for (int i = g_Dbs.db[0].superTbls[0].columnCount;
                    i < g_args.num_of_CPR; i++) {
                tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
9695
                        "INT", min(DATATYPE_BUFF_LEN, strlen("INT") + 1));
9696 9697 9698 9699 9700 9701
                g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
                g_Dbs.db[0].superTbls[0].columnCount++;
            }
        }

        tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
9702
                "INT", min(DATATYPE_BUFF_LEN, strlen("INT") + 1));
9703 9704 9705
        g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;

        tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
9706
                "BINARY", min(DATATYPE_BUFF_LEN, strlen("BINARY") + 1));
9707
        g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.binwidth;
9708 9709
        g_Dbs.db[0].superTbls[0].tagCount = 2;
    } else {
9710
        g_Dbs.threadCountForCreateTbl = g_args.num_of_threads;
9711 9712
        g_Dbs.db[0].superTbls[0].tagCount = 0;
    }
9713 9714 9715 9716
}

/* Function to do regular expression check */
static int regexMatch(const char *s, const char *reg, int cflags) {
9717 9718 9719 9720 9721
    regex_t regex;
    char    msgbuf[100] = {0};

    /* Compile regular expression */
    if (regcomp(&regex, reg, cflags) != 0) {
9722
        ERROR_EXIT("Fail to compile regex\n");
9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735
    }

    /* Execute regular expression */
    int reti = regexec(&regex, s, 0, NULL, 0);
    if (!reti) {
        regfree(&regex);
        return 1;
    } else if (reti == REG_NOMATCH) {
        regfree(&regex);
        return 0;
    } else {
        regerror(reti, &regex, msgbuf, sizeof(msgbuf));
        regfree(&regex);
9736 9737
        printf("Regex match failed: %s\n", msgbuf);
        exit(EXIT_FAILURE);
9738 9739
    }

9740 9741 9742 9743
    return 0;
}

static int isCommentLine(char *line) {
9744
    if (line == NULL) return 1;
9745

9746
    return regexMatch(line, "^\\s*#.*", REG_EXTENDED);
9747 9748
}

9749
static void querySqlFile(TAOS* taos, char* sqlFile)
9750
{
9751 9752 9753 9754 9755
    FILE *fp = fopen(sqlFile, "r");
    if (fp == NULL) {
        printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
        return;
    }
9756

9757 9758 9759 9760 9761
    int       read_len = 0;
    char *    cmd = calloc(1, TSDB_MAX_BYTES_PER_ROW);
    size_t    cmd_len = 0;
    char *    line = NULL;
    size_t    line_len = 0;
9762

9763
    double t = taosGetTimestampMs();
9764

9765 9766 9767
    while((read_len = tgetline(&line, &line_len, fp)) != -1) {
        if (read_len >= TSDB_MAX_BYTES_PER_ROW) continue;
        line[--read_len] = '\0';
9768

9769 9770 9771
        if (read_len == 0 || isCommentLine(line)) {  // line starts with #
            continue;
        }
9772

9773 9774 9775 9776 9777 9778
        if (line[read_len - 1] == '\\') {
            line[read_len - 1] = ' ';
            memcpy(cmd + cmd_len, line, read_len);
            cmd_len += read_len;
            continue;
        }
9779

9780 9781
        memcpy(cmd + cmd_len, line, read_len);
        if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
9782
            errorPrint2("%s() LN%d, queryDbExec %s failed!\n",
9783 9784 9785 9786 9787 9788 9789 9790
                    __func__, __LINE__, cmd);
            tmfree(cmd);
            tmfree(line);
            tmfclose(fp);
            return;
        }
        memset(cmd, 0, TSDB_MAX_BYTES_PER_ROW);
        cmd_len = 0;
9791
    }
H
hzcheng 已提交
9792

9793 9794
    t = taosGetTimestampMs() - t;
    printf("run %s took %.6f second(s)\n\n", sqlFile, t);
9795

9796 9797 9798 9799
    tmfree(cmd);
    tmfree(line);
    tmfclose(fp);
    return;
H
hzcheng 已提交
9800 9801
}

9802
static void testMetaFile() {
9803
    if (INSERT_TEST == g_args.test_mode) {
9804 9805
        if (g_Dbs.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
9806

9807
        insertTestProcess();
9808

9809
    } else if (QUERY_TEST == g_args.test_mode) {
9810 9811
        if (g_queryInfo.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
9812

9813
        queryTestProcess();
9814

9815
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
9816 9817
        if (g_queryInfo.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
9818

9819
        subscribeTestProcess();
9820

9821
    }  else {
9822
        ;
9823
    }
9824
}
9825

9826
static void queryResult() {
9827 9828 9829 9830 9831
    // query data

    pthread_t read_id;
    threadInfo *pThreadInfo = calloc(1, sizeof(threadInfo));
    assert(pThreadInfo);
9832
    pThreadInfo->start_time = DEFAULT_START_TIME;  // 2017-07-14 10:40:00.000
9833 9834 9835 9836 9837 9838
    pThreadInfo->start_table_from = 0;

    //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
    if (g_args.use_metric) {
        pThreadInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
        pThreadInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
9839
        pThreadInfo->stbInfo = &g_Dbs.db[0].superTbls[0];
9840
        tstrncpy(pThreadInfo->tb_prefix,
9841
                g_Dbs.db[0].superTbls[0].childTblPrefix, TBNAME_PREFIX_LEN);
9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854
    } else {
        pThreadInfo->ntables = g_args.num_of_tables;
        pThreadInfo->end_table_to = g_args.num_of_tables -1;
        tstrncpy(pThreadInfo->tb_prefix, g_args.tb_prefix, TSDB_TABLE_NAME_LEN);
    }

    pThreadInfo->taos = taos_connect(
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            g_Dbs.db[0].dbName,
            g_Dbs.port);
    if (pThreadInfo->taos == NULL) {
9855
        free(pThreadInfo);
9856
        errorPrint2("Failed to connect to TDengine, reason:%s\n",
9857
                taos_errstr(NULL));
9858
        exit(EXIT_FAILURE);
9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869
    }

    tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);

    if (!g_Dbs.use_metric) {
        pthread_create(&read_id, NULL, readTable, pThreadInfo);
    } else {
        pthread_create(&read_id, NULL, readMetric, pThreadInfo);
    }
    pthread_join(read_id, NULL);
    taos_close(pThreadInfo->taos);
9870
    free(pThreadInfo);
9871 9872
}

9873 9874
static void testCmdLine() {

9875 9876 9877
    if (strlen(configDir)) {
        wordexp_t full_path;
        if (wordexp(configDir, &full_path, 0) != 0) {
9878
            errorPrint("Invalid path %s\n", configDir);
9879 9880 9881 9882
            return;
        }
        taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
        wordfree(&full_path);
9883 9884
    }

9885 9886
    g_args.test_mode = INSERT_TEST;
    insertTestProcess();
9887

9888 9889
    if (false == g_Dbs.insert_only)
        queryResult();
9890 9891
}

9892
int main(int argc, char *argv[]) {
9893
    parse_args(argc, argv, &g_args);
9894

9895
    debugPrint("meta file: %s\n", g_args.metaFile);
9896

9897
    if (g_args.metaFile) {
9898
        g_totalChildTables = 0;
9899 9900
        initOfInsertMeta();
        initOfQueryMeta();
9901

9902 9903 9904 9905
        if (false == getInfoFromJsonFile(g_args.metaFile)) {
            printf("Failed to read %s\n", g_args.metaFile);
            return 1;
        }
9906

9907
        testMetaFile();
9908
    } else {
9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920
        memset(&g_Dbs, 0, sizeof(SDbs));
        setParaFromArg();

        if (NULL != g_args.sqlFile) {
            TAOS* qtaos = taos_connect(
                    g_Dbs.host,
                    g_Dbs.user,
                    g_Dbs.password,
                    g_Dbs.db[0].dbName,
                    g_Dbs.port);
            querySqlFile(qtaos, g_args.sqlFile);
            taos_close(qtaos);
9921

9922 9923 9924
        } else {
            testCmdLine();
        }
9925

9926 9927 9928 9929 9930
        if (g_dupstr)
            free(g_dupstr);
    }

    return 0;
H
hzcheng 已提交
9931
}
9932