taosdemo.c 424.8 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>
23
#include <taoserror.h>
S
slguan 已提交
24
#define _GNU_SOURCE
25 26
#define CURL_STATICLIB

S
TD-1057  
Shengliang Guan 已提交
27
#ifdef LINUX
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#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>
43
#else
44 45
#include <regex.h>
#include <stdio.h>
46
#endif
H
hzcheng 已提交
47

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

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

57 58 59
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

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

62 63
#define STR_INSERT_INTO     "INSERT INTO "

64 65
#define MAX_RECORDS_PER_REQ     32766

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

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

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

79 80
#define DEFAULT_START_TIME 1500000000000

81 82 83 84 85 86 87 88 89 90
#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

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

94 95
#define MAX_DB_COUNT            8
#define MAX_SUPER_TABLE_COUNT   200
96

97
#define MAX_QUERY_SQL_COUNT     100
98

99 100
#define MAX_DATABASE_COUNT      256
#define INPUT_BUF_LEN           256
101

102 103 104 105 106
#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)

107
#define DEFAULT_NTHREADS        8
108
#define DEFAULT_TIMESTAMP_STEP  1
109
#define DEFAULT_INTERLACE_ROWS  0
110
#define DEFAULT_DATATYPE_NUM    1
111
#define DEFAULT_CHILDTABLES     10000
112

113
#define STMT_BIND_PARAM_BATCH   1
114 115 116 117 118 119 120

char* g_sampleDataBuf = NULL;
#if STMT_BIND_PARAM_BATCH == 1
    // bind param batch
char* g_sampleBindBatchArray = NULL;
#endif

121 122 123 124 125 126 127
enum TEST_MODE {
    INSERT_TEST,            // 0
    QUERY_TEST,             // 1
    SUBSCRIBE_TEST,         // 2
    INVAID_TEST
};

128
typedef enum CREATE_SUB_TABLE_MOD_EN {
129 130 131
    PRE_CREATE_SUBTBL,
    AUTO_CREATE_SUBTBL,
    NO_CREATE_SUBTBL
132
} CREATE_SUB_TABLE_MOD_EN;
133

134
typedef enum TABLE_EXISTS_EN {
135 136 137
    TBL_NO_EXISTS,
    TBL_ALREADY_EXISTS,
    TBL_EXISTS_BUTT
138
} TABLE_EXISTS_EN;
139

140
enum enumSYNC_MODE {
141 142 143
    SYNC_MODE,
    ASYNC_MODE,
    MODE_BUT
144
};
145

S
Shuduo Sang 已提交
146
enum enum_TAOS_INTERFACE {
147 148 149
    TAOSC_IFACE,
    REST_IFACE,
    STMT_IFACE,
150 151 152
    INTERFACE_BUT
};

153 154 155 156 157 158
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

S
Shuduo Sang 已提交
159
typedef enum enum_PROGRESSIVE_OR_INTERLACE {
160 161 162
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
163
} PROG_OR_INTERLACE_MODE;
164

165
typedef enum enumQUERY_TYPE {
166 167 168
    NO_INSERT_TYPE,
    INSERT_TYPE,
    QUERY_TYPE_BUT
169
} QUERY_TYPE;
170 171

enum _show_db_index {
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    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
192 193 194 195
};

// -----------------------------------------SHOW TABLES CONFIGURE -------------------------------------
enum _show_stables_index {
196 197 198 199 200 201 202 203
    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
204 205
};

206
enum _describe_table_index {
207 208 209 210 211
    TSDB_DESCRIBE_METRIC_FIELD_INDEX,
    TSDB_DESCRIBE_METRIC_TYPE_INDEX,
    TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
    TSDB_DESCRIBE_METRIC_NOTE_INDEX,
    TSDB_MAX_DESCRIBE_METRIC
212 213
};

H
hzcheng 已提交
214
/* Used by main to communicate with parse_opt. */
215 216
static char *g_dupstr = NULL;

217
typedef struct SArguments_S {
218
    char     *metaFile;
219
    uint32_t test_mode;
220
    char     *host;
221 222 223
    uint16_t port;
    uint16_t iface;
    char *   user;
224
    char     password[SHELL_MAX_PASSWORD_LEN];
225 226 227 228 229 230
    char *   database;
    int      replica;
    char *   tb_prefix;
    char *   sqlFile;
    bool     use_metric;
    bool     drop_database;
231
    bool     aggr_func;
232 233 234 235 236 237
    bool     answer_yes;
    bool     debug_print;
    bool     verbose_print;
    bool     performance_print;
    char *   output_file;
    bool     async_mode;
238 239
    char     data_type[MAX_NUM_COLUMNS+1];
    char     *dataType[MAX_NUM_COLUMNS+1];
240
    uint32_t binwidth;
241 242 243
    uint32_t columnCount;
    uint64_t lenOfOneRow;
    uint32_t nthreads;
244
    uint64_t insert_interval;
245
    uint64_t timestamp_step;
246
    int64_t  query_times;
247
    uint32_t interlaceRows;
248
    uint32_t reqPerReq;                  // num_of_records_per_req
249
    uint64_t max_sql_len;
250 251
    int64_t  ntables;
    int64_t  insertRows;
252 253
    int      abort;
    uint32_t disorderRatio;               // 0: no disorder, >0: x%
254
    int      disorderRange;               // ms, us or ns. according to database precision
255 256 257 258
    uint32_t method_of_delete;
    uint64_t totalInsertRows;
    uint64_t totalAffectedRows;
    bool     demo_mode;                  // use default column name and semi-random data
259 260 261
} SArguments;

typedef struct SColumn_S {
262 263 264 265 266
    char        field[TSDB_COL_NAME_LEN];
    char        data_type;
    char        dataType[DATATYPE_BUFF_LEN];
    uint32_t    dataLen;
    char        note[NOTE_BUFF_LEN];
267 268 269
} StrColumn;

typedef struct SSuperTable_S {
270
    char         stbName[TSDB_TABLE_NAME_LEN];
271 272
    char         dataSource[SMALL_BUFF_LEN];  // rand_gen or sample
    char         childTblPrefix[TBNAME_PREFIX_LEN];
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
    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];
291
    char         sampleFormat[SMALL_BUFF_LEN];  // csv, json
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
    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;

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

312 313 314 315
#if STMT_BIND_PARAM_BATCH == 1
    // bind param batch
    char        *sampleBindBatchArray;
#endif
316 317 318
    // statistics
    uint64_t     totalInsertRows;
    uint64_t     totalAffectedRows;
319 320 321
} SSuperTable;

typedef struct {
322 323 324 325 326 327 328
    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;
329
    char     keeplist[64];
330 331 332 333 334 335 336 337
    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;
338
    char     precision[SMALL_BUFF_LEN];   // time resolution
339 340
    int8_t   update;
    char     status[16];
341 342
} SDbInfo;

343
typedef struct SDbCfg_S {
344 345 346 347 348 349 350 351 352 353 354 355 356 357
    //  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;
358
    char      precision[SMALL_BUFF_LEN];
359 360 361
} SDbCfg;

typedef struct SDataBase_S {
362 363 364 365 366
    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];
367 368 369
} SDataBase;

typedef struct SDbs_S {
370 371 372 373 374 375
    char        cfgDir[MAX_FILE_NAME_LEN];
    char        host[MAX_HOSTNAME_SIZE];
    struct      sockaddr_in serv_addr;

    uint16_t    port;
    char        user[MAX_USERNAME_SIZE];
376
    char        password[SHELL_MAX_PASSWORD_LEN];
377 378
    char        resultFile[MAX_FILE_NAME_LEN];
    bool        use_metric;
379
    bool        aggr_func;
380 381 382
    bool        asyncMode;

    uint32_t    threadCount;
383
    uint32_t    threadCountForCreateTbl;
384 385 386 387 388 389
    uint32_t    dbCount;
    SDataBase   db[MAX_DB_COUNT];

    // statistics
    uint64_t    totalInsertRows;
    uint64_t    totalAffectedRows;
390

391 392
} SDbs;

393
typedef struct SpecifiedQueryInfo_S {
394
    uint64_t     queryInterval;  // 0: unlimited  > 0   loop/s
395 396 397 398 399 400 401
    uint32_t     concurrent;
    int          sqlCount;
    uint32_t     asyncMode; // 0: sync, 1: async
    uint64_t     subscribeInterval; // ms
    uint64_t     queryTimes;
    bool         subscribeRestart;
    int          subscribeKeepProgress;
402
    char         sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
403 404 405 406 407 408 409 410
    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;
411
} SpecifiedQueryInfo;
412

413
typedef struct SuperQueryInfo_S {
414
    char         stbName[TSDB_TABLE_NAME_LEN];
415
    uint64_t     queryInterval;  // 0: unlimited  > 0   loop/s
416 417 418 419 420 421 422
    uint32_t     threadCnt;
    uint32_t     asyncMode; // 0: sync, 1: async
    uint64_t     subscribeInterval; // ms
    bool         subscribeRestart;
    int          subscribeKeepProgress;
    uint64_t     queryTimes;
    int64_t      childTblCount;
423
    char         childTblPrefix[TBNAME_PREFIX_LEN];    // 20 characters reserved for seq
424
    int          sqlCount;
425
    char         sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
426 427 428 429 430 431 432
    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;
433
} SuperQueryInfo;
434 435

typedef struct SQueryMetaInfo_S {
436 437 438 439 440
    char         cfgDir[MAX_FILE_NAME_LEN];
    char         host[MAX_HOSTNAME_SIZE];
    uint16_t     port;
    struct       sockaddr_in serv_addr;
    char         user[MAX_USERNAME_SIZE];
441
    char         password[SHELL_MAX_PASSWORD_LEN];
442
    char         dbName[TSDB_DB_NAME_LEN];
443
    char         queryMode[SMALL_BUFF_LEN];  // taosc, rest
444 445 446 447

    SpecifiedQueryInfo  specifiedQueryInfo;
    SuperQueryInfo      superQueryInfo;
    uint64_t     totalQueried;
448 449 450
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
451 452
    TAOS *    taos;
    TAOS_STMT *stmt;
453
    int64_t     *bind_ts;
454 455 456 457 458 459 460 461 462

#if STMT_BIND_PARAM_BATCH == 1
    int64_t     *bind_ts_array;
    char        *bindParams;
    char        *is_null;
#else
    char*       sampleBindArray;
#endif

463 464 465 466 467 468 469 470 471
    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;
472
    int64_t   tables_created;
473 474 475 476
    uint64_t  data_of_rate;
    int64_t   start_time;
    char*     cols;
    bool      use_metric;
477
    SSuperTable* stbInfo;
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    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;
503

504 505
} threadInfo;

506
#ifdef WINDOWS
507 508
#define _CRT_RAND_S

509
#include <windows.h>
510 511 512 513 514
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
515 516
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
517
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
518
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
519 520 521 522

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

523
static void setupForAnsiEscape(void) {
524 525
    DWORD mode = 0;
    g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
526

527 528 529
    if(g_stdoutHandle == INVALID_HANDLE_VALUE) {
        exit(GetLastError());
    }
530

531 532 533
    if(!GetConsoleMode(g_stdoutHandle, &mode)) {
        exit(GetLastError());
    }
534

535
    g_consoleMode = mode;
536

537 538
    // Enable ANSI escape codes
    mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
539

540 541 542
    if(!SetConsoleMode(g_stdoutHandle, mode)) {
        exit(GetLastError());
    }
543 544
}

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

549 550 551 552
    // Reset console mode
    if(!SetConsoleMode(g_stdoutHandle, g_consoleMode)) {
        exit(GetLastError());
    }
553
}
554

555
static int taosRandom()
556 557 558 559 560 561
{
    int number;
    rand_s(&number);

    return number;
}
562
#else   // Not windows
563
static void setupForAnsiEscape(void) {}
564

565
static void resetAfterAnsiEscape(void) {
566 567
    // Reset colors
    printf("\x1b[0m");
568
}
569

570 571
#include <time.h>

572
static int taosRandom()
573
{
574
    return rand();
575 576
}

577
#endif // ifdef Windows
578

579
static void prompt();
580
static int createDatabasesAndStables();
581
static void createChildTables();
582
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
583
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
584
        uint16_t port, char* sqlstr, threadInfo *pThreadInfo);
585 586
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
        int disorderRatio, int disorderRange);
587 588
static bool getInfoFromJsonFile(char* file);
static void init_rand_data();
589 590 591

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

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
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;

608 609 610
char    *g_aggreFuncDemo[] = {"*", "count(*)", "avg(current)", "sum(current)",
    "max(current)", "min(current)", "first(current)", "last(current)"};

611 612
char    *g_aggreFunc[] = {"*", "count(*)", "avg(C0)", "sum(C0)",
    "max(C0)", "min(C0)", "first(C0)", "last(C0)"};
613

614
SArguments g_args = {
615 616 617 618 619 620
    NULL,           // metaFile
    0,              // test_mode
    "localhost",    // host
    6030,           // port
    INTERFACE_BUT,  // iface
    "root",         // user
621 622 623
#ifdef _TD_POWER_
    "powerdb",      // password
#elif (_TD_TQ_ == true)
624
    "tqueue",       // password
625 626
#elif (_TD_PRO_ == true)
    "prodb",       // password
627
#else
628
    "taosdata",     // password
629
#endif
630 631
    "test",         // database
    1,              // replica
632 633 634 635
    "d",             // tb_prefix
    NULL,            // sqlFile
    true,            // use_metric
    true,            // drop_database
636
    false,           // aggr_func
637 638 639 640 641 642
    false,           // debug_print
    false,           // verbose_print
    false,           // performance statistic print
    false,           // answer_yes;
    "./output.txt",  // output_file
    0,               // mode : sync or async
643 644 645
    {TSDB_DATA_TYPE_FLOAT,
    TSDB_DATA_TYPE_INT,
    TSDB_DATA_TYPE_FLOAT},
646
    {
647 648 649
        "FLOAT",         // dataType
        "INT",           // dataType
        "FLOAT",         // dataType. demo mode has 3 columns
650
    },
651
    64,              // binwidth
652 653
    4,               // columnCount, timestamp + float + int + float
    20 + FLOAT_BUFF_LEN + INT_BUFF_LEN + FLOAT_BUFF_LEN, // lenOfOneRow
654
    DEFAULT_NTHREADS,// nthreads
655
    0,               // insert_interval
656
    DEFAULT_TIMESTAMP_STEP, // timestamp_step
657
    1,               // query_times
658
    DEFAULT_INTERLACE_ROWS, // interlaceRows;
659
    30000,           // reqPerReq
660
    (1024*1024),     // max_sql_len
661 662
    DEFAULT_CHILDTABLES,    // ntables
    10000,           // insertRows
663 664 665 666 667 668 669
    0,               // abort
    0,               // disorderRatio
    1000,            // disorderRange
    1,               // method_of_delete
    0,               // totalInsertRows;
    0,               // totalAffectedRows;
    true,            // demo_mode;
670 671 672
};

static SDbs            g_Dbs;
673
static int64_t         g_totalChildTables = DEFAULT_CHILDTABLES;
674
static int64_t         g_actualChildTables = 0;
675 676 677
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

678 679 680 681
#if _MSC_VER <= 1900
#define __func__ __FUNCTION__
#endif

682
#define debugPrint(fmt, ...) \
683
    do { if (g_args.debug_print || g_args.verbose_print) \
684
        fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
685

686
#define verbosePrint(fmt, ...) \
687 688
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
689

690 691
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
692
        fprintf(stderr, "PERF: "fmt, __VA_ARGS__); } while(0)
693

694
#define errorPrint(fmt, ...) \
695 696 697 698 699 700 701
    do {\
        fprintf(stderr, " \033[31m");\
        fprintf(stderr, "ERROR: "fmt, __VA_ARGS__);\
        fprintf(stderr, " \033[0m");\
    } while(0)

#define errorPrint2(fmt, ...) \
702 703 704 705 706 707 708 709 710 711 712 713 714
    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");\
715
        errorPrint(fmt, __VA_ARGS__);\
716
    } while(0)
717

718 719 720
// for strncpy buffer overflow
#define min(a, b) (((a) < (b)) ? (a) : (b))

721

722
///////////////////////////////////////////////////
H
hzcheng 已提交
723

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

726 727 728 729 730 731 732 733
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

734
#ifndef TAOSDEMO_STATUS
735 736 737 738 739 740 741 742 743
#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) {
744
        printf("taosdemo version %s-%s\n",
745 746
                tdengine_ver, taosdemo_ver);
    } else {
747
        printf("taosdemo version %s-%s, status:%s\n",
748 749 750 751
                tdengine_ver, taosdemo_ver, taosdemo_status);
    }
}

752
static void printHelp() {
753 754 755
    char indent[10] = "  ";
    printf("%s\n\n", "Usage: taosdemo [OPTION...]");
    printf("%s%s%s%s\n", indent, "-f, --file=FILE", "\t\t",
756
            "The meta file to the execution procedure.");
757 758
    printf("%s%s%s%s\n", indent, "-u, --user=USER", "\t\t",
            "The user name to use when connecting to the server.");
759
#ifdef _TD_POWER_
760
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
761
            "The password to use when connecting to the server. By default is 'powerdb'");
762
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
763
            "Configuration directory. By default is '/etc/power/'.");
764
#elif (_TD_TQ_ == true)
765
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
766
            "The password to use when connecting to the server. By default is 'tqueue'");
767
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
768
            "Configuration directory. By default is '/etc/tq/'.");
769 770 771 772 773
#elif (_TD_PRO_ == true)
    printf("%s%s%s%s\n", indent, "-p, --password", "\t\t",
            "The password to use when connecting to the server. By default is 'prodb'");
    printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t",
            "Configuration directory. By default is '/etc/ProDB/'.");
774
#else
775 776 777 778
    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.");
779
#endif
780 781 782 783 784
    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",
785
            "The interface (taosc, rest, and stmt) taosdemo uses. By default use 'taosc'.");
786
    printf("%s%s%s%s\n", indent, "-d, --database=DATABASE", "\t",
787
            "Destination database. By default is 'test'.");
788
    printf("%s%s%s%s\n", indent, "-a, --replica=REPLICA", "\t\t",
789
            "Set the replica parameters of the database, By default use 1, min: 1, max: 3.");
790
    printf("%s%s%s%s\n", indent, "-m, --table-prefix=TABLEPREFIX", "\t",
791
            "Table prefix name. By default use 'd'.");
792 793
    printf("%s%s%s%s\n", indent, "-s, --sql-file=FILE", "\t\t",
            "The select sql file.");
794 795
    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",
796
            "Direct output to the named file. By default use './output.txt'.");
797
    printf("%s%s%s%s\n", indent, "-q, --query-mode=MODE", "\t\t",
798
            "Query mode -- 0: SYNC, 1: ASYNC. By default use SYNC.");
799
    printf("%s%s%s%s\n", indent, "-b, --data-type=DATATYPE", "\t",
800
            "The data_type of columns, By default use: FLOAT, INT, FLOAT.");
801
    printf("%s%s%s%s%d\n", indent, "-w, --binwidth=WIDTH", "\t\t",
802
            "The width of data_type 'BINARY' or 'NCHAR'. By default use ",
803 804
            g_args.binwidth);
    printf("%s%s%s%s%d%s%d\n", indent, "-l, --columns=COLUMNS", "\t\t",
805
            "The number of columns per record. Demo mode by default is ",
806
            DEFAULT_DATATYPE_NUM,
807
            " (float, int, float). Max values is ",
808 809
            MAX_NUM_COLUMNS);
    printf("%s%s%s%s\n", indent, indent, indent,
810
            "\t\t\t\tAll of the new column(s) type is INT. If use -b to specify column type, -l will be ignored.");
811 812
    printf("%s%s%s%s%d.\n", indent, "-T, --threads=NUMBER", "\t\t",
            "The number of threads. By default use ", DEFAULT_NTHREADS);
813
    printf("%s%s%s%s\n", indent, "-i, --insert-interval=NUMBER", "\t",
814
            "The sleep time (ms) between insertion. By default is 0.");
815
    printf("%s%s%s%s%d.\n", indent, "-S, --time-step=TIME_STEP", "\t",
816
            "The timestamp step between insertion. By default is ",
817
            DEFAULT_TIMESTAMP_STEP);
818
    printf("%s%s%s%s%d.\n", indent, "-B, --interlace-rows=NUMBER", "\t",
819
            "The interlace rows of insertion. By default is ",
820 821
            DEFAULT_INTERLACE_ROWS);
    printf("%s%s%s%s\n", indent, "-r, --rec-per-req=NUMBER", "\t",
822
            "The number of records per request. By default is 30000.");
823
    printf("%s%s%s%s\n", indent, "-t, --tables=NUMBER", "\t\t",
824
            "The number of tables. By default is 10000.");
825
    printf("%s%s%s%s\n", indent, "-n, --records=NUMBER", "\t\t",
826
            "The number of records per table. By default is 10000.");
827
    printf("%s%s%s%s\n", indent, "-M, --random", "\t\t\t",
828
            "The value of records generated are totally random.");
829 830 831 832
    printf("%s\n", "\t\t\t\tBy default to simulate power equipment scenario.");
    printf("%s%s%s%s\n", indent, "-x, --aggr-func", "\t\t",
            "Test aggregation functions after insertion.");
    printf("%s%s%s%s\n", indent, "-y, --answer-yes", "\t\t", "Input yes for prompt.");
833
    printf("%s%s%s%s\n", indent, "-O, --disorder=NUMBER", "\t\t",
834
            "Insert order mode--0: In order, 1 ~ 50: disorder ratio. By default is in order.");
835
    printf("%s%s%s%s\n", indent, "-R, --disorder-range=NUMBER", "\t",
836
            "Out of order data's range. Unit is ms. By default is 1000.");
837
    printf("%s%s%s%s\n", indent, "-g, --debug", "\t\t\t",
838
            "Print debug info.");
839 840 841 842
    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");
843
    printf("%s%s\n", indent, "-V, --version\t\t\tPrint program version.");
844 845
    /*    printf("%s%s%s%s\n", indent, "-D", indent,
          "Delete database if exists. 0: no, 1: yes, default is 1");
846
          */
847 848 849 850
    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");
851 852
}

853 854
static bool isStringNumber(char *input)
{
855 856 857 858
    int len = strlen(input);
    if (0 == len) {
        return false;
    }
859

860 861 862 863
    for (int i = 0; i < len; i++) {
        if (!isdigit(input[i]))
            return false;
    }
864

865
    return true;
866 867
}

868 869 870 871 872 873
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");
}

874
static void errorUnrecognized(char *program, char *wrong_arg)
875 876 877 878 879
{
    fprintf(stderr, "%s: unrecognized options '%s'\n", program, wrong_arg);
    fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n");
}

880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
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");
}

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

909
    for (int i = 1; i < argc; i++) {
910
        if ((0 == strncmp(argv[i], "-f", strlen("-f")))
911
                || (0 == strncmp(argv[i], "--file", strlen("--file")))) {
912
            arguments->demo_mode = false;
913

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

1426
            g_totalChildTables = arguments->ntables;
1427
        } else if ((0 == strncmp(argv[i], "-n", strlen("-n")))
1428 1429 1430 1431 1432 1433 1434 1435 1436
                || (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);
                }
1437
                arguments->insertRows = atoi(argv[++i]);
1438 1439
            } else if (0 == strncmp(argv[i], "--records=", strlen("--records="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--records=")))) {
1440
                    arguments->insertRows = atoi((char *)(argv[i]+strlen("--records=")));
1441 1442 1443 1444
                } else {
                    errorPrintReqArg2(argv[0], "--records");
                    exit(EXIT_FAILURE);
                }
1445 1446
            } else if (0 == strncmp(argv[i], "-n", strlen("-n"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-n")))) {
1447
                    arguments->insertRows = atoi((char *)(argv[i]+strlen("-n")));
1448
                } else {
1449
                    errorPrintReqArg2(argv[0], "-n");
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
                    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);
                }
1460
                arguments->insertRows = atoi(argv[++i]);
1461
            } else {
1462
                errorUnrecognized(argv[0], argv[i]);
1463
                exit(EXIT_FAILURE);
1464
            }
1465
        } else if ((0 == strncmp(argv[i], "-d", strlen("-d")))
1466 1467 1468
                || (0 == strncmp(argv[i], "--database", strlen("--database")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
1469
                    errorPrintReqArg(argv[0], "d");
1470 1471 1472 1473 1474
                    exit(EXIT_FAILURE);
                }
                arguments->database = argv[++i];
            } else if (0 == strncmp(argv[i], "--database=", strlen("--database="))) {
                arguments->output_file = (char *)(argv[i] + strlen("--database="));
1475 1476 1477 1478 1479 1480 1481 1482 1483
            } 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 {
1484
                errorUnrecognized(argv[0], argv[i]);
1485
                exit(EXIT_FAILURE);
1486
            }
1487
        } else if ((0 == strncmp(argv[i], "-l", strlen("-l")))
1488
                || (0 == strncmp(argv[i], "--columns", strlen("--columns")))) {
1489
            arguments->demo_mode = false;
1490 1491 1492 1493 1494 1495 1496 1497
            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);
                }
1498
                arguments->columnCount = atoi(argv[++i]);
1499 1500
            } else if (0 == strncmp(argv[i], "--columns=", strlen("--columns="))) {
                if (isStringNumber((char *)(argv[i] + strlen("--columns=")))) {
1501
                    arguments->columnCount = atoi((char *)(argv[i]+strlen("--columns=")));
1502 1503 1504 1505 1506 1507
                } else {
                    errorPrintReqArg2(argv[0], "--columns");
                    exit(EXIT_FAILURE);
                }
            } else if (0 == strncmp(argv[i], "-l", strlen("-l"))) {
                if (isStringNumber((char *)(argv[i] + strlen("-l")))) {
1508
                    arguments->columnCount = atoi((char *)(argv[i]+strlen("-l")));
1509
                } else {
1510 1511 1512 1513 1514 1515 1516 1517
                    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])) {
1518
                    errorPrintReqArg2(argv[0], "--columns");
1519 1520
                    exit(EXIT_FAILURE);
                }
1521
                arguments->columnCount = atoi(argv[++i]);
1522
            } else {
1523
                errorUnrecognized(argv[0], argv[i]);
1524
                exit(EXIT_FAILURE);
1525
            }
1526

1527
            if (arguments->columnCount > MAX_NUM_COLUMNS) {
1528
                printf("WARNING: max acceptable columns count is %d\n", MAX_NUM_COLUMNS);
1529
                prompt();
1530
                arguments->columnCount = MAX_NUM_COLUMNS;
1531
            }
1532

1533 1534 1535
            for (int col = DEFAULT_DATATYPE_NUM; col < arguments->columnCount; col ++) {
                arguments->dataType[col] = "INT";
                arguments->data_type[col] = TSDB_DATA_TYPE_INT;
1536
            }
1537 1538 1539
            for (int col = arguments->columnCount; col < MAX_NUM_COLUMNS; col++) {
                arguments->dataType[col] = NULL;
                arguments->data_type[col] = TSDB_DATA_TYPE_NULL;
1540
            }
1541
        } else if ((0 == strncmp(argv[i], "-b", strlen("-b")))
1542
                || (0 == strncmp(argv[i], "--data-type", strlen("--data-type")))) {
1543
            arguments->demo_mode = false;
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553

            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="));
1554 1555 1556 1557 1558 1559 1560 1561 1562
            } 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 {
1563
                errorUnrecognized(argv[0], argv[i]);
1564
                exit(EXIT_FAILURE);
1565
            }
1566 1567

            if (strstr(dataType, ",") == NULL) {
1568
                // only one col
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
                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")) {
1579 1580 1581 1582
                    printHelp();
                    errorPrint("%s", "-b: Invalid data_type!\n");
                    exit(EXIT_FAILURE);
                }
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
                arguments->dataType[0] = dataType;
                if (0 == strcasecmp(dataType, "INT")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_INT;
                } else if (0 == strcasecmp(dataType, "TINYINT")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_TINYINT;
                } else if (0 == strcasecmp(dataType, "SMALLINT")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_SMALLINT;
                } else if (0 == strcasecmp(dataType, "BIGINT")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_BIGINT;
                } else if (0 == strcasecmp(dataType, "FLOAT")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_FLOAT;
                } else if (0 == strcasecmp(dataType, "DOUBLE")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_DOUBLE;
                } else if (0 == strcasecmp(dataType, "BINARY")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_BINARY;
                } else if (0 == strcasecmp(dataType, "NCHAR")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_NCHAR;
                } else if (0 == strcasecmp(dataType, "BOOL")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_BOOL;
                } else if (0 == strcasecmp(dataType, "TIMESTAMP")) {
                    arguments->data_type[0] = TSDB_DATA_TYPE_TIMESTAMP;
                } else {
                    arguments->data_type[0] = TSDB_DATA_TYPE_NULL;
                }
                arguments->dataType[1] = NULL;
                arguments->data_type[1] = TSDB_DATA_TYPE_NULL;
1609 1610 1611
            } else {
                // more than one col
                int index = 0;
1612
                g_dupstr = strdup(dataType);
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630
                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);
                    }
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656

                    if (0 == strcasecmp(token, "INT")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_INT;
                    } else if (0 == strcasecmp(token, "FLOAT")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_FLOAT;
                    } else if (0 == strcasecmp(token, "SMALLINT")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_SMALLINT;
                    } else if (0 == strcasecmp(token, "BIGINT")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_BIGINT;
                    } else if (0 == strcasecmp(token, "DOUBLE")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_FLOAT;
                    } else if (0 == strcasecmp(token, "TINYINT")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_TINYINT;
                    } else if (0 == strcasecmp(token, "BINARY")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_BINARY;
                    } else if (0 == strcasecmp(token, "NCHAR")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_NCHAR;
                    } else if (0 == strcasecmp(token, "BOOL")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_BOOL;
                    } else if (0 == strcasecmp(token, "TIMESTAMP")) {
                        arguments->data_type[index] = TSDB_DATA_TYPE_TIMESTAMP;
                    } else {
                        arguments->data_type[index] = TSDB_DATA_TYPE_NULL;
                    }
                    arguments->dataType[index] = token;
                    index ++;
1657
                    token = strsep(&running, ",");
1658
                    if (index >= MAX_NUM_COLUMNS) break;
1659
                }
1660 1661
                arguments->dataType[index] = NULL;
                arguments->data_type[index] = TSDB_DATA_TYPE_NULL;
1662
            }
1663
        } else if ((0 == strncmp(argv[i], "-w", strlen("-w")))
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
                || (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);
                }
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
            } 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 {
1698
                errorUnrecognized(argv[0], argv[i]);
1699
                exit(EXIT_FAILURE);
1700
            }
1701
        } else if ((0 == strncmp(argv[i], "-m", strlen("-m")))
1702 1703 1704
                || (0 == strncmp(argv[i], "--table-prefix", strlen("--table-prefix")))) {
            if (2 == strlen(argv[i])) {
                if (argc == i+1) {
1705
                    errorPrintReqArg(argv[0], "m");
1706 1707 1708 1709 1710
                    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="));
1711 1712 1713 1714 1715 1716 1717 1718 1719
            } 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 {
1720
                errorUnrecognized(argv[0], argv[i]);
1721
                exit(EXIT_FAILURE);
1722
            }
1723 1724
        } else if ((strcmp(argv[i], "-N") == 0)
                || (0 == strcmp(argv[i], "--normal-table"))) {
1725
            arguments->demo_mode = false;
1726
            arguments->use_metric = false;
1727 1728
        } else if ((strcmp(argv[i], "-M") == 0)
                || (0 == strcmp(argv[i], "--random"))) {
1729
            arguments->demo_mode = false;
1730
        } else if ((strcmp(argv[i], "-x") == 0)
1731 1732
                || (0 == strcmp(argv[i], "--aggr-func"))) {
            arguments->aggr_func = true;
1733 1734
        } else if ((strcmp(argv[i], "-y") == 0)
                || (0 == strcmp(argv[i], "--answer-yes"))) {
1735
            arguments->answer_yes = true;
1736 1737
        } else if ((strcmp(argv[i], "-g") == 0)
                || (0 == strcmp(argv[i], "--debug"))) {
1738 1739 1740
            arguments->debug_print = true;
        } else if (strcmp(argv[i], "-gg") == 0) {
            arguments->verbose_print = true;
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
        } 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 {
1786
                errorUnrecognized(argv[0], argv[i]);
1787 1788
                exit(EXIT_FAILURE);
            }
1789
        } else if ((0 == strncmp(argv[i], "-O", strlen("-O")))
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
                || (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);
                }
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
            } 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 {
1824
                errorUnrecognized(argv[0], argv[i]);
1825
                exit(EXIT_FAILURE);
1826
            }
1827

1828
            if (arguments->disorderRatio > 50) {
1829 1830
                errorPrint("Invalid disorder ratio %d, will be set to %d\n",
                        arguments->disorderRatio, 50);
1831 1832
                arguments->disorderRatio = 50;
            }
1833

1834
            if (arguments->disorderRatio < 0) {
1835 1836
                errorPrint("Invalid disorder ratio %d, will be set to %d\n",
                        arguments->disorderRatio, 0);
1837 1838
                arguments->disorderRatio = 0;
            }
1839
        } else if ((0 == strncmp(argv[i], "-a", strlen("-a")))
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859
                || (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);
                }
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877
            } 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 {
1878
                errorUnrecognized(argv[0], argv[i]);
1879
                exit(EXIT_FAILURE);
1880
            }
1881

1882
            if (arguments->replica > 3 || arguments->replica < 1) {
1883 1884
                errorPrint("Invalid replica value %d, will be set to %d\n",
                        arguments->replica, 1);
1885 1886 1887 1888 1889
                arguments->replica = 1;
            }
        } else if (strcmp(argv[i], "-D") == 0) {
            arguments->method_of_delete = atoi(argv[++i]);
            if (arguments->method_of_delete > 3) {
1890
                errorPrint("%s", "\n\t-D need a value (0~3) number following!\n");
1891 1892
                exit(EXIT_FAILURE);
            }
1893 1894
        } else if ((strcmp(argv[i], "--version") == 0)
                || (strcmp(argv[i], "-V") == 0)) {
1895 1896
            printVersion();
            exit(0);
1897 1898
        } else if ((strcmp(argv[i], "--help") == 0)
                || (strcmp(argv[i], "-?") == 0)) {
1899 1900
            printHelp();
            exit(0);
1901 1902 1903 1904
        } 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\
1905
                    [-b DATATYPES] [-w WIDTH_OF_BINARY] [-l COLUMNS] [-T THREADNUMBER]\n\
1906 1907 1908 1909
                    [-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);
1910
        } else {
1911 1912
            // to simulate argp_option output
            if (strlen(argv[i]) > 2) {
1913 1914 1915 1916 1917 1918 1919 1920 1921
                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]);
                }
1922 1923 1924 1925 1926
            } 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");
1927 1928
            exit(EXIT_FAILURE);
        }
S
TD-1057  
Shengliang Guan 已提交
1929
    }
1930

1931
    int columnCount;
1932
    for (columnCount = 0; columnCount < MAX_NUM_COLUMNS; columnCount ++) {
1933
        if (g_args.dataType[columnCount] == NULL) {
1934 1935
            break;
        }
1936 1937
    }

1938
    if (0 == columnCount) {
1939
        ERROR_EXIT("data type error!");
1940
    }
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
    g_args.columnCount = columnCount;

    g_args.lenOfOneRow = 20; // timestamp
    for (int c = 0; c < g_args.columnCount; c++) {
        switch(g_args.data_type[c]) {
            case TSDB_DATA_TYPE_BINARY:
                g_args.lenOfOneRow += g_args.binwidth + 3;
                break;

            case TSDB_DATA_TYPE_NCHAR:
                g_args.lenOfOneRow += g_args.binwidth + 3;
                break;

            case TSDB_DATA_TYPE_INT:
                g_args.lenOfOneRow += INT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_BIGINT:
                g_args.lenOfOneRow += BIGINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_SMALLINT:
                g_args.lenOfOneRow += SMALLINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TINYINT:
                g_args.lenOfOneRow += TINYINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_BOOL:
                g_args.lenOfOneRow += BOOL_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_FLOAT:
                g_args.lenOfOneRow += FLOAT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_DOUBLE:
                g_args.lenOfOneRow += DOUBLE_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TIMESTAMP:
                g_args.lenOfOneRow += TIMESTAMP_BUFF_LEN;
                break;

            default:
                errorPrint2("get error data type : %s\n", g_args.dataType[c]);
                exit(EXIT_FAILURE);
        }
    }
1991

1992
    if (((arguments->debug_print) && (NULL != arguments->metaFile))
1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
            || 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");
2003
        if (*(arguments->dataType)) {
2004
            printf("# Specified data type:               ");
2005
            for (int c = 0; c < MAX_NUM_COLUMNS; c++)
2006 2007
                if (arguments->dataType[c])
                    printf("%s,", arguments->dataType[c]);
2008 2009 2010 2011 2012 2013 2014
                else
                    break;
            printf("\n");
        }
        printf("# Insertion interval:                %"PRIu64"\n",
                arguments->insert_interval);
        printf("# Number of records per req:         %u\n",
2015
                arguments->reqPerReq);
2016 2017
        printf("# Max SQL length:                    %"PRIu64"\n",
                arguments->max_sql_len);
2018
        printf("# Length of Binary:                  %d\n", arguments->binwidth);
2019
        printf("# Number of Threads:                 %d\n", arguments->nthreads);
2020
        printf("# Number of Tables:                  %"PRId64"\n",
2021
                arguments->ntables);
2022
        printf("# Number of Data per Table:          %"PRId64"\n",
2023
                arguments->insertRows);
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
        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();
2037
    }
2038
}
H
hzcheng 已提交
2039

2040
static void tmfclose(FILE *fp) {
2041 2042 2043
    if (NULL != fp) {
        fclose(fp);
    }
2044
}
2045

2046
static void tmfree(char *buf) {
2047 2048
    if (NULL != buf) {
        free(buf);
2049
        buf = NULL;
2050
    }
2051
}
H
Hui Li 已提交
2052

2053
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
2054

2055
    verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
2056

2057 2058
    TAOS_RES *res = taos_query(taos, command);
    int32_t code = taos_errno(res);
2059

2060 2061
    if (code != 0) {
        if (!quiet) {
2062
            errorPrint2("Failed to execute <%s>, reason: %s\n",
2063 2064 2065 2066 2067
                    command, taos_errstr(res));
        }
        taos_free_result(res);
        //taos_close(taos);
        return -1;
2068
    }
H
hzcheng 已提交
2069

2070 2071 2072 2073
    if (INSERT_TYPE == type) {
        int affectedRows = taos_affected_rows(res);
        taos_free_result(res);
        return affectedRows;
2074
    }
H
hzcheng 已提交
2075

2076
    taos_free_result(res);
2077
    return 0;
2078
}
H
hzcheng 已提交
2079

2080
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
2081
{
2082 2083
    pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
    if (pThreadInfo->fp == NULL) {
2084
        errorPrint2(
2085 2086 2087 2088
                "%s() LN%d, failed to open result file: %s, result will not save to file\n",
                __func__, __LINE__, pThreadInfo->filePath);
        return;
    }
2089

2090 2091 2092
    fprintf(pThreadInfo->fp, "%s", resultBuf);
    tmfclose(pThreadInfo->fp);
    pThreadInfo->fp = NULL;
2093 2094
}

2095
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
2096 2097 2098 2099 2100 2101 2102
    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) {
2103
        errorPrint2("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
2104 2105 2106
                __func__, __LINE__);
        return ;
    }
H
hzcheng 已提交
2107

2108
    int64_t   totalLen = 0;
H
hzcheng 已提交
2109

2110 2111
    // fetch the records row by row
    while((row = taos_fetch_row(res))) {
2112
        if (totalLen >= (100*1024*1024 - HEAD_BUFF_LEN*2)) {
2113 2114 2115 2116 2117 2118
            if (strlen(pThreadInfo->filePath) > 0)
                appendResultBufToFile(databuf, pThreadInfo);
            totalLen = 0;
            memset(databuf, 0, 100*1024*1024);
        }
        num_rows++;
2119
        char  temp[HEAD_BUFF_LEN] = {0};
2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
        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);
2135
}
H
hzcheng 已提交
2136

2137
static void selectAndGetResult(
2138 2139
        threadInfo *pThreadInfo, char *command)
{
2140 2141 2142
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
        TAOS_RES *res = taos_query(pThreadInfo->taos, command);
        if (res == NULL || taos_errno(res) != 0) {
2143
            errorPrint2("%s() LN%d, failed to execute sql:%s, reason:%s\n",
2144 2145 2146 2147
                    __func__, __LINE__, command, taos_errstr(res));
            taos_free_result(res);
            return;
        }
2148

2149 2150
        fetchResult(res, pThreadInfo);
        taos_free_result(res);
2151

2152 2153 2154 2155 2156 2157 2158 2159
    } 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);
        }
2160

2161
    } else {
2162
        errorPrint2("%s() LN%d, unknown query mode: %s\n",
2163 2164
                __func__, __LINE__, g_queryInfo.queryMode);
    }
2165
}
H
hzcheng 已提交
2166

2167
static char *rand_bool_str() {
2168 2169 2170
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2171
    return g_randbool_buff + ((cursor % MAX_PREPARED_RAND) * BOOL_BUFF_LEN);
2172 2173
}

2174
static int32_t rand_bool() {
2175 2176
    static int cursor;
    cursor++;
2177 2178
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 2;
2179 2180
}

2181 2182 2183 2184 2185
static char *rand_tinyint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2186 2187
    return g_randtinyint_buff +
        ((cursor % MAX_PREPARED_RAND) * TINYINT_BUFF_LEN);
2188 2189 2190 2191
}

static int32_t rand_tinyint()
{
2192 2193
    static int cursor;
    cursor++;
2194 2195
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 128;
2196 2197 2198 2199 2200 2201 2202
}

static char *rand_smallint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2203 2204
    return g_randsmallint_buff +
        ((cursor % MAX_PREPARED_RAND) * SMALLINT_BUFF_LEN);
2205 2206
}

2207 2208
static int32_t rand_smallint()
{
2209 2210
    static int cursor;
    cursor++;
2211 2212
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND] % 32767;
2213 2214
}

2215 2216 2217 2218 2219
static char *rand_int_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2220
    return g_randint_buff + ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN);
2221 2222 2223 2224
}

static int32_t rand_int()
{
2225 2226
    static int cursor;
    cursor++;
2227 2228
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randint[cursor % MAX_PREPARED_RAND];
2229 2230 2231 2232 2233 2234 2235
}

static char *rand_bigint_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2236 2237
    return g_randbigint_buff +
        ((cursor % MAX_PREPARED_RAND) * BIGINT_BUFF_LEN);
2238 2239
}

2240 2241
static int64_t rand_bigint()
{
2242 2243
    static int cursor;
    cursor++;
2244 2245
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randbigint[cursor % MAX_PREPARED_RAND];
2246 2247
}

2248 2249 2250 2251 2252
static char *rand_float_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2253
    return g_randfloat_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2254 2255
}

S
Shengliang Guan 已提交
2256

2257 2258
static float rand_float()
{
2259 2260
    static int cursor;
    cursor++;
2261 2262
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return g_randfloat[cursor % MAX_PREPARED_RAND];
2263 2264
}

2265 2266 2267 2268 2269
static char *demo_current_float_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2270 2271
    return g_rand_current_buff +
        ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2272 2273 2274 2275
}

static float UNUSED_FUNC demo_current_float()
{
2276 2277
    static int cursor;
    cursor++;
2278 2279 2280
    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);
2281 2282 2283 2284 2285 2286 2287
}

static char *demo_voltage_int_str()
{
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2288 2289
    return g_rand_voltage_buff +
        ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN);
2290 2291
}

2292 2293
static int32_t UNUSED_FUNC demo_voltage_int()
{
2294 2295
    static int cursor;
    cursor++;
2296 2297
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
    return 215 + g_randint[cursor % MAX_PREPARED_RAND] % 10;
2298 2299 2300 2301 2302 2303
}

static char *demo_phase_float_str() {
    static int cursor;
    cursor++;
    if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0;
2304
    return g_rand_phase_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN);
2305 2306
}

2307
static float UNUSED_FUNC demo_phase_float() {
2308 2309
    static int cursor;
    cursor++;
2310 2311 2312
    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);
2313 2314
}

2315 2316 2317 2318 2319 2320
#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)
{
2321 2322 2323 2324 2325 2326 2327 2328
    str[0] = 0;
    if (size > 0) {
        int n;
        for (n = 0; n < size; n++) {
            str[n] = charNum[n % 10];
        }
        str[n] = 0;
    }
2329 2330 2331
}
#endif

2332
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
2333

2334
static void rand_string(char *str, int size) {
2335 2336 2337 2338 2339 2340 2341 2342 2343
    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;
2344 2345 2346
    }
}

2347 2348 2349 2350 2351 2352 2353 2354 2355 2356
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()
{
2357 2358 2359
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
2360
    return g_randdouble[cursor];
2361 2362 2363
}

static void init_rand_data() {
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385

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

2386
    for (int i = 0; i < MAX_PREPARED_RAND; i++) {
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
        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]);
2417
    }
2418 2419
}

2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
#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)

2440
static int printfInsertMeta() {
2441
    SHOW_PARSE_RESULT_START();
2442

2443 2444 2445
    if (g_args.demo_mode) {
        printf("\ntaosdemo is simulating data generated by power equipment monitoring...\n\n");
    } else {
2446
        printf("\ntaosdemo is simulating random data as you request..\n\n");
2447
    }
2448

2449 2450 2451
    if (g_args.iface != INTERFACE_BUT) {
        // first time if no iface specified
        printf("interface:                  \033[33m%s\033[0m\n",
2452 2453
                (g_args.iface==TAOSC_IFACE)?"taosc":
                (g_args.iface==REST_IFACE)?"rest":"stmt");
2454 2455
    }

2456 2457 2458 2459 2460 2461 2462 2463
    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",
2464
            g_Dbs.threadCountForCreateTbl);
2465 2466 2467
    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",
2468
            g_args.reqPerReq);
2469 2470 2471 2472
    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);
2473

2474 2475 2476 2477 2478
    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) {
2479
            printf("  drop:                  \033[33m no\033[0m\n");
2480
        } else {
2481
            printf("  drop:                  \033[33m yes\033[0m\n");
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 2527 2528 2529 2530 2531 2532
        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))
2533 2534
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2))) {
2535 2536 2537 2538 2539 2540 2541 2542
                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;
            }
        }
2543

2544 2545 2546 2547 2548 2549
        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",
2550
                    g_Dbs.db[i].superTbls[j].stbName);
2551 2552 2553 2554 2555 2556 2557 2558 2559

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

2561 2562 2563 2564 2565 2566 2567
            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");
            }
2568

2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589
            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) {
2590
               printf("      multiThreadWriteOneTbl:  \033[33m no\033[0m\n");
2591
               }else {
2592
               printf("      multiThreadWriteOneTbl:  \033[33m yes\033[0m\n");
2593 2594 2595 2596 2597 2598 2599 2600 2601
               }
               */
            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);
            }
2602

2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
            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");
2654
        }
2655
        printf("\n");
2656
    }
2657

2658
    SHOW_PARSE_RESULT_END();
2659

2660
    return 0;
2661 2662 2663
}

static void printfInsertMetaToFile(FILE* fp) {
2664

2665
    SHOW_PARSE_RESULT_START_TO_FILE(fp);
2666

2667 2668 2669 2670 2671
    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);
2672
    fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountForCreateTbl);
2673
    fprintf(fp, "number of records per req:  %u\n", g_args.reqPerReq);
2674 2675
    fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
    fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
2676

2677 2678 2679 2680 2681 2682 2683 2684
    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");
        }
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 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
        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))
2724
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2))
2725 2726 2727 2728 2729 2730 2731 2732
                    || (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);
            }
        }
2733

2734 2735 2736 2737 2738 2739
        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",
2740
                    g_Dbs.db[i].superTbls[j].stbName);
2741 2742 2743 2744 2745 2746 2747 2748 2749

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

2751 2752 2753 2754 2755 2756 2757 2758
            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");
            }
2759

2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839
            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");
2840
        }
2841
        fprintf(fp, "\n");
2842
    }
2843

2844
    SHOW_PARSE_RESULT_END_TO_FILE(fp);
2845 2846 2847
}

static void printfQueryMeta() {
2848

2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898
    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",
2899
                    g_queryInfo.superQueryInfo.stbName);
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
            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");
        }
2918
    }
2919

2920
    SHOW_PARSE_RESULT_END();
2921 2922
}

2923
static char* formatTimestamp(char* buf, int64_t val, int precision) {
2924
    time_t tt;
2925
    if (precision == TSDB_TIME_PRECISION_MICRO) {
2926
        tt = (time_t)(val / 1000000);
2927 2928
    } if (precision == TSDB_TIME_PRECISION_NANO) {
        tt = (time_t)(val / 1000000000);
2929 2930 2931
    } else {
        tt = (time_t)(val / 1000);
    }
2932

2933 2934 2935 2936 2937 2938 2939
    /* 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;
       }
       */
2940 2941

#ifdef WINDOWS
2942
    if (tt < 0) tt = 0;
2943 2944
#endif

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

2948
    if (precision == TSDB_TIME_PRECISION_MICRO) {
2949
        sprintf(buf + pos, ".%06d", (int)(val % 1000000));
2950 2951
    } else if (precision == TSDB_TIME_PRECISION_NANO) {
        sprintf(buf + pos, ".%09d", (int)(val % 1000000000));
2952 2953 2954
    } else {
        sprintf(buf + pos, ".%03d", (int)(val % 1000));
    }
2955

2956
    return buf;
2957 2958
}

2959
static void xDumpFieldToFile(FILE* fp, const char* val,
2960
        TAOS_FIELD* field, int32_t length, int precision) {
2961

2962 2963 2964 2965
    if (val == NULL) {
        fprintf(fp, "%s", TSDB_DATA_NULL_STR);
        return;
    }
2966

2967 2968 2969
    char buf[TSDB_MAX_BYTES_PER_ROW];
    switch (field->type) {
        case TSDB_DATA_TYPE_BOOL:
2970
            fprintf(fp, "%d", ((((int32_t)(*((int8_t*)val))) == 1) ? 1 : 0));
2971
            break;
2972

2973 2974 2975
        case TSDB_DATA_TYPE_TINYINT:
            fprintf(fp, "%d", *((int8_t *)val));
            break;
2976

2977 2978 2979
        case TSDB_DATA_TYPE_SMALLINT:
            fprintf(fp, "%d", *((int16_t *)val));
            break;
2980

2981 2982 2983
        case TSDB_DATA_TYPE_INT:
            fprintf(fp, "%d", *((int32_t *)val));
            break;
2984

2985
        case TSDB_DATA_TYPE_BIGINT:
2986
            fprintf(fp, "%"PRId64"", *((int64_t *)val));
2987
            break;
2988

2989 2990 2991
        case TSDB_DATA_TYPE_FLOAT:
            fprintf(fp, "%.5f", GET_FLOAT_VAL(val));
            break;
2992

2993 2994 2995
        case TSDB_DATA_TYPE_DOUBLE:
            fprintf(fp, "%.9f", GET_DOUBLE_VAL(val));
            break;
2996

2997 2998 2999 3000 3001 3002
        case TSDB_DATA_TYPE_BINARY:
        case TSDB_DATA_TYPE_NCHAR:
            memcpy(buf, val, length);
            buf[length] = 0;
            fprintf(fp, "\'%s\'", buf);
            break;
3003

3004 3005 3006 3007
        case TSDB_DATA_TYPE_TIMESTAMP:
            formatTimestamp(buf, *(int64_t*)val, precision);
            fprintf(fp, "'%s'", buf);
            break;
3008

3009 3010 3011
        default:
            break;
    }
3012 3013 3014
}

static int xDumpResultToFile(const char* fname, TAOS_RES* tres) {
3015 3016 3017 3018
    TAOS_ROW row = taos_fetch_row(tres);
    if (row == NULL) {
        return 0;
    }
3019

3020 3021
    FILE* fp = fopen(fname, "at");
    if (fp == NULL) {
3022
        errorPrint2("%s() LN%d, failed to open file: %s\n",
3023 3024 3025
                __func__, __LINE__, fname);
        return -1;
    }
3026

3027 3028 3029
    int num_fields = taos_num_fields(tres);
    TAOS_FIELD *fields = taos_fetch_fields(tres);
    int precision = taos_result_precision(tres);
3030

3031 3032 3033 3034 3035
    for (int col = 0; col < num_fields; col++) {
        if (col > 0) {
            fprintf(fp, ",");
        }
        fprintf(fp, "%s", fields[col].name);
3036 3037 3038
    }
    fputc('\n', fp);

3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053
    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);
3054

3055
    fclose(fp);
3056

3057
    return numOfRows;
3058 3059
}

3060
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
3061 3062 3063
    TAOS_RES * res;
    TAOS_ROW row = NULL;
    int count = 0;
3064

3065 3066
    res = taos_query(taos, "show databases;");
    int32_t code = taos_errno(res);
3067

3068
    if (code != 0) {
3069
        errorPrint2("failed to run <show databases>, reason: %s\n",
3070 3071
                taos_errstr(res));
        return -1;
3072
    }
3073

3074
    TAOS_FIELD *fields = taos_fetch_fields(res);
3075

3076 3077 3078 3079 3080 3081
    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;
        }
3082

3083 3084
        dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo));
        if (dbInfos[count] == NULL) {
3085
            errorPrint2("failed to allocate memory for some dbInfo[%d]\n", count);
3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124
            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;
        }
3125 3126
    }

3127
    return count;
3128 3129
}

3130
static void printfDbInfoForQueryToFile(
3131
        char* filename, SDbInfo* dbInfos, int index) {
3132

3133 3134
    if (filename[0] == 0)
        return;
3135

3136 3137 3138 3139 3140
    FILE *fp = fopen(filename, "at");
    if (fp == NULL) {
        errorPrint( "failed to open file: %s\n", filename);
        return;
    }
3141

3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162
    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");
3163

3164
    fclose(fp);
3165 3166 3167
}

static void printfQuerySystemInfo(TAOS * taos) {
3168 3169
    char filename[MAX_FILE_NAME_LEN] = {0};
    char buffer[1024] = {0};
3170 3171 3172 3173 3174 3175
    TAOS_RES* res;

    time_t t;
    struct tm* lt;
    time(&t);
    lt = localtime(&t);
3176
    snprintf(filename, MAX_FILE_NAME_LEN, "querySystemInfo-%d-%d-%d %d:%d:%d",
3177 3178 3179 3180 3181 3182
            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);
3183
    xDumpResultToFile(filename, res);
3184

3185 3186
    // show dnodes
    res = taos_query(taos, "show dnodes;");
3187
    xDumpResultToFile(filename, res);
3188
    //fetchResult(res, filename);
3189

3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207
    // 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
3208
        snprintf(buffer, 1024, "show %s.vgroups;", dbInfos[i]->name);
3209 3210 3211 3212
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);

        // show db.stables
3213
        snprintf(buffer, 1024, "show %s.stables;", dbInfos[i]->name);
3214 3215 3216 3217
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);
        free(dbInfos[i]);
    }
3218

3219
    free(dbInfos);
3220 3221
}

3222
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
3223
        char* sqlstr, threadInfo *pThreadInfo)
3224
{
3225
    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";
3226

3227
    char *url = "/rest/sql";
3228

3229 3230 3231 3232
    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;
3233

3234
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
3235

3236 3237
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
3238
        errorPrint("%s", "cannot allocate memory.\n");
3239
        exit(EXIT_FAILURE);
3240
    }
3241

3242 3243
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
3244

3245
    static char base64[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
3246 3247 3248 3249 3250 3251 3252
        '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', '+', '/'};
3253

3254
    snprintf(userpass_buf, INPUT_BUF_LEN, "%s:%s",
3255
            g_Dbs.user, g_Dbs.password);
3256 3257
    size_t userpass_buf_len = strlen(userpass_buf);
    size_t encoded_len = 4 * ((userpass_buf_len +2) / 3);
3258

3259
    char base64_buf[INPUT_BUF_LEN];
3260
#ifdef WINDOWS
3261
    WSADATA wsaData;
3262
    WSAStartup(MAKEWORD(2, 2), &wsaData);
3263 3264
    SOCKET sockfd;
#else
3265
    int sockfd;
3266
#endif
3267 3268
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
3269
#ifdef WINDOWS
3270
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
3271
#endif
3272 3273
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
3274
        ERROR_EXIT("opening socket");
3275
    }
3276

3277
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
3278 3279 3280
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
3281
        ERROR_EXIT("connecting");
3282
    }
3283

3284
    memset(base64_buf, 0, INPUT_BUF_LEN);
3285

3286
    for (int n = 0, m = 0; n < userpass_buf_len;) {
3287 3288 3289 3290 3291 3292 3293
        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;
3294

3295 3296 3297 3298
        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];
3299
    }
3300

3301
    for (int l = 0; l < mod_table[userpass_buf_len % 3]; l++)
3302
        base64_buf[encoded_len - 1 - l] = '=';
3303

3304 3305 3306
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
3307

3308 3309 3310 3311 3312 3313
    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);
3314
        ERROR_EXIT("too long request");
3315 3316
    }
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
3317

3318 3319 3320
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
3321
#ifdef WINDOWS
3322
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
3323
#else
3324
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
3325
#endif
3326
        if (bytes < 0)
3327
            ERROR_EXIT("writing message to socket");
3328 3329 3330 3331
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
3332

3333 3334 3335 3336
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
3337
#ifdef WINDOWS
3338
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
3339
#else
3340
        bytes = read(sockfd, response_buf + received, resp_len - received);
3341
#endif
3342 3343
        if (bytes < 0) {
            free(request_buf);
3344
            ERROR_EXIT("reading response from socket");
3345 3346 3347 3348 3349
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
3350

3351 3352
    if (received == resp_len) {
        free(request_buf);
3353
        ERROR_EXIT("storing complete response from socket");
3354
    }
H
Haojun Liao 已提交
3355

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

3359
    if (strlen(pThreadInfo->filePath) > 0) {
3360
        appendResultBufToFile(response_buf, pThreadInfo);
3361 3362
    }

3363
    free(request_buf);
3364
#ifdef WINDOWS
3365
    closesocket(sockfd);
3366 3367
    WSACleanup();
#else
3368
    close(sockfd);
3369
#endif
3370

3371
    return 0;
3372 3373
}

3374
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
3375 3376
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
3377
        errorPrint2("%s() LN%d, calloc failed! size:%d\n",
3378 3379 3380
                __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
        return NULL;
    }
3381

3382 3383 3384
    int    dataLen = 0;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
            "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
3385

3386
    return dataBuf;
3387 3388
}

3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407
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) {
3408 3409 3410
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
        printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1);
3411
        return NULL;
3412
    }
3413

3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426
    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;
            }
3427

3428 3429
            int32_t tagBufLen = stbInfo->tags[i].dataLen + 1;
            char *buf = generateBinaryNCharTagValues(tableSeq, tagBufLen);
3430 3431 3432 3433 3434
            if (NULL == buf) {
                tmfree(dataBuf);
                return NULL;
            }
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3435
                    "\'%s\',", buf);
3436 3437 3438
            tmfree(buf);
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "int", strlen("int"))) {
3439 3440 3441
            if ((g_args.demo_mode) && (i == 0)) {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
3442
                        "%"PRId64",", (tableSeq % 10) + 1);
3443 3444 3445
            } else {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
3446
                        "%"PRId64",", tableSeq);
3447
            }
3448 3449 3450
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bigint", strlen("bigint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3451
                    "%"PRId64",", rand_bigint());
3452 3453 3454
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "float", strlen("float"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3455
                    "%f,", rand_float());
3456 3457 3458
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "double", strlen("double"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3459
                    "%f,", rand_double());
3460 3461 3462
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "smallint", strlen("smallint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3463
                    "%d,", rand_smallint());
3464 3465 3466
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "tinyint", strlen("tinyint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3467
                    "%d,", rand_tinyint());
3468 3469 3470
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bool", strlen("bool"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3471
                    "%d,", rand_bool());
3472 3473 3474
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "timestamp", strlen("timestamp"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
3475
                    "%"PRId64",", rand_bigint());
3476
        }  else {
3477
            errorPrint2("No support data type: %s\n", stbInfo->tags[i].dataType);
3478 3479 3480
            tmfree(dataBuf);
            return NULL;
        }
3481
    }
3482

3483
    dataLen -= 1;
3484 3485
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
    return dataBuf;
3486 3487
}

3488
static int calcRowLen(SSuperTable*  superTbls) {
3489 3490 3491 3492 3493 3494
    int colIndex;
    int  lenOfOneRow = 0;

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

3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538
        switch(superTbls->columns[colIndex].data_type) {
            case TSDB_DATA_TYPE_BINARY:
                lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
                break;

            case TSDB_DATA_TYPE_NCHAR:
                lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
                break;

            case TSDB_DATA_TYPE_INT:
                lenOfOneRow += INT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_BIGINT:
                lenOfOneRow += BIGINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_SMALLINT:
                lenOfOneRow += SMALLINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TINYINT:
                lenOfOneRow += TINYINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_BOOL:
                lenOfOneRow += BOOL_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_FLOAT:
                lenOfOneRow += FLOAT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_DOUBLE:
                lenOfOneRow += DOUBLE_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TIMESTAMP:
                lenOfOneRow += TIMESTAMP_BUFF_LEN;
                break;

            default:
                errorPrint2("get error data type : %s\n", dataType);
                exit(EXIT_FAILURE);
3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553
        }
    }

    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)  {
3554
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + INT_BUFF_LEN;
3555
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3556
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + BIGINT_BUFF_LEN;
3557
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3558
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + SMALLINT_BUFF_LEN;
3559
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3560
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + TINYINT_BUFF_LEN;
3561
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3562
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + BOOL_BUFF_LEN;
3563
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
3564
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + FLOAT_BUFF_LEN;
3565
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
3566
            lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + DOUBLE_BUFF_LEN;
3567
        } else {
3568
            errorPrint2("get error tag type : %s\n", dataType);
3569
            exit(EXIT_FAILURE);
3570
        }
3571 3572
    }

3573
    superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
3574

3575
    return 0;
3576 3577
}

3578
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
3579
        char* dbName, char* stbName, char** childTblNameOfSuperTbl,
3580
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
3581

3582
    char command[1024] = "\0";
3583
    char limitBuf[100] = "\0";
3584

3585 3586
    TAOS_RES * res;
    TAOS_ROW row = NULL;
3587

3588
    char* childTblName = *childTblNameOfSuperTbl;
3589

3590 3591
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
        limit, offset);
3592

3593
    //get all child table name use cmd: select tbname from superTblName;
3594
    snprintf(command, 1024, "select tbname from %s.%s %s",
3595
            dbName, stbName, limitBuf);
3596

3597 3598 3599 3600
    res = taos_query(taos, command);
    int32_t code = taos_errno(res);
    if (code != 0) {
        taos_free_result(res);
3601
        taos_close(taos);
3602
        errorPrint2("%s() LN%d, failed to run command %s\n",
3603
                __func__, __LINE__, command);
3604
        exit(EXIT_FAILURE);
3605
    }
3606

3607 3608 3609 3610 3611 3612 3613
    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);
3614
            errorPrint2("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
3615
            exit(EXIT_FAILURE);
3616
        }
3617 3618
    }

3619 3620 3621 3622 3623
    char* pTblName = childTblName;
    while((row = taos_fetch_row(res)) != NULL) {
        int32_t* len = taos_fetch_lengths(res);

        if (0 == strlen((char *)row[0])) {
3624
            errorPrint2("%s() LN%d, No.%"PRId64" table return empty name\n",
3625
                    __func__, __LINE__, count);
3626
            exit(EXIT_FAILURE);
3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644
        }

        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);
3645
                errorPrint2("%s() LN%d, realloc fail for save child table name of %s.%s\n",
3646
                        __func__, __LINE__, dbName, stbName);
3647
                exit(EXIT_FAILURE);
3648 3649 3650
            }
        }
        pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
3651
    }
3652

3653 3654
    *childTblCountOfSuperTbl = count;
    *childTblNameOfSuperTbl  = childTblName;
3655

3656 3657
    taos_free_result(res);
    return 0;
3658 3659
}

3660
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
3661
        char* stbName, char** childTblNameOfSuperTbl,
3662
        int64_t* childTblCountOfSuperTbl) {
3663

3664
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, stbName,
3665
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
3666
            -1, 0);
3667 3668
}

3669
static int getSuperTableFromServer(TAOS * taos, char* dbName,
3670
        SSuperTable*  superTbls) {
3671

3672
    char command[1024] = "\0";
3673 3674 3675 3676 3677
    TAOS_RES * res;
    TAOS_ROW row = NULL;
    int count = 0;

    //get schema use cmd: describe superTblName;
3678
    snprintf(command, 1024, "describe %s.%s", dbName, superTbls->stbName);
3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701
    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],
3702 3703
                    min(DATATYPE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes) + 1);
3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736
            if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "INT", strlen("INT"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_INT;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "TINYINT", strlen("TINYINT"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_TINYINT;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "SMALLINT", strlen("SMALLINT"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_SMALLINT;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "BIGINT", strlen("BIGINT"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_BIGINT;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "FLOAT", strlen("FLOAT"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_FLOAT;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "DOUBLE", strlen("DOUBLE"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_DOUBLE;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "BINARY", strlen("BINARY"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_BINARY;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "NCHAR", strlen("NCHAR"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_NCHAR;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "BOOL", strlen("BOOL"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_BOOL;
            } else if (0 == strncasecmp(superTbls->tags[tagIndex].dataType,
                        "TIMESTAMP", strlen("TIMESTAMP"))) {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_TIMESTAMP;
            } else {
                superTbls->tags[tagIndex].data_type = TSDB_DATA_TYPE_NULL;
            }
3737 3738 3739 3740
            superTbls->tags[tagIndex].dataLen =
                *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
            tstrncpy(superTbls->tags[tagIndex].note,
                    (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
3741 3742
                    min(NOTE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes) + 1);
3743 3744 3745 3746 3747
            tagIndex++;
        } else {
            tstrncpy(superTbls->columns[columnIndex].field,
                    (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
                    fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
3748

3749 3750
            tstrncpy(superTbls->columns[columnIndex].dataType,
                    (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
3751 3752
                    min(DATATYPE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes) + 1);
3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785
            if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "INT", strlen("INT"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_INT;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "TINYINT", strlen("TINYINT"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_TINYINT;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "SMALLINT", strlen("SMALLINT"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_SMALLINT;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "BIGINT", strlen("BIGINT"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_BIGINT;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "FLOAT", strlen("FLOAT"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_FLOAT;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "DOUBLE", strlen("DOUBLE"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_DOUBLE;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "BINARY", strlen("BINARY"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_BINARY;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "NCHAR", strlen("NCHAR"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_NCHAR;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "BOOL", strlen("BOOL"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_BOOL;
            } else if (0 == strncasecmp(superTbls->columns[columnIndex].dataType,
                        "TIMESTAMP", strlen("TIMESTAMP"))) {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_TIMESTAMP;
            } else {
                superTbls->columns[columnIndex].data_type = TSDB_DATA_TYPE_NULL;
            }
3786 3787 3788 3789
            superTbls->columns[columnIndex].dataLen =
                *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
            tstrncpy(superTbls->columns[columnIndex].note,
                    (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
3790 3791
                    min(NOTE_BUFF_LEN,
                        fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes) + 1);
3792

3793 3794 3795 3796 3797 3798 3799
            columnIndex++;
        }
        count++;
    }

    superTbls->columnCount = columnIndex;
    superTbls->tagCount    = tagIndex;
3800
    taos_free_result(res);
3801

3802 3803 3804 3805
    calcRowLen(superTbls);

    /*
       if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
3806
    //get all child table name use cmd: select tbname from superTblName;
3807 3808 3809
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
3810
    errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
3811
    return -1;
3812
    }
3813
    getAllChildNameOfSuperTable(taos, dbName,
3814
    superTbls->stbName,
3815 3816 3817 3818 3819
    &superTbls->childTblName,
    &superTbls->childTblCount);
    }
    */
    return 0;
3820 3821
}

H
Haojun Liao 已提交
3822
static int createSuperTable(
3823 3824
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
3825

3826 3827
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);
3828

3829
    char cols[COL_BUFFER_LEN] = "\0";
3830
    int len = 0;
3831

3832
    int  lenOfOneRow = 0;
3833

3834
    if (superTbl->columnCount == 0) {
3835
        errorPrint2("%s() LN%d, super table column count is %d\n",
3836
                __func__, __LINE__, superTbl->columnCount);
3837
        free(command);
3838 3839
        return -1;
    }
3840

3841
    for (int colIndex = 0; colIndex < superTbl->columnCount; colIndex++) {
3842

3843 3844
        switch(superTbl->columns[colIndex].data_type) {
            case TSDB_DATA_TYPE_BINARY:
3845
                len += snprintf(cols + len, COL_BUFFER_LEN - len,
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863
                        ",C%d %s(%d)", colIndex, "BINARY",
                        superTbl->columns[colIndex].dataLen);
                lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
                break;

            case TSDB_DATA_TYPE_NCHAR:
                len += snprintf(cols + len, COL_BUFFER_LEN - len,
                        ",C%d %s(%d)", colIndex, "NCHAR",
                        superTbl->columns[colIndex].dataLen);
                lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
                break;

            case TSDB_DATA_TYPE_INT:
                if ((g_args.demo_mode) && (colIndex == 1)) {
                    len += snprintf(cols + len, COL_BUFFER_LEN - len,
                            ", VOLTAGE INT");
                } else {
                    len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "INT");
3864
                }
3865 3866
                lenOfOneRow += INT_BUFF_LEN;
                break;
3867

3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921
            case TSDB_DATA_TYPE_BIGINT:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
                        colIndex, "BIGINT");
                lenOfOneRow += BIGINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_SMALLINT:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
                        colIndex, "SMALLINT");
                lenOfOneRow += SMALLINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TINYINT:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "TINYINT");
                lenOfOneRow += TINYINT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_BOOL:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "BOOL");
                lenOfOneRow += BOOL_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_FLOAT:
                if (g_args.demo_mode) {
                    if (colIndex == 0) {
                        len += snprintf(cols + len, COL_BUFFER_LEN - len, ", CURRENT FLOAT");
                    } else if (colIndex == 2) {
                        len += snprintf(cols + len, COL_BUFFER_LEN - len, ", PHASE FLOAT");
                    }
                } else {
                    len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s", colIndex, "FLOAT");
                }

                lenOfOneRow += FLOAT_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_DOUBLE:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
                        colIndex, "DOUBLE");
                lenOfOneRow += DOUBLE_BUFF_LEN;
                break;

            case TSDB_DATA_TYPE_TIMESTAMP:
                len += snprintf(cols + len, COL_BUFFER_LEN - len, ",C%d %s",
                        colIndex, "TIMESTAMP");
                lenOfOneRow += TIMESTAMP_BUFF_LEN;
                break;

            default:
                taos_close(taos);
                free(command);
                errorPrint2("%s() LN%d, config error data type : %s\n",
                        __func__, __LINE__, superTbl->columns[colIndex].dataType);
                exit(EXIT_FAILURE);
3922
        }
3923 3924
    }

3925
    superTbl->lenOfOneRow = lenOfOneRow + 20; // timestamp
3926

3927 3928 3929 3930
    // save for creating child table
    superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
    if (NULL == superTbl->colsOfCreateChildTable) {
        taos_close(taos);
3931
        free(command);
3932
        errorPrint2("%s() LN%d, Failed when calloc, size:%d",
3933 3934
                __func__, __LINE__, len+1);
        exit(EXIT_FAILURE);
3935
    }
3936

3937 3938 3939
    snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
    verbosePrint("%s() LN%d: %s\n",
            __func__, __LINE__, superTbl->colsOfCreateChildTable);
3940

3941
    if (superTbl->tagCount == 0) {
3942
        errorPrint2("%s() LN%d, super table tag count is %d\n",
3943
                __func__, __LINE__, superTbl->tagCount);
3944
        free(command);
3945 3946
        return -1;
    }
3947

3948
    char tags[TSDB_MAX_TAGS_LEN] = "\0";
3949 3950
    int tagIndex;
    len = 0;
3951

3952
    int lenOfTagOfOneRow = 0;
3953
    len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len, "(");
3954 3955 3956 3957
    for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
        char* dataType = superTbl->tags[tagIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
3958
            if ((g_args.demo_mode) && (tagIndex == 1)) {
3959
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3960
                        "location BINARY(%d),",
3961 3962
                        superTbl->tags[tagIndex].dataLen);
            } else {
3963
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3964
                        "T%d %s(%d),", tagIndex, "BINARY",
3965
                        superTbl->tags[tagIndex].dataLen);
3966
            }
3967 3968
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
3969
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3970
                    "T%d %s(%d),", tagIndex,
3971 3972 3973
                    "NCHAR", superTbl->tags[tagIndex].dataLen);
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
3974
            if ((g_args.demo_mode) && (tagIndex == 0)) {
3975 3976
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
                        "groupId INT, ");
3977
            } else {
3978
                len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3979
                        "T%d %s,", tagIndex, "INT");
3980
            }
3981
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + INT_BUFF_LEN;
3982
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
3983
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3984
                    "T%d %s,", tagIndex, "BIGINT");
3985
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + BIGINT_BUFF_LEN;
3986
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
3987
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3988
                    "T%d %s,", tagIndex, "SMALLINT");
3989
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + SMALLINT_BUFF_LEN;
3990
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
3991
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3992
                    "T%d %s,", tagIndex, "TINYINT");
3993
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + TINYINT_BUFF_LEN;
3994
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
3995
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
3996
                    "T%d %s,", tagIndex, "BOOL");
3997
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + BOOL_BUFF_LEN;
3998
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
3999
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
4000
                    "T%d %s,", tagIndex, "FLOAT");
4001
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + FLOAT_BUFF_LEN;
4002
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
4003
            len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len,
4004
                    "T%d %s,", tagIndex, "DOUBLE");
4005
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + DOUBLE_BUFF_LEN;
4006 4007
        } else {
            taos_close(taos);
4008
            free(command);
4009
            errorPrint2("%s() LN%d, config error tag type : %s\n",
4010
                    __func__, __LINE__, dataType);
4011
            exit(EXIT_FAILURE);
4012
        }
4013
    }
4014

4015
    len -= 1;
4016
    len += snprintf(tags + len, TSDB_MAX_TAGS_LEN - len, ")");
4017

4018
    superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;
4019

4020
    snprintf(command, BUFFER_SIZE,
4021 4022
            "CREATE TABLE IF NOT EXISTS %s.%s (ts TIMESTAMP%s) TAGS %s",
            dbName, superTbl->stbName, cols, tags);
4023
    if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
4024
        errorPrint2("create supertable %s failed!\n\n",
4025
                superTbl->stbName);
4026
        free(command);
4027 4028
        return -1;
    }
4029

4030
    debugPrint("create supertable %s success!\n\n", superTbl->stbName);
4031
    free(command);
4032
    return 0;
4033 4034
}

4035
int createDatabasesAndStables(char *command) {
4036 4037 4038 4039
    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) {
4040
        errorPrint2("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
4041
        return -1;
4042
    }
4043

4044 4045 4046 4047 4048 4049 4050
    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;
            }
4051

4052 4053
            int dataLen = 0;
            dataLen += snprintf(command + dataLen,
4054
                    BUFFER_SIZE - dataLen, "CREATE DATABASE IF NOT EXISTS %s",
4055
                    g_Dbs.db[i].dbName);
4056

4057 4058
            if (g_Dbs.db[i].dbCfg.blocks > 0) {
                dataLen += snprintf(command + dataLen,
4059
                        BUFFER_SIZE - dataLen, " BLOCKS %d",
4060
                        g_Dbs.db[i].dbCfg.blocks);
4061 4062 4063
            }
            if (g_Dbs.db[i].dbCfg.cache > 0) {
                dataLen += snprintf(command + dataLen,
4064
                        BUFFER_SIZE - dataLen, " CACHE %d",
4065
                        g_Dbs.db[i].dbCfg.cache);
4066 4067 4068
            }
            if (g_Dbs.db[i].dbCfg.days > 0) {
                dataLen += snprintf(command + dataLen,
4069
                        BUFFER_SIZE - dataLen, " DAYS %d",
4070
                        g_Dbs.db[i].dbCfg.days);
4071 4072 4073
            }
            if (g_Dbs.db[i].dbCfg.keep > 0) {
                dataLen += snprintf(command + dataLen,
4074
                        BUFFER_SIZE - dataLen, " KEEP %d",
4075
                        g_Dbs.db[i].dbCfg.keep);
4076 4077 4078
            }
            if (g_Dbs.db[i].dbCfg.quorum > 1) {
                dataLen += snprintf(command + dataLen,
4079
                        BUFFER_SIZE - dataLen, " QUORUM %d",
4080
                        g_Dbs.db[i].dbCfg.quorum);
4081 4082 4083
            }
            if (g_Dbs.db[i].dbCfg.replica > 0) {
                dataLen += snprintf(command + dataLen,
4084
                        BUFFER_SIZE - dataLen, " REPLICA %d",
4085
                        g_Dbs.db[i].dbCfg.replica);
4086 4087 4088
            }
            if (g_Dbs.db[i].dbCfg.update > 0) {
                dataLen += snprintf(command + dataLen,
4089
                        BUFFER_SIZE - dataLen, " UPDATE %d",
4090
                        g_Dbs.db[i].dbCfg.update);
4091 4092 4093 4094 4095 4096 4097
            }
            //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,
4098
                        BUFFER_SIZE - dataLen, " MINROWS %d",
4099
                        g_Dbs.db[i].dbCfg.minRows);
4100 4101 4102
            }
            if (g_Dbs.db[i].dbCfg.maxRows > 0) {
                dataLen += snprintf(command + dataLen,
4103
                        BUFFER_SIZE - dataLen, " MAXROWS %d",
4104
                        g_Dbs.db[i].dbCfg.maxRows);
4105 4106 4107
            }
            if (g_Dbs.db[i].dbCfg.comp > 0) {
                dataLen += snprintf(command + dataLen,
4108
                        BUFFER_SIZE - dataLen, " COMP %d",
4109
                        g_Dbs.db[i].dbCfg.comp);
4110 4111 4112
            }
            if (g_Dbs.db[i].dbCfg.walLevel > 0) {
                dataLen += snprintf(command + dataLen,
4113 4114
                        BUFFER_SIZE - dataLen, " wal %d",
                        g_Dbs.db[i].dbCfg.walLevel);
4115 4116 4117
            }
            if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
                dataLen += snprintf(command + dataLen,
4118
                        BUFFER_SIZE - dataLen, " CACHELAST %d",
4119
                        g_Dbs.db[i].dbCfg.cacheLast);
4120 4121 4122
            }
            if (g_Dbs.db[i].dbCfg.fsync > 0) {
                dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
4123
                        " FSYNC %d", g_Dbs.db[i].dbCfg.fsync);
4124
            }
4125
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
4126
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
4127
                            "ns", 2))
4128
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
4129
                            "us", 2))) {
4130 4131 4132
                dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                        " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
            }
4133

4134 4135
            if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
                taos_close(taos);
4136
                errorPrint("\ncreate database %s failed!\n\n",
4137
                        g_Dbs.db[i].dbName);
4138 4139 4140 4141
                return -1;
            }
            printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName);
        }
4142

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

4146
        int validStbCount = 0;
4147

4148 4149
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
4150
                    g_Dbs.db[i].superTbls[j].stbName);
4151
            ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);
4152

4153 4154 4155
            if ((ret != 0) || (g_Dbs.db[i].drop)) {
                ret = createSuperTable(taos, g_Dbs.db[i].dbName,
                        &g_Dbs.db[i].superTbls[j]);
4156

4157 4158 4159 4160 4161
                if (0 != ret) {
                    errorPrint("create super table %"PRIu64" failed!\n\n", j);
                    continue;
                }
            }
4162

4163 4164 4165
            ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
                    &g_Dbs.db[i].superTbls[j]);
            if (0 != ret) {
4166
                errorPrint2("\nget super table %s.%s info failed!\n\n",
4167
                        g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].stbName);
4168 4169
                continue;
            }
4170

4171 4172
            validStbCount ++;
        }
4173

4174 4175 4176 4177 4178
        g_Dbs.db[i].superTblCount = validStbCount;
    }

    taos_close(taos);
    return 0;
4179 4180
}

4181 4182
static void* createTable(void *sarg)
{
4183
    threadInfo *pThreadInfo = (threadInfo *)sarg;
4184
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
4185

4186 4187
    setThreadName("createTable");

4188
    uint64_t  lastPrintTime = taosGetTimestampMs();
4189

4190
    int buff_len = BUFFER_SIZE;
4191

4192 4193
    pThreadInfo->buffer = calloc(buff_len, 1);
    if (pThreadInfo->buffer == NULL) {
4194
        errorPrint2("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
4195
        exit(EXIT_FAILURE);
4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208
    }

    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,
4209
                    "CREATE TABLE IF NOT EXISTS %s.%s%"PRIu64" %s;",
4210 4211 4212
                    pThreadInfo->db_name,
                    g_args.tb_prefix, i,
                    pThreadInfo->cols);
4213
            batchNum ++;
4214
        } else {
4215 4216
            if (stbInfo == NULL) {
                free(pThreadInfo->buffer);
4217
                errorPrint2("%s() LN%d, use metric, but super table info is NULL\n",
4218
                        __func__, __LINE__);
4219
                exit(EXIT_FAILURE);
4220 4221 4222 4223 4224
            } else {
                if (0 == len) {
                    batchNum = 0;
                    memset(pThreadInfo->buffer, 0, buff_len);
                    len += snprintf(pThreadInfo->buffer + len,
4225
                            buff_len - len, "CREATE TABLE ");
4226
                }
4227

4228
                char* tagsValBuf = NULL;
4229 4230
                if (0 == stbInfo->tagSource) {
                    tagsValBuf = generateTagValuesForStb(stbInfo, i);
4231
                } else {
4232 4233 4234 4235
                    if (0 == stbInfo->tagSampleCount) {
                        free(pThreadInfo->buffer);
                        ERROR_EXIT("use sample file for tag, but has no content!\n");
                    }
4236
                    tagsValBuf = getTagValueFromTagSample(
4237 4238
                            stbInfo,
                            i % stbInfo->tagSampleCount);
4239
                }
4240

4241 4242
                if (NULL == tagsValBuf) {
                    free(pThreadInfo->buffer);
4243
                    ERROR_EXIT("use metric, but tag buffer is NULL\n");
4244 4245 4246 4247
                }
                len += snprintf(pThreadInfo->buffer + len,
                        buff_len - len,
                        "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
4248
                        pThreadInfo->db_name, stbInfo->childTblPrefix,
4249
                        i, pThreadInfo->db_name,
4250
                        stbInfo->stbName, tagsValBuf);
4251 4252
                free(tagsValBuf);
                batchNum++;
4253
                if ((batchNum < stbInfo->batchCreateTableNum)
4254
                        && ((buff_len - len)
4255
                            >= (stbInfo->lenOfTagOfOneRow + 256))) {
4256 4257 4258
                    continue;
                }
            }
4259
        }
4260

4261
        len = 0;
S
Shengliang Guan 已提交
4262

4263
        if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
4264
                    NO_INSERT_TYPE, false)) {
4265
            errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
4266 4267 4268
            free(pThreadInfo->buffer);
            return NULL;
        }
4269
        pThreadInfo->tables_created += batchNum;
4270

4271
        uint64_t currentPrintTime = taosGetTimestampMs();
4272 4273 4274 4275 4276
        if (currentPrintTime - lastPrintTime > 30*1000) {
            printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
                    pThreadInfo->threadID, pThreadInfo->start_table_from, i);
            lastPrintTime = currentPrintTime;
        }
4277
    }
4278

4279 4280 4281
    if (0 != len) {
        if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                    NO_INSERT_TYPE, false)) {
4282
            errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
4283
        }
4284
    }
4285

4286 4287
    free(pThreadInfo->buffer);
    return NULL;
4288 4289
}

4290
static int startMultiThreadCreateChildTable(
4291
        char* cols, int threads, uint64_t tableFrom, int64_t ntables,
4292
        char* db_name, SSuperTable* stbInfo) {
4293

4294 4295
    pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
    threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
4296

4297
    if ((NULL == pids) || (NULL == infos)) {
4298
        ERROR_EXIT("createChildTable malloc failed\n");
4299
    }
4300

4301 4302 4303
    if (threads < 1) {
        threads = 1;
    }
4304

4305 4306 4307 4308
    int64_t a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
4309
    }
4310

4311 4312
    int64_t b = 0;
    b = ntables % threads;
4313

4314 4315 4316 4317
    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);
4318
        pThreadInfo->stbInfo = stbInfo;
4319 4320 4321 4322 4323 4324 4325 4326
        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) {
4327
            errorPrint2("%s() LN%d, Failed to connect to TDengine, reason:%s\n",
4328 4329 4330 4331 4332
                    __func__, __LINE__, taos_errstr(NULL));
            free(pids);
            free(infos);
            return -1;
        }
4333

4334 4335 4336 4337 4338 4339 4340
        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;
4341
        pThreadInfo->tables_created = 0;
4342 4343
        pthread_create(pids + i, NULL, createTable, pThreadInfo);
    }
4344

4345 4346 4347
    for (int i = 0; i < threads; i++) {
        pthread_join(pids[i], NULL);
    }
4348

4349 4350 4351
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
        taos_close(pThreadInfo->taos);
4352 4353

        g_actualChildTables += pThreadInfo->tables_created;
4354 4355 4356 4357 4358 4359
    }

    free(pids);
    free(infos);

    return 0;
4360 4361
}

4362
static void createChildTables() {
4363
    char tblColsBuf[TSDB_MAX_BYTES_PER_ROW];
4364
    int len;
4365

4366 4367 4368 4369 4370
    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++) {
4371 4372 4373 4374
                    if ((AUTO_CREATE_SUBTBL
                                == g_Dbs.db[i].superTbls[j].autoCreateTable)
                            || (TBL_ALREADY_EXISTS
                                == g_Dbs.db[i].superTbls[j].childTblExists)) {
4375 4376 4377
                        continue;
                    }
                    verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
4378
                            g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
4379 4380 4381 4382 4383 4384 4385
                    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,
4386
                            g_Dbs.threadCountForCreateTbl,
4387 4388 4389 4390 4391 4392 4393
                            startFrom,
                            g_Dbs.db[i].superTbls[j].childTblCount,
                            g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
                }
            }
        } else {
            // normal table
4394
            len = snprintf(tblColsBuf, TSDB_MAX_BYTES_PER_ROW, "(TS TIMESTAMP");
4395 4396 4397
            for (int j = 0; j < g_args.columnCount; j++) {
                if ((strncasecmp(g_args.dataType[j], "BINARY", strlen("BINARY")) == 0)
                        || (strncasecmp(g_args.dataType[j],
4398
                                "NCHAR", strlen("NCHAR")) == 0)) {
4399
                    snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len,
4400
                            ",C%d %s(%d)", j, g_args.dataType[j], g_args.binwidth);
4401
                } else {
4402
                    snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len,
4403
                            ",C%d %s", j, g_args.dataType[j]);
4404 4405 4406
                }
                len = strlen(tblColsBuf);
            }
4407

4408
            snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len, ")");
4409 4410 4411

            verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
                    __func__, __LINE__,
4412
                    g_Dbs.db[i].dbName, g_args.ntables, tblColsBuf);
4413 4414
            startMultiThreadCreateChildTable(
                    tblColsBuf,
4415
                    g_Dbs.threadCountForCreateTbl,
4416
                    0,
4417
                    g_args.ntables,
4418 4419
                    g_Dbs.db[i].dbName,
                    NULL);
4420
        }
4421
    }
4422 4423 4424
}

/*
4425 4426
   Read 10000 lines at most. If more than 10000 lines, continue to read after using
   */
4427
static int readTagFromCsvFileToMem(SSuperTable  * stbInfo) {
4428 4429 4430
    size_t  n = 0;
    ssize_t readLen = 0;
    char *  line = NULL;
4431

4432
    FILE *fp = fopen(stbInfo->tagsFile, "r");
4433 4434
    if (fp == NULL) {
        printf("Failed to open tags file: %s, reason:%s\n",
4435
                stbInfo->tagsFile, strerror(errno));
4436
        return -1;
4437 4438
    }

4439 4440 4441
    if (stbInfo->tagDataBuf) {
        free(stbInfo->tagDataBuf);
        stbInfo->tagDataBuf = NULL;
4442 4443
    }

4444 4445
    int tagCount = 10000;
    int count = 0;
4446
    char* tagDataBuf = calloc(1, stbInfo->lenOfTagOfOneRow * tagCount);
4447 4448
    if (tagDataBuf == NULL) {
        printf("Failed to calloc, reason:%s\n", strerror(errno));
4449 4450 4451 4452
        fclose(fp);
        return -1;
    }

4453 4454 4455 4456 4457 4458 4459 4460 4461
    while((readLen = tgetline(&line, &n, fp)) != -1) {
        if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
            line[--readLen] = 0;
        }

        if (readLen == 0) {
            continue;
        }

4462
        memcpy(tagDataBuf + count * stbInfo->lenOfTagOfOneRow, line, readLen);
4463 4464 4465 4466
        count++;

        if (count >= tagCount - 1) {
            char *tmp = realloc(tagDataBuf,
4467
                    (size_t)tagCount*1.5*stbInfo->lenOfTagOfOneRow);
4468 4469 4470
            if (tmp != NULL) {
                tagDataBuf = tmp;
                tagCount = (int)(tagCount*1.5);
4471 4472
                memset(tagDataBuf + count*stbInfo->lenOfTagOfOneRow,
                        0, (size_t)((tagCount-count)*stbInfo->lenOfTagOfOneRow));
4473 4474
            } else {
                // exit, if allocate more memory failed
4475
                printf("realloc fail for save tag val from %s\n", stbInfo->tagsFile);
4476 4477 4478 4479 4480 4481 4482
                tmfree(tagDataBuf);
                free(line);
                fclose(fp);
                return -1;
            }
        }
    }
4483

4484 4485
    stbInfo->tagDataBuf = tagDataBuf;
    stbInfo->tagSampleCount = count;
4486 4487 4488 4489

    free(line);
    fclose(fp);
    return 0;
4490 4491 4492
}

/*
4493 4494
   Read 10000 lines at most. If more than 10000 lines, continue to read after using
   */
4495
static int generateSampleFromCsvForStb(
4496
        SSuperTable* stbInfo) {
4497 4498 4499 4500 4501
    size_t  n = 0;
    ssize_t readLen = 0;
    char *  line = NULL;
    int getRows = 0;

4502
    FILE*  fp = fopen(stbInfo->sampleFile, "r");
4503
    if (fp == NULL) {
4504
        errorPrint("Failed to open sample file: %s, reason:%s\n",
4505
                stbInfo->sampleFile, strerror(errno));
4506 4507
        return -1;
    }
4508

4509 4510
    assert(stbInfo->sampleDataBuf);
    memset(stbInfo->sampleDataBuf, 0,
4511
            MAX_SAMPLES * stbInfo->lenOfOneRow);
4512 4513 4514 4515
    while(1) {
        readLen = tgetline(&line, &n, fp);
        if (-1 == readLen) {
            if(0 != fseek(fp, 0, SEEK_SET)) {
4516
                errorPrint("Failed to fseek file: %s, reason:%s\n",
4517
                        stbInfo->sampleFile, strerror(errno));
4518 4519 4520 4521 4522
                fclose(fp);
                return -1;
            }
            continue;
        }
4523

4524 4525 4526
        if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
            line[--readLen] = 0;
        }
4527

4528 4529 4530
        if (readLen == 0) {
            continue;
        }
4531

4532
        if (readLen > stbInfo->lenOfOneRow) {
4533
            printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
4534
                    (int32_t)readLen, stbInfo->lenOfOneRow);
4535 4536
            continue;
        }
4537

4538
        memcpy(stbInfo->sampleDataBuf + getRows * stbInfo->lenOfOneRow,
4539 4540 4541
                line, readLen);
        getRows++;

4542
        if (getRows == MAX_SAMPLES) {
4543 4544
            break;
        }
4545 4546
    }

4547 4548 4549
    fclose(fp);
    tmfree(line);
    return 0;
4550 4551
}

4552
static bool getColumnAndTagTypeFromInsertJsonFile(
4553
        cJSON* stbInfo, SSuperTable* superTbls) {
4554 4555 4556 4557 4558
    bool  ret = false;

    // columns
    cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
    if (columns && columns->type != cJSON_Array) {
4559
        errorPrint("%s", "failed to read json, columns not found\n");
4560 4561 4562 4563 4564 4565
        goto PARSE_OVER;
    } else if (NULL == columns) {
        superTbls->columnCount = 0;
        superTbls->tagCount    = 0;
        return true;
    }
4566

4567 4568
    int columnSize = cJSON_GetArraySize(columns);
    if ((columnSize + 1/* ts */) > TSDB_MAX_COLUMNS) {
4569 4570
        errorPrint("failed to read json, column size overflow, max column size is %d\n",
                TSDB_MAX_COLUMNS);
4571 4572
        goto PARSE_OVER;
    }
4573

4574 4575 4576
    int count = 1;
    int index = 0;
    StrColumn    columnCase;
4577

4578 4579 4580 4581
    //superTbls->columnCount = columnSize;
    for (int k = 0; k < columnSize; ++k) {
        cJSON* column = cJSON_GetArrayItem(columns, k);
        if (column == NULL) continue;
4582

4583 4584 4585 4586 4587
        count = 1;
        cJSON* countObj = cJSON_GetObjectItem(column, "count");
        if (countObj && countObj->type == cJSON_Number) {
            count = countObj->valueint;
        } else if (countObj && countObj->type != cJSON_Number) {
4588
            errorPrint("%s", "failed to read json, column count not found\n");
4589 4590 4591 4592 4593 4594 4595 4596 4597 4598
            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) {
4599
            errorPrint("%s", "failed to read json, column type not found\n");
4600 4601
            goto PARSE_OVER;
        }
4602 4603 4604
        //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, DATATYPE_BUFF_LEN);
        tstrncpy(columnCase.dataType, dataType->valuestring,
                min(DATATYPE_BUFF_LEN, strlen(dataType->valuestring) + 1));
4605 4606 4607 4608 4609 4610 4611 4612 4613

        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 {
4614
            columnCase.dataLen = SMALL_BUFF_LEN;
4615 4616 4617 4618
        }

        for (int n = 0; n < count; ++n) {
            tstrncpy(superTbls->columns[index].dataType,
4619 4620
                    columnCase.dataType,
                    min(DATATYPE_BUFF_LEN, strlen(columnCase.dataType) + 1));
4621

4622 4623 4624 4625 4626 4627
            superTbls->columns[index].dataLen = columnCase.dataLen;
            index++;
        }
    }

    if ((index + 1 /* ts */) > MAX_NUM_COLUMNS) {
4628 4629
        errorPrint("failed to read json, column size overflow, allowed max column size is %d\n",
                MAX_NUM_COLUMNS);
4630 4631 4632 4633
        goto PARSE_OVER;
    }

    superTbls->columnCount = index;
4634

4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670
    for (int c = 0; c < superTbls->columnCount; c++) {
        if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "INT", strlen("INT"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_INT;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "TINYINT", strlen("TINYINT"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_TINYINT;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "SMALLINT", strlen("SMALLINT"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_SMALLINT;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "BIGINT", strlen("BIGINT"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_BIGINT;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "FLOAT", strlen("FLOAT"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_FLOAT;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "DOUBLE", strlen("DOUBLE"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_DOUBLE;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "BINARY", strlen("BINARY"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_BINARY;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "NCHAR", strlen("NCHAR"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_NCHAR;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "BOOL", strlen("BOOL"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_BOOL;
        } else if (0 == strncasecmp(superTbls->columns[c].dataType,
                    "TIMESTAMP", strlen("TIMESTAMP"))) {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_TIMESTAMP;
        } else {
            superTbls->columns[c].data_type = TSDB_DATA_TYPE_NULL;
        }
    }

4671
    count = 1;
4672 4673 4674 4675
    index = 0;
    // tags
    cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
    if (!tags || tags->type != cJSON_Array) {
4676
        errorPrint("%s", "failed to read json, tags not found\n");
4677 4678 4679 4680 4681
        goto PARSE_OVER;
    }

    int tagSize = cJSON_GetArraySize(tags);
    if (tagSize > TSDB_MAX_TAGS) {
4682 4683
        errorPrint("failed to read json, tags size overflow, max tag size is %d\n",
                TSDB_MAX_TAGS);
4684
        goto PARSE_OVER;
4685 4686
    }

4687 4688 4689 4690 4691 4692 4693 4694 4695 4696
    //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) {
4697
            errorPrint("%s", "failed to read json, column count not found\n");
4698 4699 4700 4701 4702 4703 4704 4705 4706 4707
            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) {
4708
            errorPrint("%s", "failed to read json, tag type not found\n");
4709 4710
            goto PARSE_OVER;
        }
4711 4712
        tstrncpy(columnCase.dataType, dataType->valuestring,
                min(DATATYPE_BUFF_LEN, strlen(dataType->valuestring) + 1));
4713 4714 4715 4716 4717

        cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
        if (dataLen && dataLen->type == cJSON_Number) {
            columnCase.dataLen = dataLen->valueint;
        } else if (dataLen && dataLen->type != cJSON_Number) {
4718
            errorPrint("%s", "failed to read json, column len not found\n");
4719 4720 4721 4722 4723 4724 4725
            goto PARSE_OVER;
        } else {
            columnCase.dataLen = 0;
        }

        for (int n = 0; n < count; ++n) {
            tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
4726
                    min(DATATYPE_BUFF_LEN, strlen(columnCase.dataType) + 1));
4727 4728 4729
            superTbls->tags[index].dataLen = columnCase.dataLen;
            index++;
        }
4730
    }
4731

4732
    if (index > TSDB_MAX_TAGS) {
4733 4734
        errorPrint("failed to read json, tags size overflow, allowed max tag count is %d\n",
                TSDB_MAX_TAGS);
4735 4736
        goto PARSE_OVER;
    }
4737

4738
    superTbls->tagCount = index;
4739

4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775
    for (int t = 0; t < superTbls->tagCount; t++) {
        if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "INT", strlen("INT"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_INT;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "TINYINT", strlen("TINYINT"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_TINYINT;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "SMALLINT", strlen("SMALLINT"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_SMALLINT;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "BIGINT", strlen("BIGINT"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_BIGINT;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "FLOAT", strlen("FLOAT"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_FLOAT;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "DOUBLE", strlen("DOUBLE"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_DOUBLE;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "BINARY", strlen("BINARY"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_BINARY;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "NCHAR", strlen("NCHAR"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_NCHAR;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "BOOL", strlen("BOOL"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_BOOL;
        } else if (0 == strncasecmp(superTbls->tags[t].dataType,
                    "TIMESTAMP", strlen("TIMESTAMP"))) {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_TIMESTAMP;
        } else {
            superTbls->tags[t].data_type = TSDB_DATA_TYPE_NULL;
        }
    }

4776
    if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > TSDB_MAX_COLUMNS) {
4777 4778
        errorPrint("columns + tags is more than allowed max columns count: %d\n",
                TSDB_MAX_COLUMNS);
4779 4780 4781
        goto PARSE_OVER;
    }
    ret = true;
4782

4783
PARSE_OVER:
4784
    return ret;
4785 4786 4787
}

static bool getMetaFromInsertJsonFile(cJSON* root) {
4788
    bool  ret = false;
4789

4790 4791 4792
    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);
4793
    }
4794

4795 4796 4797 4798 4799
    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);
4800
    } else {
4801
        errorPrint("%s", "failed to read json, host not found\n");
4802
        goto PARSE_OVER;
4803 4804
    }

4805 4806 4807 4808 4809
    cJSON* port = cJSON_GetObjectItem(root, "port");
    if (port && port->type == cJSON_Number) {
        g_Dbs.port = port->valueint;
    } else if (!port) {
        g_Dbs.port = 6030;
4810
    }
4811

4812 4813 4814 4815 4816
    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);
4817 4818
    }

4819 4820
    cJSON* password = cJSON_GetObjectItem(root, "password");
    if (password && password->type == cJSON_String && password->valuestring != NULL) {
4821
        tstrncpy(g_Dbs.password, password->valuestring, SHELL_MAX_PASSWORD_LEN);
4822
    } else if (!password) {
4823
        tstrncpy(g_Dbs.password, "taosdata", SHELL_MAX_PASSWORD_LEN);
4824 4825
    }

4826 4827 4828 4829 4830
    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);
4831 4832
    }

4833 4834 4835 4836 4837
    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;
4838
    } else {
4839
        errorPrint("%s", "failed to read json, threads not found\n");
4840
        goto PARSE_OVER;
4841
    }
4842

4843 4844
    cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
    if (threads2 && threads2->type == cJSON_Number) {
4845
        g_Dbs.threadCountForCreateTbl = threads2->valueint;
4846
    } else if (!threads2) {
4847
        g_Dbs.threadCountForCreateTbl = 1;
4848
    } else {
4849
        errorPrint("%s", "failed to read json, threads2 not found\n");
4850
        goto PARSE_OVER;
4851
    }
4852

4853 4854 4855
    cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
    if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
        if (gInsertInterval->valueint <0) {
4856
            errorPrint("%s", "failed to read json, insert interval input mistake\n");
4857 4858 4859 4860 4861
            goto PARSE_OVER;
        }
        g_args.insert_interval = gInsertInterval->valueint;
    } else if (!gInsertInterval) {
        g_args.insert_interval = 0;
4862
    } else {
4863
        errorPrint("%s", "failed to read json, insert_interval input mistake\n");
4864
        goto PARSE_OVER;
4865
    }
4866

4867 4868 4869
    cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
    if (interlaceRows && interlaceRows->type == cJSON_Number) {
        if (interlaceRows->valueint < 0) {
4870
            errorPrint("%s", "failed to read json, interlaceRows input mistake\n");
4871
            goto PARSE_OVER;
4872

4873
        }
4874
        g_args.interlaceRows = interlaceRows->valueint;
4875
    } else if (!interlaceRows) {
4876
        g_args.interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
4877
    } else {
4878
        errorPrint("%s", "failed to read json, interlaceRows input mistake\n");
4879
        goto PARSE_OVER;
4880 4881
    }

4882 4883 4884 4885 4886 4887 4888 4889 4890 4891
    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);
4892
    } else {
4893 4894 4895
        errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
                __func__, __LINE__);
        goto PARSE_OVER;
4896 4897
    }

4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911
    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;
        }
4912
        g_args.reqPerReq = numRecPerReq->valueint;
4913
    } else if (!numRecPerReq) {
4914
        g_args.reqPerReq = MAX_RECORDS_PER_REQ;
4915
    } else {
4916 4917 4918
        errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
                __func__, __LINE__);
        goto PARSE_OVER;
4919 4920
    }

4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933
    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.
4934
    } else {
4935 4936
        errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
        goto PARSE_OVER;
4937 4938
    }

4939
    // rows per table need be less than insert batch
4940
    if (g_args.interlaceRows > g_args.reqPerReq) {
4941
        printf("NOTICE: interlace rows value %u > num_of_records_per_req %u\n\n",
4942
                g_args.interlaceRows, g_args.reqPerReq);
4943
        printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
4944
                g_args.reqPerReq);
4945
        prompt();
4946
        g_args.interlaceRows = g_args.reqPerReq;
4947 4948
    }

4949 4950
    cJSON* dbs = cJSON_GetObjectItem(root, "databases");
    if (!dbs || dbs->type != cJSON_Array) {
4951
        errorPrint("%s", "failed to read json, databases not found\n");
4952
        goto PARSE_OVER;
4953
    }
4954

4955 4956 4957
    int dbSize = cJSON_GetArraySize(dbs);
    if (dbSize > MAX_DB_COUNT) {
        errorPrint(
4958
                "failed to read json, databases size overflow, max database is %d\n",
4959 4960
                MAX_DB_COUNT);
        goto PARSE_OVER;
4961 4962
    }

4963 4964 4965 4966
    g_Dbs.dbCount = dbSize;
    for (int i = 0; i < dbSize; ++i) {
        cJSON* dbinfos = cJSON_GetArrayItem(dbs, i);
        if (dbinfos == NULL) continue;
4967

4968 4969 4970
        // dbinfo
        cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
        if (!dbinfo || dbinfo->type != cJSON_Object) {
4971
            errorPrint("%s", "failed to read json, dbinfo not found\n");
4972 4973
            goto PARSE_OVER;
        }
4974

4975 4976
        cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
        if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
4977
            errorPrint("%s", "failed to read json, db name not found\n");
4978 4979 4980
            goto PARSE_OVER;
        }
        tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, TSDB_DB_NAME_LEN);
4981

4982 4983 4984 4985 4986 4987 4988 4989 4990 4991
        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 {
4992
            errorPrint("%s", "failed to read json, drop input mistake\n");
4993 4994
            goto PARSE_OVER;
        }
4995

4996 4997 4998 4999
        cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
        if (precision && precision->type == cJSON_String
                && precision->valuestring != NULL) {
            tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
5000
                    SMALL_BUFF_LEN);
5001
        } else if (!precision) {
5002
            memset(g_Dbs.db[i].dbCfg.precision, 0, SMALL_BUFF_LEN);
5003
        } else {
5004
            errorPrint("%s", "failed to read json, precision not found\n");
5005 5006
            goto PARSE_OVER;
        }
5007

5008 5009 5010 5011 5012
        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;
5013
        } else {
5014
            errorPrint("%s", "failed to read json, update not found\n");
5015
            goto PARSE_OVER;
5016
        }
5017

5018 5019 5020 5021 5022 5023
        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 {
5024
            errorPrint("%s", "failed to read json, replica not found\n");
5025 5026
            goto PARSE_OVER;
        }
5027

5028 5029 5030 5031 5032 5033
        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 {
5034
            errorPrint("%s", "failed to read json, keep not found\n");
5035 5036
            goto PARSE_OVER;
        }
5037

5038 5039 5040 5041 5042
        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;
5043
        } else {
5044
            errorPrint("%s", "failed to read json, days not found\n");
5045 5046
            goto PARSE_OVER;
        }
5047

5048 5049 5050 5051 5052 5053
        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 {
5054
            errorPrint("%s", "failed to read json, cache not found\n");
5055
            goto PARSE_OVER;
5056 5057
        }

5058 5059 5060 5061 5062 5063
        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 {
5064
            errorPrint("%s", "failed to read json, block not found\n");
5065
            goto PARSE_OVER;
5066 5067
        }

5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083
        //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 {
5084
            errorPrint("%s", "failed to read json, minRows not found\n");
5085 5086
            goto PARSE_OVER;
        }
5087

5088 5089 5090 5091 5092 5093
        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 {
5094
            errorPrint("%s", "failed to read json, maxRows not found\n");
5095 5096
            goto PARSE_OVER;
        }
5097

5098 5099 5100 5101 5102 5103
        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 {
5104
            errorPrint("%s", "failed to read json, comp not found\n");
5105 5106
            goto PARSE_OVER;
        }
5107

5108 5109 5110 5111 5112 5113
        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 {
5114
            errorPrint("%s", "failed to read json, walLevel not found\n");
5115 5116
            goto PARSE_OVER;
        }
5117

5118 5119 5120 5121 5122
        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;
5123
        } else {
5124
            errorPrint("%s", "failed to read json, cacheLast not found\n");
5125
            goto PARSE_OVER;
5126
        }
5127

5128 5129 5130 5131 5132
        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;
5133
        } else {
5134 5135
            printf("failed to read json, quorum input mistake");
            goto PARSE_OVER;
5136
        }
5137 5138 5139 5140 5141 5142 5143

        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 {
5144
            errorPrint("%s", "failed to read json, fsync input mistake\n");
5145
            goto PARSE_OVER;
5146 5147
        }

5148
        // super_tables
5149 5150
        cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
        if (!stables || stables->type != cJSON_Array) {
5151
            errorPrint("%s", "failed to read json, super_tables not found\n");
5152
            goto PARSE_OVER;
5153
        }
5154

5155 5156 5157
        int stbSize = cJSON_GetArraySize(stables);
        if (stbSize > MAX_SUPER_TABLE_COUNT) {
            errorPrint(
5158 5159
                    "failed to read json, supertable size overflow, max supertable is %d\n",
                    MAX_SUPER_TABLE_COUNT);
5160
            goto PARSE_OVER;
5161
        }
5162

5163 5164 5165 5166
        g_Dbs.db[i].superTblCount = stbSize;
        for (int j = 0; j < stbSize; ++j) {
            cJSON* stbInfo = cJSON_GetArrayItem(stables, j);
            if (stbInfo == NULL) continue;
5167

5168 5169 5170 5171
            // dbinfo
            cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
            if (!stbName || stbName->type != cJSON_String
                    || stbName->valuestring == NULL) {
5172
                errorPrint("%s", "failed to read json, stb name not found\n");
5173 5174
                goto PARSE_OVER;
            }
5175
            tstrncpy(g_Dbs.db[i].superTbls[j].stbName, stbName->valuestring,
5176
                    TSDB_TABLE_NAME_LEN);
5177

5178 5179
            cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
            if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
5180
                errorPrint("%s", "failed to read json, childtable_prefix not found\n");
5181 5182 5183
                goto PARSE_OVER;
            }
            tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring,
5184
                    TBNAME_PREFIX_LEN);
5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200

            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 {
5201
                errorPrint("%s", "failed to read json, auto_create_table not found\n");
5202 5203
                goto PARSE_OVER;
            }
5204

5205 5206 5207 5208
            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) {
5209
                g_Dbs.db[i].superTbls[j].batchCreateTableNum = 10;
5210
            } else {
5211
                errorPrint("%s", "failed to read json, batch_create_tbl_num not found\n");
5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230
                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 {
5231 5232
                errorPrint("%s",
                        "failed to read json, child_table_exists not found\n");
5233 5234 5235 5236 5237 5238 5239 5240 5241
                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) {
5242 5243
                errorPrint("%s",
                        "failed to read json, childtable_count input mistake\n");
5244 5245 5246
                goto PARSE_OVER;
            }
            g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;
5247
            g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;
5248 5249 5250 5251 5252

            cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
            if (dataSource && dataSource->type == cJSON_String
                    && dataSource->valuestring != NULL) {
                tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
5253 5254
                        dataSource->valuestring,
                        min(SMALL_BUFF_LEN, strlen(dataSource->valuestring) + 1));
5255
            } else if (!dataSource) {
5256 5257
                tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand",
                        min(SMALL_BUFF_LEN, strlen("rand") + 1));
5258
            } else {
5259
                errorPrint("%s", "failed to read json, data_source not found\n");
5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272
                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 {
5273 5274
                    errorPrint("failed to read json, insert_mode %s not recognized\n",
                            stbIface->valuestring);
5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287
                    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) {
5288
                    errorPrint("%s", "failed to read json, childtable_limit\n");
5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300
                    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)) {
5301
                    errorPrint("%s", "failed to read json, childtable_offset\n");
5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316
                    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 {
5317
                errorPrint("%s", "failed to read json, start_timestamp not found\n");
5318 5319 5320 5321 5322 5323 5324
                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) {
5325
                g_Dbs.db[i].superTbls[j].timeStampStep = g_args.timestamp_step;
5326
            } else {
5327
                errorPrint("%s", "failed to read json, timestamp_step not found\n");
5328 5329 5330 5331 5332 5333 5334
                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,
5335 5336 5337
                        sampleFormat->valuestring,
                        min(SMALL_BUFF_LEN,
                            strlen(sampleFormat->valuestring) + 1));
5338
            } else if (!sampleFormat) {
5339 5340
                tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv",
                        SMALL_BUFF_LEN);
5341
            } else {
5342
                errorPrint("%s", "failed to read json, sample_format not found\n");
5343 5344 5345 5346 5347 5348 5349
                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,
5350 5351 5352
                        sampleFile->valuestring,
                        min(MAX_FILE_NAME_LEN,
                            strlen(sampleFile->valuestring) + 1));
5353
            } else if (!sampleFile) {
5354 5355
                memset(g_Dbs.db[i].superTbls[j].sampleFile, 0,
                        MAX_FILE_NAME_LEN);
5356
            } else {
5357
                errorPrint("%s", "failed to read json, sample_file not found\n");
5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374
                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 {
5375
                errorPrint("%s", "failed to read json, tags_file not found\n");
5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390
                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 {
5391
                errorPrint("%s", "failed to read json, stbMaxSqlLen input mistake\n");
5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407
                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 {
5408
               errorPrint("%s", "failed to read json, multiThreadWriteOneTbl not found\n");
5409 5410 5411 5412 5413 5414
               goto PARSE_OVER;
               }
               */
            cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
            if (insertRows && insertRows->type == cJSON_Number) {
                if (insertRows->valueint < 0) {
5415
                    errorPrint("%s", "failed to read json, insert_rows input mistake\n");
5416 5417 5418 5419 5420 5421
                    goto PARSE_OVER;
                }
                g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
            } else if (!insertRows) {
                g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
            } else {
5422
                errorPrint("%s", "failed to read json, insert_rows input mistake\n");
5423 5424 5425 5426 5427 5428
                goto PARSE_OVER;
            }

            cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
            if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) {
                if (stbInterlaceRows->valueint < 0) {
5429
                    errorPrint("%s", "failed to read json, interlace rows input mistake\n");
5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443
                    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) {
5444
                g_Dbs.db[i].superTbls[j].interlaceRows = g_args.interlaceRows; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
5445 5446
            } else {
                errorPrint(
5447
                        "%s", "failed to read json, interlace rows input mistake\n");
5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462
                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 {
5463
                errorPrint("%s", "failed to read json, disorderRatio not found\n");
5464 5465 5466 5467 5468 5469 5470 5471 5472
                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 {
5473
                errorPrint("%s", "failed to read json, disorderRange not found\n");
5474 5475 5476 5477 5478 5479 5480
                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) {
5481
                    errorPrint("%s", "failed to read json, insert_interval input mistake\n");
5482 5483 5484
                    goto PARSE_OVER;
                }
            } else if (!insertInterval) {
5485
                verbosePrint("%s() LN%d: stable insert interval be overrode by global %"PRIu64".\n",
5486 5487 5488
                        __func__, __LINE__, g_args.insert_interval);
                g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
            } else {
5489
                errorPrint("%s", "failed to read json, insert_interval input mistake\n");
5490 5491
                goto PARSE_OVER;
            }
5492

5493 5494 5495 5496 5497
            int retVal = getColumnAndTagTypeFromInsertJsonFile(
                    stbInfo, &g_Dbs.db[i].superTbls[j]);
            if (false == retVal) {
                goto PARSE_OVER;
            }
5498
        }
5499
    }
5500

5501
    ret = true;
5502

5503
PARSE_OVER:
5504
    return ret;
5505 5506 5507
}

static bool getMetaFromQueryJsonFile(cJSON* root) {
5508
    bool  ret = false;
5509

5510 5511 5512 5513
    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 已提交
5514

5515 5516 5517 5518 5519
    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 已提交
5520
    } else {
5521
        errorPrint("%s", "failed to read json, host not found\n");
5522
        goto PARSE_OVER;
H
hzcheng 已提交
5523
    }
5524

5525 5526 5527 5528 5529
    cJSON* port = cJSON_GetObjectItem(root, "port");
    if (port && port->type == cJSON_Number) {
        g_queryInfo.port = port->valueint;
    } else if (!port) {
        g_queryInfo.port = 6030;
5530
    }
5531

5532 5533 5534 5535 5536
    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); ;
5537 5538
    }

5539 5540
    cJSON* password = cJSON_GetObjectItem(root, "password");
    if (password && password->type == cJSON_String && password->valuestring != NULL) {
5541
        tstrncpy(g_queryInfo.password, password->valuestring, SHELL_MAX_PASSWORD_LEN);
5542
    } else if (!password) {
5543
        tstrncpy(g_queryInfo.password, "taosdata", SHELL_MAX_PASSWORD_LEN);;
5544
    }
5545

5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557
    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;
5558
    } else {
5559
        errorPrint("%s", "failed to read json, confirm_parameter_prompt not found\n");
5560
        goto PARSE_OVER;
5561
    }
5562

5563 5564 5565
    cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
    if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
        if (gQueryTimes->valueint <= 0) {
5566
            errorPrint("%s()", "failed to read json, query_times input mistake\n");
5567 5568 5569 5570 5571
            goto PARSE_OVER;
        }
        g_args.query_times = gQueryTimes->valueint;
    } else if (!gQueryTimes) {
        g_args.query_times = 1;
5572
    } else {
5573
        errorPrint("%s", "failed to read json, query_times input mistake\n");
5574
        goto PARSE_OVER;
5575
    }
5576

5577 5578 5579 5580
    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) {
5581
        errorPrint("%s", "failed to read json, databases not found\n");
5582
        goto PARSE_OVER;
5583
    }
5584

5585
    cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
5586 5587 5588 5589 5590
    if (queryMode
            && queryMode->type == cJSON_String
            && queryMode->valuestring != NULL) {
        tstrncpy(g_queryInfo.queryMode, queryMode->valuestring,
                min(SMALL_BUFF_LEN, strlen(queryMode->valuestring) + 1));
5591
    } else if (!queryMode) {
5592 5593
        tstrncpy(g_queryInfo.queryMode, "taosc",
                min(SMALL_BUFF_LEN, strlen("taosc") + 1));
5594
    } else {
5595
        errorPrint("%s", "failed to read json, query_mode not found\n");
5596
        goto PARSE_OVER;
5597
    }
5598

5599 5600 5601 5602 5603 5604
    // 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) {
5605
        errorPrint("%s", "failed to read json, super_table_query not found\n");
5606 5607
        goto PARSE_OVER;
    } else {
5608 5609 5610 5611 5612 5613
        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;
        }
5614

5615 5616 5617 5618 5619
        cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
                "query_times");
        if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
            if (specifiedQueryTimes->valueint <= 0) {
                errorPrint(
5620 5621
                        "failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                        specifiedQueryTimes->valueint);
5622
                goto PARSE_OVER;
5623

5624 5625 5626 5627
            }
            g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
        } else if (!specifiedQueryTimes) {
            g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
5628
        } else {
5629 5630 5631
            errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
                    __func__, __LINE__);
            goto PARSE_OVER;
5632
        }
5633

5634 5635 5636 5637
        cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
        if (concurrent && concurrent->type == cJSON_Number) {
            if (concurrent->valueint <= 0) {
                errorPrint(
5638
                        "query sqlCount %d or concurrent %d is not correct.\n",
5639 5640 5641 5642 5643 5644 5645 5646
                        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;
        }
5647

5648 5649 5650 5651 5652 5653 5654 5655
        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 {
5656
                errorPrint("%s", "failed to read json, async mode input error\n");
5657 5658 5659 5660 5661
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
        }
5662

5663 5664 5665 5666 5667 5668 5669 5670
        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;
        }
5671

5672 5673 5674 5675 5676 5677 5678
        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 {
5679
                errorPrint("%s", "failed to read json, subscribe restart error\n");
5680 5681 5682 5683 5684
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
        }
5685

5686 5687 5688 5689 5690 5691 5692 5693 5694
        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 {
5695
                errorPrint("%s", "failed to read json, subscribe keepProgress error\n");
5696 5697 5698 5699 5700
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
        }
5701

5702 5703 5704 5705 5706
        // sqls
        cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
        if (!specifiedSqls) {
            g_queryInfo.specifiedQueryInfo.sqlCount = 0;
        } else if (specifiedSqls->type != cJSON_Array) {
5707
            errorPrint("%s", "failed to read json, super sqls not found\n");
5708 5709 5710 5711 5712
            goto PARSE_OVER;
        } else {
            int superSqlSize = cJSON_GetArraySize(specifiedSqls);
            if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent
                    > MAX_QUERY_SQL_COUNT) {
5713
                errorPrint("failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n",
5714 5715 5716 5717 5718
                        superSqlSize,
                        g_queryInfo.specifiedQueryInfo.concurrent,
                        MAX_QUERY_SQL_COUNT);
                goto PARSE_OVER;
            }
5719

5720 5721 5722 5723 5724 5725 5726
            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) {
5727
                    errorPrint("%s", "failed to read json, sql not found\n");
5728 5729 5730
                    goto PARSE_OVER;
                }
                tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
5731
                        sqlStr->valuestring, BUFFER_SIZE);
5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766

                // 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 {
5767 5768
                    errorPrint("%s",
                            "failed to read json, super query result file not found\n");
5769 5770 5771 5772
                    goto PARSE_OVER;
                }
            }
        }
5773
    }
5774

5775 5776 5777 5778 5779 5780
    // 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) {
5781
        errorPrint("%s", "failed to read json, sub_table_query not found\n");
5782
        ret = true;
5783 5784
        goto PARSE_OVER;
    } else {
5785 5786 5787 5788 5789 5790 5791 5792 5793 5794
        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) {
5795 5796
                errorPrint("failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                        superQueryTimes->valueint);
5797 5798 5799 5800 5801 5802
                goto PARSE_OVER;
            }
            g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
        } else if (!superQueryTimes) {
            g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
        } else {
5803
            errorPrint("%s", "failed to read json, query_times input mistake\n");
5804 5805
            goto PARSE_OVER;
        }
5806

5807 5808 5809
        cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
        if (threads && threads->type == cJSON_Number) {
            if (threads->valueint <= 0) {
5810
                errorPrint("%s", "failed to read json, threads input mistake\n");
5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828
                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) {
5829
            tstrncpy(g_queryInfo.superQueryInfo.stbName, stblname->valuestring,
5830 5831
                    TSDB_TABLE_NAME_LEN);
        } else {
5832
            errorPrint("%s", "failed to read json, super table name input error\n");
5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843
            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 {
5844
                errorPrint("%s", "failed to read json, async mode input error\n");
5845 5846 5847 5848 5849 5850 5851 5852 5853
                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) {
5854
                errorPrint("%s", "failed to read json, interval input mistake\n");
5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871
                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 {
5872
                errorPrint("%s", "failed to read json, subscribe restart error\n");
5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887
                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 {
5888 5889
                errorPrint("%s",
                        "failed to read json, subscribe super table keepProgress error\n");
5890 5891 5892 5893 5894 5895 5896
                goto PARSE_OVER;
            }
        } else {
            g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
        }

        // default value is -1, which mean do not resub
5897
        g_queryInfo.superQueryInfo.endAfterConsume = -1;
5898 5899 5900 5901 5902 5903 5904 5905 5906
        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;
5907

5908
        // default value is -1, which mean do not resub
5909
        g_queryInfo.superQueryInfo.resubAfterConsume = -1;
5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925
        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) {
5926
            errorPrint("%s", "failed to read json, super sqls not found\n");
5927 5928 5929 5930
            goto PARSE_OVER;
        } else {
            int superSqlSize = cJSON_GetArraySize(superSqls);
            if (superSqlSize > MAX_QUERY_SQL_COUNT) {
5931 5932
                errorPrint("failed to read json, query sql size overflow, max is %d\n",
                        MAX_QUERY_SQL_COUNT);
5933 5934
                goto PARSE_OVER;
            }
5935

5936 5937 5938 5939
            g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
            for (int j = 0; j < superSqlSize; ++j) {
                cJSON* sql = cJSON_GetArrayItem(superSqls, j);
                if (sql == NULL) continue;
5940

5941 5942 5943
                cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
                if (!sqlStr || sqlStr->type != cJSON_String
                        || sqlStr->valuestring == NULL) {
5944
                    errorPrint("%s", "failed to read json, sql not found\n");
5945 5946 5947
                    goto PARSE_OVER;
                }
                tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
5948
                        BUFFER_SIZE);
5949 5950 5951

                cJSON *result = cJSON_GetObjectItem(sql, "result");
                if (result != NULL && result->type == cJSON_String
5952
                        && result->valuestring != NULL) {
5953 5954 5955 5956 5957
                    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 {
5958
                    errorPrint("%s", "failed to read json, sub query result file not found\n");
5959 5960 5961
                    goto PARSE_OVER;
                }
            }
5962
        }
5963
    }
H
hzcheng 已提交
5964

5965
    ret = true;
H
hzcheng 已提交
5966

5967
PARSE_OVER:
5968
    return ret;
5969
}
H
hzcheng 已提交
5970

5971
static bool getInfoFromJsonFile(char* file) {
5972
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
5973

5974 5975
    FILE *fp = fopen(file, "r");
    if (!fp) {
5976
        errorPrint("failed to read %s, reason:%s\n", file, strerror(errno));
5977 5978
        return false;
    }
H
Hui Li 已提交
5979

5980 5981 5982 5983 5984 5985 5986
    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);
5987
        errorPrint("failed to read %s, content is null", file);
5988 5989
        return false;
    }
H
Hui Li 已提交
5990

5991 5992 5993
    content[len] = 0;
    cJSON* root = cJSON_Parse(content);
    if (root == NULL) {
5994
        errorPrint("failed to cjson parse %s, invalid json format\n", file);
5995 5996
        goto PARSE_OVER;
    }
H
Hui Li 已提交
5997

5998 5999 6000 6001 6002 6003 6004 6005 6006
    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 {
6007
            errorPrint("%s", "failed to read json, filetype not support\n");
6008 6009 6010 6011
            goto PARSE_OVER;
        }
    } else if (!filetype) {
        g_args.test_mode = INSERT_TEST;
6012
    } else {
6013
        errorPrint("%s", "failed to read json, filetype not found\n");
6014
        goto PARSE_OVER;
6015
    }
H
hzcheng 已提交
6016

6017 6018 6019 6020 6021 6022
    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 {
6023 6024
        errorPrint("%s",
                "input json file type error! please input correct file type: insert or query or subscribe\n");
6025 6026
        goto PARSE_OVER;
    }
6027

6028
PARSE_OVER:
6029 6030 6031 6032
    free(content);
    cJSON_Delete(root);
    fclose(fp);
    return ret;
6033
}
H
hzcheng 已提交
6034

6035
static int prepareSampleData() {
6036 6037 6038 6039 6040 6041 6042
    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;
                }
            }
6043
        }
6044
    }
6045

6046
    return 0;
6047 6048
}

6049
static void postFreeResource() {
6050
    tmfclose(g_fpOfInsertResult);
6051

6052 6053 6054
    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) {
6055
                tmfree(g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
6056 6057 6058
                g_Dbs.db[i].superTbls[j].colsOfCreateChildTable = NULL;
            }
            if (0 != g_Dbs.db[i].superTbls[j].sampleDataBuf) {
6059
                tmfree(g_Dbs.db[i].superTbls[j].sampleDataBuf);
6060 6061
                g_Dbs.db[i].superTbls[j].sampleDataBuf = NULL;
            }
6062

6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075
#if STMT_BIND_PARAM_BATCH == 1
            for (int c = 0;
                    c < g_Dbs.db[i].superTbls[j].columnCount; c ++) {

                if (g_Dbs.db[i].superTbls[j].sampleBindBatchArray) {

                    tmfree((char *)((uintptr_t)*(uintptr_t*)(
                                    g_Dbs.db[i].superTbls[j].sampleBindBatchArray
                                    + sizeof(char*) * c)));
                }
            }
            tmfree(g_Dbs.db[i].superTbls[j].sampleBindBatchArray);
#endif
6076
            if (0 != g_Dbs.db[i].superTbls[j].tagDataBuf) {
6077
                tmfree(g_Dbs.db[i].superTbls[j].tagDataBuf);
6078 6079 6080
                g_Dbs.db[i].superTbls[j].tagDataBuf = NULL;
            }
            if (0 != g_Dbs.db[i].superTbls[j].childTblName) {
6081
                tmfree(g_Dbs.db[i].superTbls[j].childTblName);
6082 6083 6084
                g_Dbs.db[i].superTbls[j].childTblName = NULL;
            }
        }
S
Shuaiqiang Chang 已提交
6085
    }
6086 6087 6088 6089 6090 6091 6092 6093 6094 6095

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

6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109
    tmfree(g_sampleDataBuf);

#if STMT_BIND_PARAM_BATCH == 1
    for (int l = 0;
             l < g_args.columnCount; l ++) {
        if (g_sampleBindBatchArray) {
            tmfree((char *)((uintptr_t)*(uintptr_t*)(
                            g_sampleBindBatchArray
                            + sizeof(char*) * l)));
        }
    }
    tmfree(g_sampleBindBatchArray);
#endif
6110
}
S
Shuaiqiang Chang 已提交
6111

6112 6113
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
6114
        SSuperTable* stbInfo, int64_t* sampleUsePos)
6115
{
6116
    if ((*sampleUsePos) == MAX_SAMPLES) {
6117 6118 6119 6120 6121 6122 6123 6124 6125
        *sampleUsePos = 0;
    }

    int    dataLen = 0;

    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "(%" PRId64 ", ", timestamp);
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "%s",
6126 6127
            stbInfo->sampleDataBuf
            + stbInfo->lenOfOneRow * (*sampleUsePos));
6128 6129 6130 6131 6132
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");

    (*sampleUsePos)++;

    return dataLen;
6133
}
S
Shuaiqiang Chang 已提交
6134

6135 6136
static int64_t generateStbRowData(
        SSuperTable* stbInfo,
6137 6138 6139
        char* recBuf,
        int64_t remainderBufLen,
        int64_t timestamp)
6140
{
6141 6142 6143
    int64_t   dataLen = 0;
    char  *pstr = recBuf;
    int64_t maxLen = MAX_DATA_SIZE;
6144
    int tmpLen;
6145 6146

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

    for (int i = 0; i < stbInfo->columnCount; i++) {
6150 6151 6152 6153 6154
        tstrncpy(pstr + dataLen, ",", 2);
        dataLen += 1;

        if ((stbInfo->columns[i].data_type == TSDB_DATA_TYPE_BINARY)
                || (stbInfo->columns[i].data_type == TSDB_DATA_TYPE_NCHAR)) {
6155
            if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
6156
                errorPrint2("binary or nchar length overflow, max size:%u\n",
6157 6158 6159
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
6160

6161 6162 6163 6164 6165
            if ((stbInfo->columns[i].dataLen + 1) >
                    /* need count 3 extra chars \', \', and , */
                    (remainderBufLen - dataLen - 3)) {
                return 0;
            }
6166 6167
            char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
            if (NULL == buf) {
6168
                errorPrint2("calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
6169 6170 6171
                return -1;
            }
            rand_string(buf, stbInfo->columns[i].dataLen);
6172
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\'", buf);
6173
            tmfree(buf);
6174

6175
        } else {
6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186
            char *tmp = NULL;
            switch(stbInfo->columns[i].data_type) {
                case TSDB_DATA_TYPE_INT:
                    if ((g_args.demo_mode) && (i == 1)) {
                        tmp = demo_voltage_int_str();
                    } else {
                        tmp = rand_int_str();
                    }
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen + 1, INT_BUFF_LEN));
                    break;
6187

6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199
                case TSDB_DATA_TYPE_BIGINT:
                    tmp = rand_bigint_str();
                    tstrncpy(pstr + dataLen, tmp, BIGINT_BUFF_LEN);
                    break;

                case TSDB_DATA_TYPE_FLOAT:
                    if (g_args.demo_mode) {
                        if (i == 0) {
                            tmp = demo_current_float_str();
                        } else {
                            tmp = demo_phase_float_str();
                        }
6200
                    } else {
6201
                        tmp = rand_float_str();
6202
                    }
6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, FLOAT_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_DOUBLE:
                    tmp = rand_double_str();
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, DOUBLE_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_SMALLINT:
                    tmp = rand_smallint_str();
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp,
                            min(tmpLen + 1, SMALLINT_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_TINYINT:
                    tmp = rand_tinyint_str();
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, TINYINT_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_BOOL:
                    tmp = rand_bool_str();
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BOOL_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_TIMESTAMP:
                    tmp = rand_bigint_str();
                    tmpLen = strlen(tmp);
                    tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BIGINT_BUFF_LEN));
                    break;

                case TSDB_DATA_TYPE_NULL:
                    break;

                default:
                    errorPrint2("Not support data type: %s\n",
                            stbInfo->columns[i].dataType);
                    exit(EXIT_FAILURE);
6245
            }
6246

6247 6248 6249
            if (tmp) {
                dataLen += strlen(tmp);
            }
6250
        }
6251

6252
        if (dataLen > (remainderBufLen - (128)))
6253
            return 0;
6254
    }
6255

6256
    tstrncpy(pstr + dataLen, ")", 2);
6257

6258 6259
    verbosePrint("%s() LN%d, dataLen:%"PRId64"\n", __func__, __LINE__, dataLen);
    verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);
6260

6261
    return strlen(recBuf);
6262
}
S
Shuaiqiang Chang 已提交
6263

6264
static int64_t generateData(char *recBuf, char *data_type,
6265
        int64_t timestamp, int lenOfBinary) {
6266 6267
    memset(recBuf, 0, MAX_DATA_SIZE);
    char *pstr = recBuf;
6268
    pstr += sprintf(pstr, "(%"PRId64"", timestamp);
6269

6270
    int columnCount = g_args.columnCount;
6271

6272 6273
    bool b;
    char *s;
6274
    for (int i = 0; i < columnCount; i++) {
6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339
        switch (data_type[i]) {
            case TSDB_DATA_TYPE_TINYINT:
                pstr += sprintf(pstr, ",%d", rand_tinyint() );
                break;

            case TSDB_DATA_TYPE_SMALLINT:
                pstr += sprintf(pstr, ",%d", rand_smallint());
                break;

            case TSDB_DATA_TYPE_INT:
                pstr += sprintf(pstr, ",%d", rand_int());
                break;

            case TSDB_DATA_TYPE_BIGINT:
                pstr += sprintf(pstr, ",%"PRId64"", rand_bigint());
                break;

            case TSDB_DATA_TYPE_TIMESTAMP:
                pstr += sprintf(pstr, ",%"PRId64"", rand_bigint());
                break;

            case TSDB_DATA_TYPE_FLOAT:
                pstr += sprintf(pstr, ",%10.4f", rand_float());
                break;

            case TSDB_DATA_TYPE_DOUBLE:
                pstr += sprintf(pstr, ",%20.8f", rand_double());
                break;

            case TSDB_DATA_TYPE_BOOL:
                b = rand_bool() & 1;
                pstr += sprintf(pstr, ",%s", b ? "true" : "false");
                break;

            case TSDB_DATA_TYPE_BINARY:
                s = malloc(lenOfBinary + 1);
                if (s == NULL) {
                    errorPrint2("%s() LN%d, memory allocation %d bytes failed\n",
                            __func__, __LINE__, lenOfBinary + 1);
                    exit(EXIT_FAILURE);
                }
                rand_string(s, lenOfBinary);
                pstr += sprintf(pstr, ",\"%s\"", s);
                free(s);
                break;

            case TSDB_DATA_TYPE_NCHAR:
                s = malloc(lenOfBinary + 1);
                if (s == NULL) {
                    errorPrint2("%s() LN%d, memory allocation %d bytes failed\n",
                            __func__, __LINE__, lenOfBinary + 1);
                    exit(EXIT_FAILURE);
                }
                rand_string(s, lenOfBinary);
                pstr += sprintf(pstr, ",\"%s\"", s);
                free(s);
                break;

            case TSDB_DATA_TYPE_NULL:
                break;

            default:
                errorPrint2("%s() LN%d, Unknown data type %d\n",
                        __func__, __LINE__,
                        data_type[i]);
6340
                exit(EXIT_FAILURE);
6341
        }
6342

6343
        if (strlen(recBuf) > MAX_DATA_SIZE) {
6344
            ERROR_EXIT("column length too long, abort");
6345
        }
6346 6347
    }

6348
    pstr += sprintf(pstr, ")");
6349

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

6352
    return (int32_t)strlen(recBuf);
6353 6354
}

6355 6356 6357 6358 6359 6360
static int generateSampleFromRand(
        char *sampleDataBuf,
        uint64_t lenOfOneRow,
        int columnCount,
        StrColumn *columns
        )
6361 6362 6363 6364
{
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);

6365
    char *buff = malloc(lenOfOneRow);
6366
    if (NULL == buff) {
6367 6368
        errorPrint2("%s() LN%d, memory allocation %"PRIu64" bytes failed\n",
                __func__, __LINE__, lenOfOneRow);
6369 6370 6371
        exit(EXIT_FAILURE);
    }

6372
    for (int i=0; i < MAX_SAMPLES; i++) {
6373
        uint64_t pos = 0;
6374
        memset(buff, 0, lenOfOneRow);
6375

6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397
        for (int c = 0; c < columnCount; c++) {
            char *tmp = NULL;

            uint32_t dataLen;
            char data_type = (columns)?(columns[c].data_type):g_args.data_type[c];

            switch(data_type) {
                case TSDB_DATA_TYPE_BINARY:
                    dataLen = (columns)?columns[c].dataLen:g_args.binwidth;
                    rand_string(data, dataLen);
                    pos += sprintf(buff + pos, "%s,", data);
                    break;

                case TSDB_DATA_TYPE_NCHAR:
                    dataLen = (columns)?columns[c].dataLen:g_args.binwidth;
                    rand_string(data, dataLen);
                    pos += sprintf(buff + pos, "%s,", data);
                    break;

                case TSDB_DATA_TYPE_INT:
                    if ((g_args.demo_mode) && (c == 1)) {
                        tmp = demo_voltage_int_str();
6398
                    } else {
6399
                        tmp = rand_int_str();
6400
                    }
6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448
                    pos += sprintf(buff + pos, "%s,", tmp);
                    break;

                case TSDB_DATA_TYPE_BIGINT:
                    pos += sprintf(buff + pos, "%s,", rand_bigint_str());
                    break;

                case TSDB_DATA_TYPE_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);
                    break;

                case TSDB_DATA_TYPE_DOUBLE:
                    pos += sprintf(buff + pos, "%s,", rand_double_str());
                    break;

                case TSDB_DATA_TYPE_SMALLINT:
                    pos += sprintf(buff + pos, "%s,", rand_smallint_str());
                    break;

                case TSDB_DATA_TYPE_TINYINT:
                    pos += sprintf(buff + pos, "%s,", rand_tinyint_str());
                    break;

                case TSDB_DATA_TYPE_BOOL:
                    pos += sprintf(buff + pos, "%s,", rand_bool_str());
                    break;

                case TSDB_DATA_TYPE_TIMESTAMP:
                    pos += sprintf(buff + pos, "%s,", rand_bigint_str());
                    break;

                case TSDB_DATA_TYPE_NULL:
                    break;

                default:
                    errorPrint2("%s() LN%d, Unknown data type %s\n",
                            __func__, __LINE__,
                            (columns)?(columns[c].dataType):g_args.dataType[c]);
                    exit(EXIT_FAILURE);
6449 6450
            }
        }
6451

6452
        *(buff + pos - 1) = 0;
6453
        memcpy(sampleDataBuf + i * lenOfOneRow, buff, pos);
6454 6455 6456 6457 6458 6459
    }

    free(buff);
    return 0;
}

6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478
static int generateSampleFromRandForNtb()
{
    return generateSampleFromRand(
            g_sampleDataBuf,
            g_args.lenOfOneRow,
            g_args.columnCount,
            NULL);
}

static int generateSampleFromRandForStb(SSuperTable *stbInfo)
{
    return generateSampleFromRand(
            stbInfo->sampleDataBuf,
            stbInfo->lenOfOneRow,
            stbInfo->columnCount,
            stbInfo->columns);
}

static int prepareSampleForNtb() {
6479
    g_sampleDataBuf = calloc(g_args.lenOfOneRow * MAX_SAMPLES, 1);
6480 6481 6482
    if (NULL == g_sampleDataBuf) {
        errorPrint2("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
                __func__, __LINE__,
6483
                g_args.lenOfOneRow * MAX_SAMPLES,
6484 6485 6486 6487 6488 6489 6490 6491
                strerror(errno));
        return -1;
    }

    return generateSampleFromRandForNtb();
}

static int prepareSampleForStb(SSuperTable *stbInfo) {
6492

6493
    stbInfo->sampleDataBuf = calloc(
6494
            stbInfo->lenOfOneRow * MAX_SAMPLES, 1);
6495
    if (NULL == stbInfo->sampleDataBuf) {
6496
        errorPrint2("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
6497
                __func__, __LINE__,
6498
                stbInfo->lenOfOneRow * MAX_SAMPLES,
6499 6500 6501
                strerror(errno));
        return -1;
    }
6502

6503
    int ret;
6504 6505 6506 6507 6508
    if (0 == strncasecmp(stbInfo->dataSource, "sample", strlen("sample"))) {
        ret = generateSampleFromCsvForStb(stbInfo);
    } else {
        ret = generateSampleFromRandForStb(stbInfo);
    }
6509

6510
    if (0 != ret) {
6511
        errorPrint2("%s() LN%d, read sample from csv file failed.\n",
6512
                __func__, __LINE__);
6513
        tmfree(stbInfo->sampleDataBuf);
6514
        stbInfo->sampleDataBuf = NULL;
6515 6516
        return -1;
    }
6517

6518
    return 0;
6519 6520
}

6521
static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k)
6522
{
6523
    int32_t affectedRows;
6524
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
6525

6526
    uint16_t iface;
6527 6528
    if (stbInfo)
        iface = stbInfo->iface;
6529 6530 6531 6532 6533 6534
    else {
        if (g_args.iface == INTERFACE_BUT)
            iface = TAOSC_IFACE;
        else
            iface = g_args.iface;
    }
6535 6536 6537

    debugPrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__,
6538 6539
            (iface==TAOSC_IFACE)?
            "taosc":(iface==REST_IFACE)?"rest":"stmt");
6540 6541 6542

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

6546 6547 6548 6549 6550 6551
            affectedRows = queryDbExec(
                    pThreadInfo->taos,
                    pThreadInfo->buffer, INSERT_TYPE, false);
            break;

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

6555
            if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
6556
                        pThreadInfo->buffer, pThreadInfo)) {
6557 6558 6559 6560 6561 6562 6563 6564 6565
                affectedRows = -1;
                printf("========restful return fail, threadID[%d]\n",
                        pThreadInfo->threadID);
            } else {
                affectedRows = k;
            }
            break;

        case STMT_IFACE:
6566 6567
            debugPrint("%s() LN%d, stmt=%p",
                    __func__, __LINE__, pThreadInfo->stmt);
6568
            if (0 != taos_stmt_execute(pThreadInfo->stmt)) {
6569
                errorPrint2("%s() LN%d, failied to execute insert statement. reason: %s\n",
6570
                        __func__, __LINE__, taos_stmt_errstr(pThreadInfo->stmt));
6571 6572

                fprintf(stderr, "\n\033[31m === Please reduce batch number if WAL size exceeds limit. ===\033[0m\n\n");
6573
                exit(EXIT_FAILURE);
6574 6575 6576 6577 6578
            }
            affectedRows = k;
            break;

        default:
6579
            errorPrint2("%s() LN%d: unknown insert mode: %d\n",
6580
                    __func__, __LINE__, stbInfo->iface);
6581
            affectedRows = 0;
6582
    }
6583

6584
    return affectedRows;
6585 6586
}

6587 6588
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
6589
{
6590 6591 6592 6593
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
    if (stbInfo) {
        if (AUTO_CREATE_SUBTBL != stbInfo->autoCreateTable) {
            if (stbInfo->childTblLimit > 0) {
6594
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
6595 6596
                        stbInfo->childTblName +
                        (tableSeq - stbInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
6597 6598 6599 6600 6601 6602
            } 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",
6603
                        stbInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
6604 6605 6606
            }
        } else {
            snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
6607
                    stbInfo->childTblPrefix, tableSeq);
6608
        }
6609
    } else {
6610 6611
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                g_args.tb_prefix, tableSeq);
6612 6613 6614
    }
}

6615
static int32_t generateDataTailWithoutStb(
6616
        uint32_t batch, char* buffer,
6617
        int64_t remainderBufLen, int64_t insertRows,
6618
        uint64_t recordFrom, int64_t startTime,
6619
        /* int64_t *pSamplePos, */int64_t *dataLen) {
6620

6621 6622
    uint64_t len = 0;
    char *pstr = buffer;
6623

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

6626 6627
    int32_t k = 0;
    for (k = 0; k < batch;) {
6628
        char *data = pstr;
6629
        memset(data, 0, MAX_DATA_SIZE);
6630

6631
        int64_t retLen = 0;
6632

6633
        char *data_type = g_args.data_type;
6634
        int lenOfBinary = g_args.binwidth;
6635

6636 6637 6638
        if (g_args.disorderRatio) {
            retLen = generateData(data, data_type,
                    startTime + getTSRandTail(
6639
                        g_args.timestamp_step, k,
6640 6641 6642 6643 6644
                        g_args.disorderRatio,
                        g_args.disorderRange),
                    lenOfBinary);
        } else {
            retLen = generateData(data, data_type,
6645
                    startTime + g_args.timestamp_step * k,
6646 6647
                    lenOfBinary);
        }
6648

6649 6650
        if (len > remainderBufLen)
            break;
6651

6652
        pstr += retLen;
6653 6654 6655
        k++;
        len += retLen;
        remainderBufLen -= retLen;
6656

6657 6658
        verbosePrint("%s() LN%d len=%"PRIu64" k=%d \nbuffer=%s\n",
                __func__, __LINE__, len, k, buffer);
6659

6660
        recordFrom ++;
6661

6662 6663 6664
        if (recordFrom >= insertRows) {
            break;
        }
6665
    }
6666

6667 6668
    *dataLen = len;
    return k;
6669 6670
}

6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687
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(
6688
        SSuperTable* stbInfo,
6689
        uint32_t batch, char* buffer,
6690
        int64_t remainderBufLen, int64_t insertRows,
6691
        uint64_t recordFrom, int64_t startTime,
6692
        int64_t *pSamplePos, int64_t *dataLen) {
6693
    uint64_t len = 0;
6694

6695
    char *pstr = buffer;
6696

6697
    bool tsRand;
6698
    if (0 == strncasecmp(stbInfo->dataSource, "rand", strlen("rand"))) {
6699 6700 6701 6702 6703 6704
        tsRand = true;
    } else {
        tsRand = false;
    }
    verbosePrint("%s() LN%d batch=%u buflen=%"PRId64"\n",
            __func__, __LINE__, batch, remainderBufLen);
6705

6706 6707
    int32_t k;
    for (k = 0; k < batch;) {
6708
        char *data = pstr;
6709

6710
        int64_t lenOfRow = 0;
6711

6712
        if (tsRand) {
6713 6714
            if (stbInfo->disorderRatio > 0) {
                lenOfRow = generateStbRowData(stbInfo, data,
6715
                        remainderBufLen,
6716
                        startTime + getTSRandTail(
6717 6718 6719
                            stbInfo->timeStampStep, k,
                            stbInfo->disorderRatio,
                            stbInfo->disorderRange)
6720 6721
                        );
            } else {
6722
                lenOfRow = generateStbRowData(stbInfo, data,
6723
                        remainderBufLen,
6724
                        startTime + stbInfo->timeStampStep * k
6725 6726 6727 6728 6729 6730
                        );
            }
        } else {
            lenOfRow = getRowDataFromSample(
                    data,
                    (remainderBufLen < MAX_DATA_SIZE)?remainderBufLen:MAX_DATA_SIZE,
6731 6732
                    startTime + stbInfo->timeStampStep * k,
                    stbInfo,
6733 6734
                    pSamplePos);
        }
6735

6736 6737 6738 6739
        if (lenOfRow == 0) {
            data[0] = '\0';
            break;
        }
6740 6741 6742
        if ((lenOfRow + 1) > remainderBufLen) {
            break;
        }
6743

6744
        pstr += lenOfRow;
6745 6746 6747
        k++;
        len += lenOfRow;
        remainderBufLen -= lenOfRow;
6748

6749 6750
        verbosePrint("%s() LN%d len=%"PRIu64" k=%u \nbuffer=%s\n",
                __func__, __LINE__, len, k, buffer);
6751

6752
        recordFrom ++;
6753

6754 6755 6756
        if (recordFrom >= insertRows) {
            break;
        }
6757
    }
6758

6759 6760
    *dataLen = len;
    return k;
6761
}
6762

6763 6764 6765

static int generateSQLHeadWithoutStb(char *tableName,
        char *dbName,
6766
        char *buffer, int remainderBufLen)
6767
{
6768
    int len;
6769

6770
    char headBuf[HEAD_BUFF_LEN];
6771

6772 6773 6774 6775 6776 6777
    len = snprintf(
            headBuf,
            HEAD_BUFF_LEN,
            "%s.%s values",
            dbName,
            tableName);
6778

6779 6780
    if (len > remainderBufLen)
        return -1;
6781

6782
    tstrncpy(buffer, headBuf, len + 1);
6783

6784
    return len;
6785 6786 6787
}

static int generateStbSQLHead(
6788
        SSuperTable* stbInfo,
6789
        char *tableName, int64_t tableSeq,
6790 6791 6792
        char *dbName,
        char *buffer, int remainderBufLen)
{
6793
    int len;
6794

6795
    char headBuf[HEAD_BUFF_LEN];
6796

6797
    if (AUTO_CREATE_SUBTBL == stbInfo->autoCreateTable) {
6798
        char* tagsValBuf = NULL;
6799 6800
        if (0 == stbInfo->tagSource) {
            tagsValBuf = generateTagValuesForStb(stbInfo, tableSeq);
6801
        } else {
6802
            tagsValBuf = getTagValueFromTagSample(
6803 6804
                    stbInfo,
                    tableSeq % stbInfo->tagSampleCount);
6805 6806
        }
        if (NULL == tagsValBuf) {
6807
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
6808 6809 6810
                    __func__, __LINE__);
            return -1;
        }
6811

6812 6813 6814 6815 6816 6817 6818
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s using %s.%s TAGS%s values",
                dbName,
                tableName,
                dbName,
6819
                stbInfo->stbName,
6820 6821
                tagsValBuf);
        tmfree(tagsValBuf);
6822
    } else if (TBL_ALREADY_EXISTS == stbInfo->childTblExists) {
6823 6824 6825 6826 6827 6828
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s values",
                dbName,
                tableName);
6829
    } else {
6830 6831 6832 6833 6834 6835 6836
        len = snprintf(
                headBuf,
                HEAD_BUFF_LEN,
                "%s.%s values",
                dbName,
                tableName);
    }
6837

6838 6839
    if (len > remainderBufLen)
        return -1;
6840

6841
    tstrncpy(buffer, headBuf, len + 1);
6842

6843
    return len;
6844 6845
}

6846
static int32_t generateStbInterlaceData(
6847
        threadInfo *pThreadInfo,
6848 6849 6850
        char *tableName, uint32_t batchPerTbl,
        uint64_t i,
        uint32_t batchPerTblTimes,
6851
        uint64_t tableSeq,
6852
        char *buffer,
6853
        int64_t insertRows,
6854
        int64_t startTime,
6855
        uint64_t *pRemainderBufLen)
6856
{
6857 6858
    assert(buffer);
    char *pstr = buffer;
6859

6860
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
6861
    int headLen = generateStbSQLHead(
6862
            stbInfo,
6863 6864
            tableName, tableSeq, pThreadInfo->db_name,
            pstr, *pRemainderBufLen);
6865

6866 6867 6868 6869 6870
    if (headLen <= 0) {
        return 0;
    }
    // generate data buffer
    verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
6871
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
6872

6873 6874
    pstr += headLen;
    *pRemainderBufLen -= headLen;
6875

6876
    int64_t dataLen = 0;
6877

6878
    verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%u batchPerTbl = %u\n",
6879 6880
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
6881

6882
    if (0 == strncasecmp(stbInfo->startTimestamp, "now", 3)) {
6883 6884
        startTime = taosGetTimestamp(pThreadInfo->time_precision);
    }
6885

6886
    int32_t k = generateStbDataTail(
6887
            stbInfo,
6888 6889 6890
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &(pThreadInfo->samplePos), &dataLen);
6891

6892 6893 6894 6895 6896 6897 6898 6899 6900 6901
    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;
    }
6902

6903
    return k;
6904 6905 6906
}

static int64_t generateInterlaceDataWithoutStb(
6907
        char *tableName, uint32_t batch,
6908 6909 6910
        uint64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
6911
        int64_t startTime,
6912 6913
        uint64_t *pRemainderBufLen)
{
6914 6915
    assert(buffer);
    char *pstr = buffer;
6916

6917 6918
    int headLen = generateSQLHeadWithoutStb(
            tableName, dbName,
6919 6920
            pstr, *pRemainderBufLen);

6921 6922 6923
    if (headLen <= 0) {
        return 0;
    }
6924

6925 6926
    pstr += headLen;
    *pRemainderBufLen -= headLen;
6927

6928
    int64_t dataLen = 0;
6929

6930
    int32_t k = generateDataTailWithoutStb(
6931
            batch, pstr, *pRemainderBufLen, insertRows, 0,
6932
            startTime,
6933
            &dataLen);
6934

6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946
    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;
6947 6948
}

6949 6950
static int32_t prepareStmtBindArrayByType(
        TAOS_BIND *bind,
6951
        char data_type, int32_t dataLen,
6952 6953 6954
        int32_t timePrec,
        char *value)
{
6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971
    int32_t *bind_int;
    int64_t *bind_bigint;
    float   *bind_float;
    double  *bind_double;
    int8_t  *bind_bool;
    int64_t *bind_ts2;
    int16_t *bind_smallint;
    int8_t  *bind_tinyint;

    switch(data_type) {
        case TSDB_DATA_TYPE_BINARY:
            if (dataLen > TSDB_MAX_BINARY_LEN) {
                errorPrint2("binary length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
            char *bind_binary;
6972

6973 6974 6975 6976 6977 6978 6979 6980 6981 6982
            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;
            }
6983

6984 6985 6986 6987
            bind->length = &bind->buffer_length;
            bind->buffer = bind_binary;
            bind->is_null = NULL;
            break;
6988

6989 6990 6991 6992 6993 6994 6995
        case TSDB_DATA_TYPE_NCHAR:
            if (dataLen > TSDB_MAX_BINARY_LEN) {
                errorPrint2("nchar length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
            char *bind_nchar;
6996

6997 6998 6999 7000 7001 7002 7003 7004
            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);
            }
7005

7006 7007 7008 7009 7010
            bind->buffer_length = strlen(bind_nchar);
            bind->buffer = bind_nchar;
            bind->length = &bind->buffer_length;
            bind->is_null = NULL;
            break;
7011

7012 7013 7014
        case TSDB_DATA_TYPE_INT:
            bind_int = malloc(sizeof(int32_t));
            assert(bind_int);
7015

7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026
            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;
            break;
7027

7028 7029 7030
        case TSDB_DATA_TYPE_BIGINT:
            bind_bigint = malloc(sizeof(int64_t));
            assert(bind_bigint);
7031

7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042
            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;
            break;
7043

7044 7045 7046 7047 7048 7049
        case TSDB_DATA_TYPE_FLOAT:
            bind_float = malloc(sizeof(float));
            assert(bind_float);

            if (value) {
                *bind_float = (float)atof(value);
7050
            } else {
7051
                *bind_float = rand_float();
7052
            }
7053 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 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126
            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;
            break;

        case TSDB_DATA_TYPE_DOUBLE:
            bind_double = malloc(sizeof(double));
            assert(bind_double);

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

        case TSDB_DATA_TYPE_SMALLINT:
            bind_smallint = malloc(sizeof(int16_t));
            assert(bind_smallint);

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

        case TSDB_DATA_TYPE_TINYINT:
            bind_tinyint = malloc(sizeof(int8_t));
            assert(bind_tinyint);

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

        case TSDB_DATA_TYPE_BOOL:
            bind_bool = malloc(sizeof(int8_t));
            assert(bind_bool);

            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;
            break;
7127

7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139
        case TSDB_DATA_TYPE_TIMESTAMP:
            bind_ts2 = malloc(sizeof(int64_t));
            assert(bind_ts2);

            if (value) {
                if (strchr(value, ':') && strchr(value, '-')) {
                    int i = 0;
                    while(value[i] != '\0') {
                        if (value[i] == '\"' || value[i] == '\'') {
                            value[i] = ' ';
                        }
                        i++;
7140
                    }
7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151
                    int64_t tmpEpoch;
                    if (TSDB_CODE_SUCCESS != taosParseTime(
                                value, &tmpEpoch, strlen(value),
                                timePrec, 0)) {
                        free(bind_ts2);
                        errorPrint2("Input %s, time format error!\n", value);
                        return -1;
                    }
                    *bind_ts2 = tmpEpoch;
                } else {
                    *bind_ts2 = atoll(value);
7152 7153
                }
            } else {
7154
                *bind_ts2 = rand_bigint();
7155
            }
7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168
            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;
            break;

        case TSDB_DATA_TYPE_NULL:
            break;

        default:
            errorPrint2("Not support data type: %d\n", data_type);
            exit(EXIT_FAILURE);
7169 7170 7171 7172 7173 7174 7175
    }

    return 0;
}

static int32_t prepareStmtBindArrayByTypeForRand(
        TAOS_BIND *bind,
7176
        char data_type, int32_t dataLen,
7177 7178 7179
        int32_t timePrec,
        char **ptr,
        char *value)
7180
{
7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191
    int32_t *bind_int;
    int64_t *bind_bigint;
    float   *bind_float;
    double  *bind_double;
    int16_t *bind_smallint;
    int8_t  *bind_tinyint;
    int8_t  *bind_bool;
    int64_t *bind_ts2;

    switch(data_type) {
        case TSDB_DATA_TYPE_BINARY:
7192

7193 7194 7195 7196 7197 7198
            if (dataLen > TSDB_MAX_BINARY_LEN) {
                errorPrint2("binary length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
            char *bind_binary = (char *)*ptr;
7199

7200 7201 7202 7203 7204 7205 7206 7207
            bind->buffer_type = TSDB_DATA_TYPE_BINARY;
            if (value) {
                strncpy(bind_binary, value, strlen(value));
                bind->buffer_length = strlen(bind_binary);
            } else {
                rand_string(bind_binary, dataLen);
                bind->buffer_length = dataLen;
            }
7208

7209 7210 7211
            bind->length = &bind->buffer_length;
            bind->buffer = bind_binary;
            bind->is_null = NULL;
7212

7213 7214
            *ptr += bind->buffer_length;
            break;
7215

7216 7217 7218 7219 7220 7221 7222
        case TSDB_DATA_TYPE_NCHAR:
            if (dataLen > TSDB_MAX_BINARY_LEN) {
                errorPrint2("nchar length overflow, max size: %u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
            char *bind_nchar = (char *)*ptr;
7223

7224 7225 7226 7227 7228 7229
            bind->buffer_type = TSDB_DATA_TYPE_NCHAR;
            if (value) {
                strncpy(bind_nchar, value, strlen(value));
            } else {
                rand_string(bind_nchar, dataLen);
            }
7230

7231 7232 7233 7234
            bind->buffer_length = strlen(bind_nchar);
            bind->buffer = bind_nchar;
            bind->length = &bind->buffer_length;
            bind->is_null = NULL;
7235

7236 7237
            *ptr += bind->buffer_length;
            break;
7238

7239 7240
        case TSDB_DATA_TYPE_INT:
            bind_int = (int32_t *)*ptr;
7241

7242 7243 7244 7245 7246 7247 7248 7249 7250 7251
            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;
7252

7253 7254
            *ptr += bind->buffer_length;
            break;
7255

7256 7257
        case TSDB_DATA_TYPE_BIGINT:
            bind_bigint = (int64_t *)*ptr;
7258

7259 7260 7261 7262 7263 7264 7265 7266 7267 7268
            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;
7269

7270 7271
            *ptr += bind->buffer_length;
            break;
7272

7273 7274
        case TSDB_DATA_TYPE_FLOAT:
            bind_float = (float *)*ptr;
7275

7276 7277 7278 7279 7280 7281 7282 7283 7284 7285
            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;
7286

7287 7288
            *ptr += bind->buffer_length;
            break;
7289

7290 7291
        case TSDB_DATA_TYPE_DOUBLE:
            bind_double = (double *)*ptr;
7292

7293 7294
            if (value) {
                *bind_double = atof(value);
7295
            } else {
7296
                *bind_double = rand_double();
7297
            }
7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348
            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;
            break;

        case TSDB_DATA_TYPE_SMALLINT:
            bind_smallint = (int16_t *)*ptr;

            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;

            *ptr += bind->buffer_length;
            break;

        case TSDB_DATA_TYPE_TINYINT:
            bind_tinyint = (int8_t *)*ptr;

            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;

            *ptr += bind->buffer_length;
            break;

        case TSDB_DATA_TYPE_BOOL:
            bind_bool = (int8_t *)*ptr;

            if (value) {
                if (strncasecmp(value, "true", 4)) {
                    *bind_bool = true;
                } else {
                    *bind_bool = false;
7349
                }
7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383
            } 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;

            *ptr += bind->buffer_length;
            break;

        case TSDB_DATA_TYPE_TIMESTAMP:
            bind_ts2 = (int64_t *)*ptr;

            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)) {
                        errorPrint2("Input %s, time format error!\n", value);
                        return -1;
                    }
                    *bind_ts2 = tmpEpoch;
                } else {
                    *bind_ts2 = atoll(value);
7384 7385
                }
            } else {
7386
                *bind_ts2 = rand_bigint();
7387
            }
7388 7389 7390 7391 7392
            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;
7393

7394 7395 7396 7397 7398 7399
            *ptr += bind->buffer_length;
            break;

        default:
            errorPrint2("No support data type: %d\n", data_type);
            return -1;
7400 7401 7402 7403 7404 7405
    }

    return 0;
}

static int32_t prepareStmtWithoutStb(
7406
        threadInfo *pThreadInfo,
7407 7408 7409 7410 7411
        char *tableName,
        uint32_t batch,
        int64_t insertRows,
        int64_t recordFrom,
        int64_t startTime)
7412
{
7413
    TAOS_STMT *stmt = pThreadInfo->stmt;
7414 7415
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
7416
        errorPrint2("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
7417
                tableName, ret, taos_stmt_errstr(stmt));
7418 7419 7420
        return ret;
    }

7421
    char *data_type = g_args.data_type;
7422

7423
    char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.columnCount + 1));
7424
    if (bindArray == NULL) {
7425
        errorPrint2("Failed to allocate %d bind params\n",
7426
                (g_args.columnCount + 1));
7427
        return -1;
7428 7429
    }

7430 7431 7432 7433 7434 7435
    int32_t k = 0;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */

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

7436
        int64_t *bind_ts = pThreadInfo->bind_ts;
7437 7438

        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
7439 7440 7441

        if (g_args.disorderRatio) {
            *bind_ts = startTime + getTSRandTail(
7442
                    g_args.timestamp_step, k,
7443 7444 7445
                    g_args.disorderRatio,
                    g_args.disorderRange);
        } else {
7446
            *bind_ts = startTime + g_args.timestamp_step * k;
7447
        }
7448 7449 7450 7451 7452
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

7453
        for (int i = 0; i < g_args.columnCount; i ++) {
7454 7455
            bind = (TAOS_BIND *)((char *)bindArray
                    + (sizeof(TAOS_BIND) * (i + 1)));
7456 7457 7458
            if ( -1 == prepareStmtBindArrayByType(
                        bind,
                        data_type[i],
7459
                        g_args.binwidth,
7460 7461
                        pThreadInfo->time_precision,
                        NULL)) {
7462
                free(bindArray);
7463 7464 7465
                return -1;
            }
        }
7466
        if (0 != taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray)) {
7467
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
7468 7469 7470
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            break;
        }
7471
        // if msg > 3MB, break
7472
        if (0 != taos_stmt_add_batch(stmt)) {
7473
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
7474 7475 7476
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            break;
        }
7477 7478 7479 7480 7481 7482 7483 7484

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

7485
    free(bindArray);
7486 7487 7488
    return k;
}

7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499
static int32_t prepareStbStmtBindTag(
        char *bindArray, SSuperTable *stbInfo,
        char *tagsVal,
        int32_t timePrec)
{
    TAOS_BIND *tag;

    for (int t = 0; t < stbInfo->tagCount; t ++) {
        tag = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * t));
        if ( -1 == prepareStmtBindArrayByType(
                    tag,
7500
                    stbInfo->tags[t].data_type,
7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513
                    stbInfo->tags[t].dataLen,
                    timePrec,
                    NULL)) {
            return -1;
        }
    }

    return 0;
}

static int32_t prepareStbStmtBindRand(
        int64_t *ts,
        char *bindArray, SSuperTable *stbInfo,
7514
        int64_t startTime, int32_t recSeq,
7515
        int32_t timePrec)
7516 7517 7518 7519 7520 7521 7522
{
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);
    char *ptr = data;

    TAOS_BIND *bind;

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

7526 7527
        if (i == 0) {
            int64_t *bind_ts = ts;
7528

7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545
            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,
7546
                    stbInfo->columns[i-1].data_type,
7547 7548 7549 7550 7551 7552 7553
                    stbInfo->columns[i-1].dataLen,
                    timePrec,
                    &ptr,
                    NULL)) {
            return -1;
        }
    }
7554

7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686
    return 0;
}

UNUSED_FUNC static int32_t prepareStbStmtRand(
        threadInfo *pThreadInfo,
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
        uint64_t insertRows,
        uint64_t recordFrom,
        int64_t startTime)
{
    int ret;
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    TAOS_STMT *stmt = pThreadInfo->stmt;

    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) {
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
                    __func__, __LINE__);
            return -1;
        }

        char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount);
        if (NULL == tagsArray) {
            tmfree(tagsValBuf);
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
                    __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) {
            errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n",
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    } else {
        ret = taos_stmt_set_tbname(stmt, tableName);
        if (0 != ret) {
            errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n",
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    }

    char *bindArray = calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1));
    if (bindArray == NULL) {
        errorPrint2("%s() LN%d, Failed to allocate %d bind params\n",
                __func__, __LINE__, (stbInfo->columnCount + 1));
        return -1;
    }

    uint32_t k;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */
        if (-1 == prepareStbStmtBindRand(
                    pThreadInfo->bind_ts,
                    bindArray, stbInfo,
                    startTime, k,
                    pThreadInfo->time_precision
                    /* is column */)) {
            free(bindArray);
            return -1;
        }
        ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        if (0 != ret) {
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            free(bindArray);
            return -1;
        }
        // if msg > 3MB, break
        ret = taos_stmt_add_batch(stmt);
        if (0 != ret) {
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            free(bindArray);
            return -1;
        }

        k++;
        recordFrom ++;

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

    free(bindArray);
    return k;
}

#if STMT_BIND_PARAM_BATCH == 1
static int execBindParamBatch(
        threadInfo *pThreadInfo,
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
        uint64_t insertRows,
        uint64_t recordFrom,
        int64_t startTime,
        int64_t *pSamplePos)
{
    int ret;
    TAOS_STMT *stmt = pThreadInfo->stmt;

    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    uint32_t columnCount = (stbInfo)?pThreadInfo->stbInfo->columnCount:g_args.columnCount;

7687
    uint32_t thisBatch = MAX_SAMPLES - (*pSamplePos);
7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856

    if (thisBatch > batch) {
        thisBatch = batch;
    }
    verbosePrint("%s() LN%d, batch=%d pos=%"PRId64" thisBatch=%d\n",
            __func__, __LINE__, batch, *pSamplePos, thisBatch);

    memset(pThreadInfo->bindParams, 0,
            (sizeof(TAOS_MULTI_BIND) * (columnCount + 1)));
    memset(pThreadInfo->is_null, 0, thisBatch);

    for (int c = 0; c < columnCount + 1; c ++) {
        TAOS_MULTI_BIND *param = (TAOS_MULTI_BIND *)(pThreadInfo->bindParams + sizeof(TAOS_MULTI_BIND) * c);

        char data_type;

        if (c == 0) {
            data_type = TSDB_DATA_TYPE_TIMESTAMP;
            param->buffer_length = sizeof(int64_t);
            param->buffer = pThreadInfo->bind_ts_array;

        } else {
            data_type = (stbInfo)?stbInfo->columns[c-1].data_type:g_args.data_type[c-1];

            char *tmpP;

            switch(data_type) {
                case TSDB_DATA_TYPE_BINARY:
                case TSDB_DATA_TYPE_NCHAR:
                    param->buffer_length =
                        ((stbInfo)?stbInfo->columns[c-1].dataLen:g_args.binwidth);

                    tmpP =
                        (char *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray
                                    +sizeof(char*)*(c-1)));

                    verbosePrint("%s() LN%d, tmpP=%p pos=%"PRId64" width=%d position=%"PRId64"\n",
                            __func__, __LINE__, tmpP, *pSamplePos,
                            (((stbInfo)?stbInfo->columns[c-1].dataLen:g_args.binwidth)),
                            (*pSamplePos) *
                            (((stbInfo)?stbInfo->columns[c-1].dataLen:g_args.binwidth)));

                    param->buffer = (void *)(tmpP + *pSamplePos *
                            (((stbInfo)?stbInfo->columns[c-1].dataLen:g_args.binwidth))
                            );
                    break;

                case TSDB_DATA_TYPE_INT:
                    param->buffer_length = sizeof(int32_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int32_t)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_TINYINT:
                    param->buffer_length = sizeof(int8_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(
                                    stbInfo->sampleBindBatchArray
                                    +sizeof(char*)*(c-1))
                                + stbInfo->columns[c-1].dataLen*(*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(
                                    g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int8_t)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_SMALLINT:
                    param->buffer_length = sizeof(int16_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int16_t)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_BIGINT:
                    param->buffer_length = sizeof(int64_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int64_t)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_BOOL:
                    param->buffer_length = sizeof(int8_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int8_t)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_FLOAT:
                    param->buffer_length = sizeof(float);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(float)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_DOUBLE:
                    param->buffer_length = sizeof(double);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(double)*(*pSamplePos));
                    break;

                case TSDB_DATA_TYPE_TIMESTAMP:
                    param->buffer_length = sizeof(int64_t);
                    param->buffer = (stbInfo)?
                        (void *)((uintptr_t)*(uintptr_t*)(stbInfo->sampleBindBatchArray+sizeof(char*)*(c-1))
                                        + stbInfo->columns[c-1].dataLen * (*pSamplePos)):
                        (void *)((uintptr_t)*(uintptr_t*)(g_sampleBindBatchArray+sizeof(char*)*(c-1))
                                    + sizeof(int64_t)*(*pSamplePos));
                    break;

                default:
                    errorPrint("%s() LN%d, wrong data type: %d\n",
                            __func__,
                            __LINE__,
                            data_type);
                    exit(EXIT_FAILURE);

            }
        }

        param->buffer_type = data_type;
        param->length = malloc(sizeof(int32_t) * thisBatch);
        assert(param->length);

        for (int b = 0; b < thisBatch; b++) {
            if (param->buffer_type == TSDB_DATA_TYPE_NCHAR) {
                param->length[b] = strlen(
                     (char *)param->buffer + b *
                         ((stbInfo)?stbInfo->columns[c].dataLen:g_args.binwidth)
                        );
            } else {
                param->length[b] = param->buffer_length;
            }
        }
        param->is_null = pThreadInfo->is_null;
        param->num = thisBatch;
    }

    uint32_t k;
    for (k = 0; k < thisBatch;) {
        /* columnCount + 1 (ts) */
        if (stbInfo->disorderRatio) {
            *(pThreadInfo->bind_ts_array + k) = startTime + getTSRandTail(
                    stbInfo->timeStampStep, k,
                    stbInfo->disorderRatio,
                    stbInfo->disorderRange);
        } else {
            *(pThreadInfo->bind_ts_array + k) = startTime + stbInfo->timeStampStep * k;
        }

        debugPrint("%s() LN%d, k=%d ts=%"PRId64"\n",
                __func__, __LINE__,
                k, *(pThreadInfo->bind_ts_array +k));
        k++;
        recordFrom ++;

        (*pSamplePos) ++;
7857
        if ((*pSamplePos) == MAX_SAMPLES) {
7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911
            *pSamplePos = 0;
        }

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

    ret = taos_stmt_bind_param_batch(stmt, (TAOS_MULTI_BIND *)pThreadInfo->bindParams);
    if (0 != ret) {
        errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
                __func__, __LINE__, taos_stmt_errstr(stmt));
        return -1;
    }

    for (int c = 0; c < stbInfo->columnCount + 1; c ++) {
        TAOS_MULTI_BIND *param = (TAOS_MULTI_BIND *)(pThreadInfo->bindParams + sizeof(TAOS_MULTI_BIND) * c);
        free(param->length);
    }

    // if msg > 3MB, break
    ret = taos_stmt_add_batch(stmt);
    if (0 != ret) {
        errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
                __func__, __LINE__, taos_stmt_errstr(stmt));
        return -1;
    }
    return k;
}

static int parseSamplefileToStmtBatch(
        SSuperTable* stbInfo)
{
    // char *sampleDataBuf = (stbInfo)?
    //    stbInfo->sampleDataBuf:g_sampleDataBuf;
    int32_t columnCount = (stbInfo)?stbInfo->columnCount:g_args.columnCount;
    char *sampleBindBatchArray = NULL;

    if (stbInfo) {
        stbInfo->sampleBindBatchArray = calloc(1, sizeof(uintptr_t *) * columnCount);
        sampleBindBatchArray = stbInfo->sampleBindBatchArray;
    } else {
        g_sampleBindBatchArray = calloc(1, sizeof(uintptr_t *) * columnCount);
        sampleBindBatchArray = g_sampleBindBatchArray;
    }
    assert(sampleBindBatchArray);

    for (int c = 0; c < columnCount; c++) {
        char data_type = (stbInfo)?stbInfo->columns[c].data_type:g_args.data_type[c];

        char *tmpP = NULL;

        switch(data_type) {
            case TSDB_DATA_TYPE_INT:
7912
                tmpP = calloc(1, sizeof(int) * MAX_SAMPLES);
7913 7914 7915 7916 7917
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_TINYINT:
7918
                tmpP = calloc(1, sizeof(int8_t) * MAX_SAMPLES);
7919 7920 7921 7922 7923
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_SMALLINT:
7924
                tmpP = calloc(1, sizeof(int16_t) * MAX_SAMPLES);
7925 7926 7927 7928 7929
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_BIGINT:
7930
                tmpP = calloc(1, sizeof(int64_t) * MAX_SAMPLES);
7931 7932 7933 7934 7935
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_BOOL:
7936
                tmpP = calloc(1, sizeof(int8_t) * MAX_SAMPLES);
7937 7938 7939 7940 7941
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_FLOAT:
7942
                tmpP = calloc(1, sizeof(float) * MAX_SAMPLES);
7943 7944 7945 7946 7947
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_DOUBLE:
7948
                tmpP = calloc(1, sizeof(double) * MAX_SAMPLES);
7949 7950 7951 7952 7953 7954
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_BINARY:
            case TSDB_DATA_TYPE_NCHAR:
7955
                tmpP = calloc(1, MAX_SAMPLES *
7956 7957 7958 7959 7960 7961
                        (((stbInfo)?stbInfo->columns[c].dataLen:g_args.binwidth)));
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            case TSDB_DATA_TYPE_TIMESTAMP:
7962
                tmpP = calloc(1, sizeof(int64_t) * MAX_SAMPLES);
7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976
                assert(tmpP);
                *(uintptr_t*)(sampleBindBatchArray+ sizeof(uintptr_t*)*c) = (uintptr_t)tmpP;
                break;

            default:
                errorPrint("Unknown data type: %s\n",
                        (stbInfo)?stbInfo->columns[c].dataType:g_args.dataType[c]);
                exit(EXIT_FAILURE);
        }
    }

    char *sampleDataBuf = (stbInfo)?stbInfo->sampleDataBuf:g_sampleDataBuf;
    int64_t lenOfOneRow = (stbInfo)?stbInfo->lenOfOneRow:g_args.lenOfOneRow;

7977
    for (int i=0; i < MAX_SAMPLES; i++) {
7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 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 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116
        int cursor = 0;

        for (int c = 0; c < columnCount; c++) {
            char data_type = (stbInfo)?
                stbInfo->columns[c].data_type:
                g_args.data_type[c];
            char *restStr = sampleDataBuf
                + lenOfOneRow * i + cursor;
            int lengthOfRest = strlen(restStr);

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

            char *tmpStr = calloc(1, index + 1);
            if (NULL == tmpStr) {
                errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n",
                        __func__, __LINE__, index + 1);
                return -1;
            }

            strncpy(tmpStr, restStr, index);
            cursor += index + 1; // skip ',' too
            char *tmpP;

            switch(data_type) {
                case TSDB_DATA_TYPE_INT:
                    *((int32_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int32_t)*i)) =
                        atoi(tmpStr);
                    break;

                case TSDB_DATA_TYPE_FLOAT:
                    *(float*)(((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(float)*i)) =
                        (float)atof(tmpStr);
                    break;

                case TSDB_DATA_TYPE_DOUBLE:
                    *(double*)(((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(double)*i)) =
                        atof(tmpStr);
                    break;

                case TSDB_DATA_TYPE_TINYINT:
                    *((int8_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int8_t)*i)) =
                        (int8_t)atoi(tmpStr);
                    break;

                case TSDB_DATA_TYPE_SMALLINT:
                    *((int16_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int16_t)*i)) =
                        (int16_t)atoi(tmpStr);
                    break;

                case TSDB_DATA_TYPE_BIGINT:
                    *((int64_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int64_t)*i)) =
                        (int64_t)atol(tmpStr);
                    break;

                case TSDB_DATA_TYPE_BOOL:
                    *((int8_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int8_t)*i)) =
                        (int8_t)atoi(tmpStr);
                    break;

                case TSDB_DATA_TYPE_TIMESTAMP:
                    *((int64_t*)((uintptr_t)*(uintptr_t*)(sampleBindBatchArray
                                    +sizeof(char*)*c)+sizeof(int64_t)*i)) =
                        (int64_t)atol(tmpStr);
                    break;

                case TSDB_DATA_TYPE_BINARY:
                case TSDB_DATA_TYPE_NCHAR:
                    tmpP = (char *)(*(uintptr_t*)(sampleBindBatchArray
                            +sizeof(char*)*c));
                    strcpy(tmpP + i*
                        (((stbInfo)?stbInfo->columns[c].dataLen:g_args.binwidth))
                    , tmpStr);
                    break;

                default:
                    break;
            }

            free(tmpStr);
        }
    }

    return 0;
}

static int parseSampleToStmtBatchForThread(
        threadInfo *pThreadInfo, SSuperTable *stbInfo,
        uint32_t timePrec,
        uint32_t batch)
{
    uint32_t columnCount = (stbInfo)?stbInfo->columnCount:g_args.columnCount;

    pThreadInfo->bind_ts_array = malloc(sizeof(int64_t) * batch);
    assert(pThreadInfo->bind_ts_array);

    pThreadInfo->bindParams = malloc(sizeof(TAOS_MULTI_BIND) * (columnCount + 1));
    assert(pThreadInfo->bindParams);

    pThreadInfo->is_null = malloc(batch);
    assert(pThreadInfo->is_null);

    return 0;
}

static int parseStbSampleToStmtBatchForThread(
        threadInfo *pThreadInfo,
        SSuperTable *stbInfo,
        uint32_t timePrec,
        uint32_t batch)
{
    return parseSampleToStmtBatchForThread(
        pThreadInfo, stbInfo, timePrec, batch);
}

static int parseNtbSampleToStmtBatchForThread(
        threadInfo *pThreadInfo, uint32_t timePrec, uint32_t batch)
{
    return parseSampleToStmtBatchForThread(
        pThreadInfo, NULL, timePrec, batch);
}

#else
static int parseSampleToStmt(
        threadInfo *pThreadInfo,
        SSuperTable *stbInfo, uint32_t timePrec)
{
    pThreadInfo->sampleBindArray =
8117
        (char *)calloc(1, sizeof(char *) * MAX_SAMPLES);
8118 8119 8120
    if (pThreadInfo->sampleBindArray == NULL) {
        errorPrint2("%s() LN%d, Failed to allocate %"PRIu64" bind array buffer\n",
                __func__, __LINE__,
8121
                (uint64_t)sizeof(char *) * MAX_SAMPLES);
8122 8123 8124 8125 8126 8127 8128
        return -1;
    }

    int32_t columnCount = (stbInfo)?stbInfo->columnCount:g_args.columnCount;
    char *sampleDataBuf = (stbInfo)?stbInfo->sampleDataBuf:g_sampleDataBuf;
    int64_t lenOfOneRow = (stbInfo)?stbInfo->lenOfOneRow:g_args.lenOfOneRow;

8129
    for (int i=0; i < MAX_SAMPLES; i++) {
8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184
        char *bindArray =
            calloc(1, sizeof(TAOS_BIND) * (columnCount + 1));
        if (bindArray == NULL) {
            errorPrint2("%s() LN%d, Failed to allocate %d bind params\n",
                    __func__, __LINE__, (columnCount + 1));
            return -1;
        }

        TAOS_BIND *bind;
        int cursor = 0;

        for (int c = 0; c < 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 data_type = (stbInfo)?
                    stbInfo->columns[c-1].data_type:
                    g_args.data_type[c-1];
                int32_t dataLen = (stbInfo)?
                    stbInfo->columns[c-1].dataLen:
                    g_args.binwidth;
                char *restStr = sampleDataBuf
                    + 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) {
                    errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n",
                            __func__, __LINE__, index + 1);
                    return -1;
                }

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

                if (-1 == prepareStmtBindArrayByType(
                            bind,
                            data_type,
                            dataLen,
                            timePrec,
                            bindBuffer)) {
                    free(bindBuffer);
8185
                    free(bindArray);
8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214
                    return -1;
                }
                free(bindBuffer);
            }
        }
        *((uintptr_t *)(pThreadInfo->sampleBindArray + (sizeof(char *)) * i)) =
            (uintptr_t)bindArray;
    }

    return 0;
}

static int parseStbSampleToStmt(
        threadInfo *pThreadInfo,
        SSuperTable *stbInfo, uint32_t timePrec)
{
    return parseSampleToStmt(
        pThreadInfo,
        stbInfo, timePrec);
}

static int parseNtbSampleToStmt(
        threadInfo *pThreadInfo,
        uint32_t timePrec)
{
    return parseSampleToStmt(
        pThreadInfo,
        NULL,
        timePrec);
8215
}
8216

8217 8218
static int32_t prepareStbStmtBindStartTime(
        char *tableName,
8219 8220
        int64_t *ts,
        char *bindArray, SSuperTable *stbInfo,
8221
        int64_t startTime, int32_t recSeq)
8222 8223
{
    TAOS_BIND *bind;
8224

8225
    bind = (TAOS_BIND *)bindArray;
8226

8227
    int64_t *bind_ts = ts;
8228

8229 8230 8231 8232 8233 8234 8235 8236
    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;
8237
    }
8238 8239 8240 8241

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

8242 8243 8244 8245
    bind->buffer_length = sizeof(int64_t);
    bind->buffer = bind_ts;
    bind->length = &bind->buffer_length;
    bind->is_null = NULL;
8246 8247 8248 8249

    return 0;
}

8250
static uint32_t execBindParam(
8251
        threadInfo *pThreadInfo,
8252 8253 8254
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
8255 8256
        uint64_t insertRows,
        uint64_t recordFrom,
8257 8258
        int64_t startTime,
        int64_t *pSamplePos)
8259
{
8260
    int ret;
8261 8262
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    TAOS_STMT *stmt = pThreadInfo->stmt;
8263

8264 8265
    uint32_t k;
    for (k = 0; k < batch;) {
8266 8267
        char *bindArray = (char *)(*((uintptr_t *)
                    (pThreadInfo->sampleBindArray + (sizeof(char *)) * (*pSamplePos))));
8268
        /* columnCount + 1 (ts) */
8269 8270
        if (-1 == prepareStbStmtBindStartTime(
                    tableName,
8271 8272
                    pThreadInfo->bind_ts,
                    bindArray, stbInfo,
8273
                    startTime, k
8274
                    /* is column */)) {
8275
            return -1;
8276
        }
8277 8278
        ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        if (0 != ret) {
8279
            errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n",
8280 8281 8282
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
8283
        // if msg > 3MB, break
8284 8285
        ret = taos_stmt_add_batch(stmt);
        if (0 != ret) {
8286
            errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n",
8287 8288 8289
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
8290

8291 8292
        k++;
        recordFrom ++;
8293

8294
        (*pSamplePos) ++;
8295
        if ((*pSamplePos) == MAX_SAMPLES) {
8296 8297 8298
            *pSamplePos = 0;
        }

8299 8300 8301 8302
        if (recordFrom >= insertRows) {
            break;
        }
    }
8303 8304 8305

    return k;
}
8306
#endif
8307

8308
static int32_t prepareStbStmt(
8309
        threadInfo *pThreadInfo,
8310 8311 8312
        char *tableName,
        int64_t tableSeq,
        uint32_t batch,
8313 8314 8315 8316 8317
        uint64_t insertRows,
        uint64_t recordFrom,
        int64_t startTime,
        int64_t *pSamplePos)
{
8318 8319 8320
    int ret;
    SSuperTable *stbInfo = pThreadInfo->stbInfo;
    TAOS_STMT *stmt = pThreadInfo->stmt;
8321

8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333
    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) {
8334
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
8335 8336 8337 8338 8339 8340 8341
                    __func__, __LINE__);
            return -1;
        }

        char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount);
        if (NULL == tagsArray) {
            tmfree(tagsValBuf);
8342
            errorPrint2("%s() LN%d, tag buf failed to allocate  memory\n",
8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360
                    __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) {
8361
            errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n",
8362 8363 8364 8365 8366 8367
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    } else {
        ret = taos_stmt_set_tbname(stmt, tableName);
        if (0 != ret) {
8368
            errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n",
8369 8370 8371 8372 8373
                    __func__, __LINE__, taos_stmt_errstr(stmt));
            return -1;
        }
    }

8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394
#if STMT_BIND_PARAM_BATCH == 1
    return execBindParamBatch(
        pThreadInfo,
        tableName,
        tableSeq,
        batch,
        insertRows,
        recordFrom,
        startTime,
        pSamplePos);
#else
    return execBindParam(
        pThreadInfo,
        tableName,
        tableSeq,
        batch,
        insertRows,
        recordFrom,
        startTime,
        pSamplePos);
#endif
8395
}
8396 8397

static int32_t generateStbProgressiveData(
8398
        SSuperTable *stbInfo,
8399
        char *tableName,
8400
        int64_t tableSeq,
8401
        char *dbName, char *buffer,
8402
        int64_t insertRows,
8403
        uint64_t recordFrom, int64_t startTime, int64_t *pSamplePos,
8404
        int64_t *pRemainderBufLen)
8405
{
8406 8407
    assert(buffer != NULL);
    char *pstr = buffer;
8408

8409
    memset(pstr, 0, *pRemainderBufLen);
8410

8411
    int64_t headLen = generateStbSQLHead(
8412
            stbInfo,
8413 8414
            tableName, tableSeq, dbName,
            buffer, *pRemainderBufLen);
8415

8416 8417 8418 8419 8420
    if (headLen <= 0) {
        return 0;
    }
    pstr += headLen;
    *pRemainderBufLen -= headLen;
8421

8422
    int64_t dataLen;
8423

8424
    return generateStbDataTail(stbInfo,
8425
            g_args.reqPerReq, pstr, *pRemainderBufLen,
8426 8427 8428
            insertRows, recordFrom,
            startTime,
            pSamplePos, &dataLen);
8429 8430
}

8431
static int32_t generateProgressiveDataWithoutStb(
8432
        char *tableName,
8433
        /* int64_t tableSeq, */
8434 8435
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
8436
        uint64_t recordFrom, int64_t startTime, /*int64_t *pSamplePos, */
8437 8438
        int64_t *pRemainderBufLen)
{
8439 8440
    assert(buffer != NULL);
    char *pstr = buffer;
8441

8442
    memset(buffer, 0, *pRemainderBufLen);
8443

8444 8445 8446
    int64_t headLen = generateSQLHeadWithoutStb(
            tableName, pThreadInfo->db_name,
            buffer, *pRemainderBufLen);
8447

8448 8449 8450 8451 8452
    if (headLen <= 0) {
        return 0;
    }
    pstr += headLen;
    *pRemainderBufLen -= headLen;
8453

8454
    int64_t dataLen;
8455

8456
    return generateDataTailWithoutStb(
8457
            g_args.reqPerReq, pstr, *pRemainderBufLen, insertRows, recordFrom,
8458 8459
            startTime,
            /*pSamplePos, */&dataLen);
8460
}
8461

8462 8463
static void printStatPerThread(threadInfo *pThreadInfo)
{
8464 8465 8466
    if (0 == pThreadInfo->totalDelay)
        pThreadInfo->totalDelay = 1;

8467
    fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
8468 8469 8470
            pThreadInfo->threadID,
            pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows,
8471 8472
            (double)(pThreadInfo->totalAffectedRows/((double)pThreadInfo->totalDelay/1000000.0))
            );
8473 8474
}

8475 8476 8477 8478
#if STMT_BIND_PARAM_BATCH == 1
// stmt sync write interlace data
static void* syncWriteInterlaceStmtBatch(threadInfo *pThreadInfo, uint32_t interlaceRows) {
    debugPrint("[%d] %s() LN%d: ### stmt interlace write\n",
8479
            pThreadInfo->threadID, __func__, __LINE__);
8480

8481
    int64_t insertRows;
8482
    int64_t timeStampStep;
8483
    uint64_t insert_interval;
8484

8485
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
8486

8487 8488
    if (stbInfo) {
        insertRows = stbInfo->insertRows;
8489
        timeStampStep = stbInfo->timeStampStep;
8490 8491 8492
        insert_interval = stbInfo->insertInterval;
    } else {
        insertRows = g_args.insertRows;
8493
        timeStampStep = g_args.timestamp_step;
8494 8495
        insert_interval = g_args.insert_interval;
    }
8496

8497 8498 8499 8500 8501
    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);

8502 8503
    uint64_t timesInterlace = (insertRows / interlaceRows) + 1;
    uint32_t precalcBatch = interlaceRows;
8504

8505 8506
    if (precalcBatch > g_args.reqPerReq)
        precalcBatch = g_args.reqPerReq;
8507

8508 8509
    if (precalcBatch > MAX_SAMPLES)
        precalcBatch = MAX_SAMPLES;
8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521

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

    uint64_t st = 0;
    uint64_t et = UINT64_MAX;

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

    uint64_t tableSeq = pThreadInfo->start_table_from;
8522
    int64_t startTime;
8523 8524 8525 8526 8527 8528

    bool flagSleep = true;
    uint64_t sleepTimeTotal = 0;

    int percentComplete = 0;
    int64_t totalRows = insertRows * pThreadInfo->ntables;
8529
    pThreadInfo->samplePos = 0;
8530

8531 8532
    for (int64_t interlace = 0;
            interlace < timesInterlace; interlace ++) {
8533 8534 8535 8536 8537
        if ((flagSleep) && (insert_interval)) {
            st = taosGetTimestampMs();
            flagSleep = false;
        }

8538 8539
        int64_t generated = 0;
        int64_t samplePos;
8540

8541
        for (; tableSeq < pThreadInfo->start_table_from + pThreadInfo->ntables; tableSeq ++) {
8542 8543 8544 8545 8546 8547 8548 8549
            char tableName[TSDB_TABLE_NAME_LEN];
            getTableName(tableName, pThreadInfo, tableSeq);
            if (0 == strlen(tableName)) {
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
                        pThreadInfo->threadID, __func__, __LINE__);
                return NULL;
            }

8550 8551 8552 8553 8554 8555
            samplePos = pThreadInfo->samplePos;
            startTime = pThreadInfo->start_time
                + interlace * interlaceRows * timeStampStep;
            uint64_t remainRecPerTbl =
                    insertRows - interlaceRows * interlace;
            uint64_t recPerTbl = 0;
8556

8557 8558 8559 8560 8561
            uint64_t remainPerInterlace;
            if (remainRecPerTbl > interlaceRows) {
                remainPerInterlace = interlaceRows;
            } else {
                remainPerInterlace = remainRecPerTbl;
8562 8563
            }

8564
            while(remainPerInterlace > 0) {
8565

8566 8567 8568 8569 8570 8571 8572 8573 8574 8575
                uint32_t batch;
                if (remainPerInterlace > precalcBatch) {
                    batch = precalcBatch;
                } else {
                    batch = remainPerInterlace;
                }
                debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n",
                        pThreadInfo->threadID,
                        __func__, __LINE__,
                        tableName, batch, startTime);
8576

8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594
                if (stbInfo) {
                    generated = prepareStbStmt(
                            pThreadInfo,
                            tableName,
                            tableSeq,
                            batch,
                            insertRows, 0,
                            startTime,
                            &samplePos);
                } else {
                    generated = prepareStmtWithoutStb(
                            pThreadInfo,
                            tableName,
                            batch,
                            insertRows,
                            interlaceRows * interlace + recPerTbl,
                            startTime);
                }
8595

8596 8597 8598 8599 8600 8601 8602
                debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                        pThreadInfo->threadID, __func__, __LINE__, generated);
                if (generated < 0) {
                    errorPrint2("[%d] %s() LN%d, generated records is %"PRId64"\n",
                            pThreadInfo->threadID, __func__, __LINE__, generated);
                    goto free_of_interlace_stmt;
                } else if (generated == 0) {
8603
                    break;
8604
                }
8605

8606 8607 8608
                recPerTbl += generated;
                remainPerInterlace -= generated;
                pThreadInfo->totalInsertRows += generated;
8609

8610 8611 8612
                verbosePrint("[%d] %s() LN%d totalInsertRows=%"PRIu64"\n",
                        pThreadInfo->threadID, __func__, __LINE__,
                        pThreadInfo->totalInsertRows);
8613

8614
                startTs = taosGetTimestampUs();
8615

8616
                int64_t affectedRows = execInsert(pThreadInfo, generated);
8617

8618 8619 8620 8621 8622 8623 8624
                endTs = taosGetTimestampUs();
                uint64_t delay = endTs - startTs;
                performancePrint("%s() LN%d, insert execution time is %10.2f ms\n",
                        __func__, __LINE__, delay / 1000.0);
                verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
                        pThreadInfo->threadID,
                        __func__, __LINE__, affectedRows);
8625

8626 8627 8628 8629
                if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
                if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
                pThreadInfo->cntDelay++;
                pThreadInfo->totalDelay += delay;
8630

8631 8632 8633 8634 8635 8636
                if (generated != affectedRows) {
                    errorPrint2("[%d] %s() LN%d execInsert() insert %"PRId64", affected rows: %"PRId64"\n\n",
                            pThreadInfo->threadID, __func__, __LINE__,
                            generated, affectedRows);
                    goto free_of_interlace_stmt;
                }
8637

8638
                pThreadInfo->totalAffectedRows += affectedRows;
8639

8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652
                int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
                if (currentPercent > percentComplete ) {
                    printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
                    percentComplete = currentPercent;
                }
                int64_t  currentPrintTime = taosGetTimestampMs();
                if (currentPrintTime - lastPrintTime > 30*1000) {
                    printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
                            pThreadInfo->threadID,
                            pThreadInfo->totalInsertRows,
                            pThreadInfo->totalAffectedRows);
                    lastPrintTime = currentPrintTime;
                }
8653

8654 8655
                startTime += (generated * timeStampStep);
            }
8656
        }
8657
        pThreadInfo->samplePos = samplePos;
8658

8659 8660 8661 8662
        if (tableSeq == pThreadInfo->start_table_from
                + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
8663

8664
            flagSleep = true;
8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693
        }

        if ((insert_interval) && flagSleep) {
            et = taosGetTimestampMs();

            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;
            }
        }
    }
    if (percentComplete < 100)
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);

free_of_interlace_stmt:
    printStatPerThread(pThreadInfo);
    return NULL;
}
#else
// stmt sync write interlace data
static void* syncWriteInterlaceStmt(threadInfo *pThreadInfo, uint32_t interlaceRows) {
    debugPrint("[%d] %s() LN%d: ### stmt interlace write\n",
            pThreadInfo->threadID, __func__, __LINE__);

    int64_t insertRows;
    uint64_t maxSqlLen;
8694
    int64_t timeStampStep;
8695 8696 8697 8698 8699 8700
    uint64_t insert_interval;

    SSuperTable* stbInfo = pThreadInfo->stbInfo;

    if (stbInfo) {
        insertRows = stbInfo->insertRows;
8701
        maxSqlLen = stbInfo->maxSqlLen;
8702
        timeStampStep = stbInfo->timeStampStep;
8703
        insert_interval = stbInfo->insertInterval;
8704
    } else {
8705
        insertRows = g_args.insertRows;
8706
        maxSqlLen = g_args.max_sql_len;
8707
        timeStampStep = g_args.timestamp_step;
8708
        insert_interval = g_args.insert_interval;
8709
    }
8710

8711 8712 8713 8714
    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);
8715

8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767
    uint32_t batchPerTbl = interlaceRows;
    uint32_t batchPerTblTimes;

    if (interlaceRows > g_args.reqPerReq)
        interlaceRows = g_args.reqPerReq;

    if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
        batchPerTblTimes =
            g_args.reqPerReq / interlaceRows;
    } else {
        batchPerTblTimes = 1;
    }

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

    uint64_t st = 0;
    uint64_t et = UINT64_MAX;

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

    uint64_t tableSeq = pThreadInfo->start_table_from;
    int64_t startTime = pThreadInfo->start_time;

    uint64_t generatedRecPerTbl = 0;
    bool flagSleep = true;
    uint64_t sleepTimeTotal = 0;

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

    while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
        if ((flagSleep) && (insert_interval)) {
            st = taosGetTimestampMs();
            flagSleep = false;
        }

        uint32_t recOfBatch = 0;

        int32_t generated;
        for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
            char tableName[TSDB_TABLE_NAME_LEN];

            getTableName(tableName, pThreadInfo, tableSeq);
            if (0 == strlen(tableName)) {
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
                        pThreadInfo->threadID, __func__, __LINE__);
                return NULL;
            }

8768 8769 8770 8771
            debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n",
                    pThreadInfo->threadID,
                    __func__, __LINE__,
                    tableName, batchPerTbl, startTime);
8772
            if (stbInfo) {
8773
                generated = prepareStbStmt(
8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814
                        pThreadInfo,
                        tableName,
                        tableSeq,
                        batchPerTbl,
                        insertRows, 0,
                        startTime,
                        &(pThreadInfo->samplePos));
            } else {
                generated = prepareStmtWithoutStb(
                        pThreadInfo,
                        tableName,
                        batchPerTbl,
                        insertRows, i,
                        startTime);
            }

            debugPrint("[%d] %s() LN%d, generated records is %d\n",
                    pThreadInfo->threadID, __func__, __LINE__, generated);
            if (generated < 0) {
                errorPrint2("[%d] %s() LN%d, generated records is %d\n",
                        pThreadInfo->threadID, __func__, __LINE__, generated);
                goto free_of_interlace_stmt;
            } else if (generated == 0) {
                break;
            }

            tableSeq ++;
            recOfBatch += batchPerTbl;

            pThreadInfo->totalInsertRows += batchPerTbl;

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

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

                startTime = pThreadInfo->start_time
8815
                    + generatedRecPerTbl * timeStampStep;
8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911

                flagSleep = true;
                if (generatedRecPerTbl >= insertRows)
                    break;

                int64_t remainRows = insertRows - generatedRecPerTbl;
                if ((remainRows > 0) && (batchPerTbl > remainRows))
                    batchPerTbl = remainRows;

                if (pThreadInfo->ntables * batchPerTbl < g_args.reqPerReq)
                    break;
            }

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

            if ((g_args.reqPerReq - recOfBatch) < batchPerTbl)
                break;
        }

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

        startTs = taosGetTimestampUs();

        if (recOfBatch == 0) {
            errorPrint2("[%d] %s() LN%d Failed to insert records of batch %d\n",
                    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);
            }
            goto free_of_interlace_stmt;
        }
        int64_t affectedRows = execInsert(pThreadInfo, recOfBatch);

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

        if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
        if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
        pThreadInfo->cntDelay++;
        pThreadInfo->totalDelay += delay;

        if (recOfBatch != affectedRows) {
            errorPrint2("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n\n",
                    pThreadInfo->threadID, __func__, __LINE__,
                    recOfBatch, affectedRows);
            goto free_of_interlace_stmt;
        }

        pThreadInfo->totalAffectedRows += affectedRows;

        int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
        if (currentPercent > percentComplete ) {
            printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
            percentComplete = currentPercent;
        }
        int64_t  currentPrintTime = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
            printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
            lastPrintTime = currentPrintTime;
        }

        if ((insert_interval) && flagSleep) {
            et = taosGetTimestampMs();

            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;
            }
        }
    }
    if (percentComplete < 100)
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);

free_of_interlace_stmt:
    printStatPerThread(pThreadInfo);
    return NULL;
}

#endif
8912

8913 8914 8915 8916 8917 8918 8919
// sync write interlace data
static void* syncWriteInterlace(threadInfo *pThreadInfo, uint32_t interlaceRows) {
    debugPrint("[%d] %s() LN%d: ### interlace write\n",
            pThreadInfo->threadID, __func__, __LINE__);

    int64_t insertRows;
    uint64_t maxSqlLen;
8920
    int64_t timeStampStep;
8921 8922 8923 8924 8925 8926 8927
    uint64_t insert_interval;

    SSuperTable* stbInfo = pThreadInfo->stbInfo;

    if (stbInfo) {
        insertRows = stbInfo->insertRows;
        maxSqlLen = stbInfo->maxSqlLen;
8928
        timeStampStep = stbInfo->timeStampStep;
8929 8930 8931 8932
        insert_interval = stbInfo->insertInterval;
    } else {
        insertRows = g_args.insertRows;
        maxSqlLen = g_args.max_sql_len;
8933
        timeStampStep = g_args.timestamp_step;
8934 8935 8936 8937 8938 8939 8940 8941
        insert_interval = g_args.insert_interval;
    }

    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);
#if 1
8942 8943
    if (interlaceRows > g_args.reqPerReq)
        interlaceRows = g_args.reqPerReq;
8944

8945 8946
    uint32_t batchPerTbl = interlaceRows;
    uint32_t batchPerTblTimes;
8947

8948 8949
    if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
        batchPerTblTimes =
8950
            g_args.reqPerReq / interlaceRows;
8951 8952 8953
    } else {
        batchPerTblTimes = 1;
    }
8954 8955 8956 8957 8958 8959 8960 8961
#else
    uint32_t batchPerTbl;
    if (interlaceRows > g_args.reqPerReq)
        batchPerTbl = g_args.reqPerReq;
    else
        batchPerTbl = interlaceRows;

    uint32_t batchPerTblTimes;
8962

8963 8964 8965 8966 8967 8968 8969
    if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
        batchPerTblTimes =
            interlaceRows / batchPerTbl;
    } else {
        batchPerTblTimes = 1;
    }
#endif
8970 8971
    pThreadInfo->buffer = calloc(maxSqlLen, 1);
    if (NULL == pThreadInfo->buffer) {
8972
        errorPrint2( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
8973 8974 8975
                __func__, __LINE__, maxSqlLen, strerror(errno));
        return NULL;
    }
8976

8977 8978
    pThreadInfo->totalInsertRows = 0;
    pThreadInfo->totalAffectedRows = 0;
8979

8980 8981
    uint64_t st = 0;
    uint64_t et = UINT64_MAX;
8982

8983 8984 8985
    uint64_t lastPrintTime = taosGetTimestampMs();
    uint64_t startTs = taosGetTimestampMs();
    uint64_t endTs;
8986

8987 8988
    uint64_t tableSeq = pThreadInfo->start_table_from;
    int64_t startTime = pThreadInfo->start_time;
8989

8990 8991 8992
    uint64_t generatedRecPerTbl = 0;
    bool flagSleep = true;
    uint64_t sleepTimeTotal = 0;
8993

8994 8995 8996
    int percentComplete = 0;
    int64_t totalRows = insertRows * pThreadInfo->ntables;

8997 8998 8999 9000 9001
    while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
        if ((flagSleep) && (insert_interval)) {
            st = taosGetTimestampMs();
            flagSleep = false;
        }
9002

9003 9004 9005
        // generate data
        memset(pThreadInfo->buffer, 0, maxSqlLen);
        uint64_t remainderBufLen = maxSqlLen;
9006

9007
        char *pstr = pThreadInfo->buffer;
9008

9009 9010 9011 9012
        int len = snprintf(pstr,
                strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
        pstr += len;
        remainderBufLen -= len;
9013

9014
        uint32_t recOfBatch = 0;
9015

9016
        int32_t generated;
9017 9018
        for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
            char tableName[TSDB_TABLE_NAME_LEN];
9019

9020 9021
            getTableName(tableName, pThreadInfo, tableSeq);
            if (0 == strlen(tableName)) {
9022
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
9023 9024 9025 9026
                        pThreadInfo->threadID, __func__, __LINE__);
                free(pThreadInfo->buffer);
                return NULL;
            }
9027

9028
            uint64_t oldRemainderLen = remainderBufLen;
9029

9030
            if (stbInfo) {
9031 9032 9033 9034 9035 9036 9037 9038 9039
                generated = generateStbInterlaceData(
                        pThreadInfo,
                        tableName, batchPerTbl, i,
                        batchPerTblTimes,
                        tableSeq,
                        pstr,
                        insertRows,
                        startTime,
                        &remainderBufLen);
9040
            } else {
9041 9042 9043 9044 9045 9046 9047
                generated = generateInterlaceDataWithoutStb(
                        tableName, batchPerTbl,
                        tableSeq,
                        pThreadInfo->db_name, pstr,
                        insertRows,
                        startTime,
                        &remainderBufLen);
9048
            }
9049

9050 9051 9052
            debugPrint("[%d] %s() LN%d, generated records is %d\n",
                    pThreadInfo->threadID, __func__, __LINE__, generated);
            if (generated < 0) {
9053
                errorPrint2("[%d] %s() LN%d, generated records is %d\n",
9054 9055 9056 9057 9058
                        pThreadInfo->threadID, __func__, __LINE__, generated);
                goto free_of_interlace;
            } else if (generated == 0) {
                break;
            }
9059

9060 9061
            tableSeq ++;
            recOfBatch += batchPerTbl;
9062

9063 9064
            pstr += (oldRemainderLen - remainderBufLen);
            pThreadInfo->totalInsertRows += batchPerTbl;
9065

9066 9067 9068
            verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
                    pThreadInfo->threadID, __func__, __LINE__,
                    batchPerTbl, recOfBatch);
9069

9070 9071 9072 9073
            if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
                // turn to first table
                tableSeq = pThreadInfo->start_table_from;
                generatedRecPerTbl += batchPerTbl;
9074

9075
                startTime = pThreadInfo->start_time
9076
                    + generatedRecPerTbl * timeStampStep;
9077

9078 9079 9080
                flagSleep = true;
                if (generatedRecPerTbl >= insertRows)
                    break;
9081

9082 9083 9084
                int64_t remainRows = insertRows - generatedRecPerTbl;
                if ((remainRows > 0) && (batchPerTbl > remainRows))
                    batchPerTbl = remainRows;
9085

9086
                if (pThreadInfo->ntables * batchPerTbl < g_args.reqPerReq)
9087 9088
                    break;
            }
9089

9090 9091 9092
            verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
                    pThreadInfo->threadID, __func__, __LINE__,
                    generatedRecPerTbl, insertRows);
9093

9094
            if ((g_args.reqPerReq - recOfBatch) < batchPerTbl)
9095
                break;
9096
        }
9097

9098 9099 9100 9101 9102 9103
        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);

9104
        startTs = taosGetTimestampUs();
9105 9106

        if (recOfBatch == 0) {
9107
            errorPrint2("[%d] %s() LN%d Failed to insert records of batch %d\n",
9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119
                    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);

9120
        endTs = taosGetTimestampUs();
9121
        uint64_t delay = endTs - startTs;
9122 9123
        performancePrint("%s() LN%d, insert execution time is %10.2f ms\n",
                __func__, __LINE__, delay / 1000.0);
9124 9125 9126
        verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
                pThreadInfo->threadID,
                __func__, __LINE__, affectedRows);
9127

9128 9129 9130 9131
        if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
        if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
        pThreadInfo->cntDelay++;
        pThreadInfo->totalDelay += delay;
9132

9133
        if (recOfBatch != affectedRows) {
9134
            errorPrint2("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n",
9135 9136 9137 9138
                    pThreadInfo->threadID, __func__, __LINE__,
                    recOfBatch, affectedRows, pThreadInfo->buffer);
            goto free_of_interlace;
        }
9139

9140
        pThreadInfo->totalAffectedRows += affectedRows;
9141

9142 9143 9144 9145 9146
        int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
        if (currentPercent > percentComplete ) {
            printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
            percentComplete = currentPercent;
        }
9147 9148 9149
        int64_t  currentPrintTime = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
            printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
9150 9151 9152
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
9153 9154
            lastPrintTime = currentPrintTime;
        }
9155

9156 9157
        if ((insert_interval) && flagSleep) {
            et = taosGetTimestampMs();
9158

9159 9160 9161 9162 9163 9164 9165 9166
            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;
            }
        }
9167
    }
9168 9169
    if (percentComplete < 100)
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);
9170

9171
free_of_interlace:
9172 9173 9174
    tmfree(pThreadInfo->buffer);
    printStatPerThread(pThreadInfo);
    return NULL;
9175 9176
}

9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 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 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314
static void* syncWriteProgressiveStmt(threadInfo *pThreadInfo) {
    debugPrint("%s() LN%d: ### stmt progressive write\n", __func__, __LINE__);

    SSuperTable* stbInfo = pThreadInfo->stbInfo;
    int64_t timeStampStep =
        stbInfo?stbInfo->timeStampStep:g_args.timestamp_step;
    int64_t insertRows =
        (stbInfo)?stbInfo->insertRows:g_args.insertRows;
    verbosePrint("%s() LN%d insertRows=%"PRId64"\n",
            __func__, __LINE__, insertRows);

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

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

    pThreadInfo->samplePos = 0;

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

    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)) {
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
                        pThreadInfo->threadID, __func__, __LINE__);
                return NULL;
            }

            // measure prepare + insert
            startTs = taosGetTimestampUs();

            int32_t generated;
            if (stbInfo) {
                generated = prepareStbStmt(
                        pThreadInfo,
                        tableName,
                        tableSeq,
                        (g_args.reqPerReq>stbInfo->insertRows)?
                        stbInfo->insertRows:
                        g_args.reqPerReq,
                        insertRows, i, start_time,
                        &(pThreadInfo->samplePos));
            } else {
                generated = prepareStmtWithoutStb(
                        pThreadInfo,
                        tableName,
                        g_args.reqPerReq,
                        insertRows, i,
                        start_time);
            }

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

            if (generated > 0)
                i += generated;
            else
                goto free_of_stmt_progressive;

            start_time +=  generated * timeStampStep;
            pThreadInfo->totalInsertRows += generated;

            // only measure insert
            // startTs = taosGetTimestampUs();

            int32_t affectedRows = execInsert(pThreadInfo, generated);

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

            if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
            if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
            pThreadInfo->cntDelay++;
            pThreadInfo->totalDelay += delay;

            if (affectedRows < 0) {
                errorPrint2("%s() LN%d, affected rows: %d\n",
                        __func__, __LINE__, affectedRows);
                goto free_of_stmt_progressive;
            }

            pThreadInfo->totalAffectedRows += affectedRows;

            int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
            if (currentPercent > percentComplete ) {
                printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
                percentComplete = currentPercent;
            }
            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;
            }

            if (i >= insertRows)
                break;
        }   // insertRows

        if ((g_args.verbose_print) &&
                (tableSeq == pThreadInfo->ntables - 1) && (stbInfo)
                && (0 == strncasecmp(
                        stbInfo->dataSource,
                        "sample", strlen("sample")))) {
            verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
                    __func__, __LINE__, pThreadInfo->samplePos);
        }
    } // tableSeq

    if (percentComplete < 100) {
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);
    }

free_of_stmt_progressive:
    tmfree(pThreadInfo->buffer);
    printStatPerThread(pThreadInfo);
    return NULL;
}
9315
// sync insertion progressive data
9316
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
9317
    debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
9318

9319 9320
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
    uint64_t maxSqlLen = stbInfo?stbInfo->maxSqlLen:g_args.max_sql_len;
9321
    int64_t timeStampStep =
9322
        stbInfo?stbInfo->timeStampStep:g_args.timestamp_step;
9323
    int64_t insertRows =
9324
        (stbInfo)?stbInfo->insertRows:g_args.insertRows;
9325
    verbosePrint("%s() LN%d insertRows=%"PRId64"\n",
9326
            __func__, __LINE__, insertRows);
9327

9328 9329
    pThreadInfo->buffer = calloc(maxSqlLen, 1);
    if (NULL == pThreadInfo->buffer) {
9330
        errorPrint2("Failed to alloc %"PRIu64" bytes, reason:%s\n",
9331 9332
                maxSqlLen,
                strerror(errno));
9333
        return NULL;
9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344
    }

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

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

    pThreadInfo->samplePos = 0;

9345 9346 9347
    int percentComplete = 0;
    int64_t totalRows = insertRows * pThreadInfo->ntables;

9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359
    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)) {
9360
                errorPrint2("[%d] %s() LN%d, getTableName return null\n",
9361 9362 9363 9364
                        pThreadInfo->threadID, __func__, __LINE__);
                free(pThreadInfo->buffer);
                return NULL;
            }
9365

9366
            int64_t remainderBufLen = maxSqlLen - 2000;
9367
            char *pstr = pThreadInfo->buffer;
9368

9369 9370
            int len = snprintf(pstr,
                    strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
9371

9372 9373
            pstr += len;
            remainderBufLen -= len;
9374

9375 9376 9377
            // measure prepare + insert
            startTs = taosGetTimestampUs();

9378
            int32_t generated;
9379 9380
            if (stbInfo) {
                if (stbInfo->iface == STMT_IFACE) {
9381
                    generated = prepareStbStmt(
9382 9383 9384
                            pThreadInfo,
                            tableName,
                            tableSeq,
9385 9386 9387
                            (g_args.reqPerReq>stbInfo->insertRows)?
                                stbInfo->insertRows:
                                g_args.reqPerReq,
9388 9389
                            insertRows, i, start_time,
                            &(pThreadInfo->samplePos));
9390 9391
                } else {
                    generated = generateStbProgressiveData(
9392 9393 9394
                            stbInfo,
                            tableName, tableSeq,
                            pThreadInfo->db_name, pstr,
9395 9396 9397 9398 9399 9400 9401
                            insertRows, i, start_time,
                            &(pThreadInfo->samplePos),
                            &remainderBufLen);
                }
            } else {
                if (g_args.iface == STMT_IFACE) {
                    generated = prepareStmtWithoutStb(
9402
                            pThreadInfo,
9403
                            tableName,
9404
                            g_args.reqPerReq,
9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416
                            insertRows, i,
                            start_time);
                } else {
                    generated = generateProgressiveDataWithoutStb(
                            tableName,
                            /*  tableSeq, */
                            pThreadInfo, pstr, insertRows,
                            i, start_time,
                            /* &(pThreadInfo->samplePos), */
                            &remainderBufLen);
                }
            }
9417 9418 9419 9420 9421

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

9422 9423 9424 9425
            if (generated > 0)
                i += generated;
            else
                goto free_of_progressive;
9426

9427 9428
            start_time +=  generated * timeStampStep;
            pThreadInfo->totalInsertRows += generated;
9429

9430 9431
            // only measure insert
            // startTs = taosGetTimestampUs();
9432

9433
            int32_t affectedRows = execInsert(pThreadInfo, generated);
9434

9435
            endTs = taosGetTimestampUs();
9436
            uint64_t delay = endTs - startTs;
9437 9438
            performancePrint("%s() LN%d, insert execution time is %10.f ms\n",
                    __func__, __LINE__, delay/1000.0);
9439 9440 9441
            verbosePrint("[%d] %s() LN%d affectedRows=%d\n",
                    pThreadInfo->threadID,
                    __func__, __LINE__, affectedRows);
9442

9443 9444 9445 9446
            if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
            if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
            pThreadInfo->cntDelay++;
            pThreadInfo->totalDelay += delay;
9447

9448
            if (affectedRows < 0) {
9449
                errorPrint2("%s() LN%d, affected rows: %d\n",
9450 9451 9452
                        __func__, __LINE__, affectedRows);
                goto free_of_progressive;
            }
9453

9454
            pThreadInfo->totalAffectedRows += affectedRows;
9455

9456 9457 9458 9459 9460
            int currentPercent = pThreadInfo->totalAffectedRows * 100 / totalRows;
            if (currentPercent > percentComplete ) {
                printf("[%d]:%d%%\n", pThreadInfo->threadID, currentPercent);
                percentComplete = currentPercent;
            }
9461 9462 9463 9464 9465 9466 9467 9468
            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;
            }
9469

9470 9471
            if (i >= insertRows)
                break;
9472
        }   // insertRows
9473

9474
        if ((g_args.verbose_print) &&
9475
                (tableSeq == pThreadInfo->ntables - 1) && (stbInfo)
9476
                && (0 == strncasecmp(
9477
                        stbInfo->dataSource,
9478
                        "sample", strlen("sample")))) {
9479 9480 9481 9482
            verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
                    __func__, __LINE__, pThreadInfo->samplePos);
        }
    } // tableSeq
9483 9484

    if (percentComplete < 100) {
9485
        printf("[%d]:%d%%\n", pThreadInfo->threadID, percentComplete);
9486
    }
9487

9488
free_of_progressive:
9489 9490 9491
    tmfree(pThreadInfo->buffer);
    printStatPerThread(pThreadInfo);
    return NULL;
H
Hui Li 已提交
9492 9493
}

9494 9495
static void* syncWrite(void *sarg) {

9496
    threadInfo *pThreadInfo = (threadInfo *)sarg;
9497
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
9498

9499 9500
    setThreadName("syncWrite");

9501
    uint32_t interlaceRows = 0;
9502

9503
    if (stbInfo) {
9504
        if (stbInfo->interlaceRows < stbInfo->insertRows)
9505
            interlaceRows = stbInfo->interlaceRows;
9506
    } else {
9507 9508
        if (g_args.interlaceRows < g_args.insertRows)
            interlaceRows = g_args.interlaceRows;
9509
    }
9510

9511 9512
    if (interlaceRows > 0) {
        // interlace mode
9513 9514
        if (stbInfo) {
            if (STMT_IFACE == stbInfo->iface) {
9515
#if STMT_BIND_PARAM_BATCH == 1
9516
                return syncWriteInterlaceStmtBatch(pThreadInfo, interlaceRows);
9517
#else
9518
                return syncWriteInterlaceStmt(pThreadInfo, interlaceRows);
9519
#endif
9520 9521 9522
            } else {
                return syncWriteInterlace(pThreadInfo, interlaceRows);
            }
9523
        }
9524 9525 9526 9527 9528 9529 9530 9531
    } else {
      // progressive mode
      if (((stbInfo) && (STMT_IFACE == stbInfo->iface))
              || (STMT_IFACE == g_args.iface)) {
          return syncWriteProgressiveStmt(pThreadInfo);
      } else {
          return syncWriteProgressive(pThreadInfo);
      }
9532
    }
9533 9534

    return NULL;
9535 9536
}

9537
static void callBack(void *param, TAOS_RES *res, int code) {
9538
    threadInfo* pThreadInfo = (threadInfo*)param;
9539
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
9540 9541

    int insert_interval =
9542
        stbInfo?stbInfo->insertInterval:g_args.insert_interval;
9543 9544 9545 9546 9547
    if (insert_interval) {
        pThreadInfo->et = taosGetTimestampMs();
        if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
            taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
        }
H
Hui Li 已提交
9548 9549
    }

9550
    char *buffer = calloc(1, pThreadInfo->stbInfo->maxSqlLen);
9551 9552
    char data[MAX_DATA_SIZE];
    char *pstr = buffer;
9553
    pstr += sprintf(pstr, "INSERT INTO %s.%s%"PRId64" VALUES",
9554 9555
            pThreadInfo->db_name, pThreadInfo->tb_prefix,
            pThreadInfo->start_table_from);
9556
    //  if (pThreadInfo->counter >= pThreadInfo->stbInfo->insertRows) {
9557
    if (pThreadInfo->counter >= g_args.reqPerReq) {
9558 9559 9560 9561 9562 9563 9564 9565
        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 已提交
9566
    }
9567

9568
    for (int i = 0; i < g_args.reqPerReq; i++) {
9569
        int rand_num = taosRandom() % 100;
9570 9571
        if (0 != pThreadInfo->stbInfo->disorderRatio
                && rand_num < pThreadInfo->stbInfo->disorderRatio) {
9572
            int64_t d = pThreadInfo->lastTs
9573 9574
                - (taosRandom() % pThreadInfo->stbInfo->disorderRange + 1);
            generateStbRowData(pThreadInfo->stbInfo, data,
9575 9576
                    MAX_DATA_SIZE,
                    d);
9577
        } else {
9578
            generateStbRowData(pThreadInfo->stbInfo,
9579 9580 9581
                    data,
                    MAX_DATA_SIZE,
                    pThreadInfo->lastTs += 1000);
9582 9583 9584
        }
        pstr += sprintf(pstr, "%s", data);
        pThreadInfo->counter++;
H
Hui Li 已提交
9585

9586
        if (pThreadInfo->counter >= pThreadInfo->stbInfo->insertRows) {
9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597
            break;
        }
    }

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

    taos_free_result(res);
H
Hui Li 已提交
9598 9599
}

9600
static void *asyncWrite(void *sarg) {
9601
    threadInfo *pThreadInfo = (threadInfo *)sarg;
9602
    SSuperTable* stbInfo = pThreadInfo->stbInfo;
9603

9604
    setThreadName("asyncWrite");
9605

9606 9607 9608
    pThreadInfo->st = 0;
    pThreadInfo->et = 0;
    pThreadInfo->lastTs = pThreadInfo->start_time;
9609

9610
    int insert_interval =
9611
        stbInfo?stbInfo->insertInterval:g_args.insert_interval;
9612 9613 9614 9615
    if (insert_interval) {
        pThreadInfo->st = taosGetTimestampMs();
    }
    taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
9616

9617
    tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
9618

9619
    return NULL;
H
Hui Li 已提交
9620 9621
}

9622 9623
static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in *serv_addr)
{
9624 9625 9626
    uint16_t rest_port = port + TSDB_PORT_HTTP;
    struct hostent *server = gethostbyname(host);
    if ((server == NULL) || (server->h_addr == NULL)) {
9627
        errorPrint2("%s", "no such host");
9628 9629
        return -1;
    }
9630

9631
    debugPrint("h_name: %s\nh_addr=%p\nh_addretype: %s\nh_length: %d\n",
9632 9633 9634 9635 9636
            server->h_name,
            server->h_addr,
            (server->h_addrtype == AF_INET)?"ipv4":"ipv6",
            server->h_length);

9637 9638 9639
    memset(serv_addr, 0, sizeof(struct sockaddr_in));
    serv_addr->sin_family = AF_INET;
    serv_addr->sin_port = htons(rest_port);
9640
#ifdef WINDOWS
9641
    serv_addr->sin_addr.s_addr = inet_addr(host);
9642
#else
9643
    memcpy(&(serv_addr->sin_addr.s_addr), server->h_addr, server->h_length);
9644
#endif
9645
    return 0;
9646 9647
}

9648
static void startMultiThreadInsertData(int threads, char* db_name,
9649
        char* precision, SSuperTable* stbInfo) {
9650

9651 9652 9653 9654 9655 9656 9657 9658 9659
    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 {
9660
            errorPrint2("Not support precision: %s\n", precision);
9661
            exit(EXIT_FAILURE);
9662
        }
9663 9664
    }

9665
    int64_t startTime;
9666 9667
    if (stbInfo) {
        if (0 == strncasecmp(stbInfo->startTimestamp, "now", 3)) {
9668
            startTime = taosGetTimestamp(timePrec);
9669 9670
        } else {
            if (TSDB_CODE_SUCCESS != taosParseTime(
9671
                        stbInfo->startTimestamp,
9672
                        &startTime,
9673
                        strlen(stbInfo->startTimestamp),
9674 9675 9676 9677
                        timePrec, 0)) {
                ERROR_EXIT("failed to parse time!\n");
            }
        }
9678
    } else {
9679
        startTime = DEFAULT_START_TIME;
9680
    }
9681 9682
    debugPrint("%s() LN%d, startTime= %"PRId64"\n",
            __func__, __LINE__, startTime);
9683

9684
    // read sample data from file first
9685
    int ret;
9686
    if (stbInfo) {
9687 9688 9689 9690 9691 9692 9693 9694 9695
        ret = prepareSampleForStb(stbInfo);
    } else {
        ret = prepareSampleForNtb();
    }

    if (0 != ret) {
        errorPrint2("%s() LN%d, prepare sample data for stable failed!\n",
                __func__, __LINE__);
        exit(EXIT_FAILURE);
9696 9697
    }

9698 9699 9700 9701
    TAOS* taos0 = taos_connect(
            g_Dbs.host, g_Dbs.user,
            g_Dbs.password, db_name, g_Dbs.port);
    if (NULL == taos0) {
9702
        errorPrint2("%s() LN%d, connect to server fail , reason: %s\n",
9703
                __func__, __LINE__, taos_errstr(NULL));
9704
        exit(EXIT_FAILURE);
9705
    }
9706

9707 9708
    int64_t ntables = 0;
    uint64_t tableFrom;
9709

9710
    if (stbInfo) {
9711 9712
        int64_t limit;
        uint64_t offset;
9713

9714
        if ((NULL != g_args.sqlFile)
9715 9716 9717
                && (stbInfo->childTblExists == TBL_NO_EXISTS)
                && ((stbInfo->childTblOffset != 0)
                    || (stbInfo->childTblLimit >= 0))) {
9718 9719
            printf("WARNING: offset and limit will not be used since the child tables not exists!\n");
        }
9720

9721 9722 9723 9724 9725
        if (stbInfo->childTblExists == TBL_ALREADY_EXISTS) {
            if ((stbInfo->childTblLimit < 0)
                    || ((stbInfo->childTblOffset
                            + stbInfo->childTblLimit)
                        > (stbInfo->childTblCount))) {
9726 9727 9728 9729 9730 9731

                if (stbInfo->childTblCount < stbInfo->childTblOffset) {
                    printf("WARNING: offset will not be used since the child tables count is less then offset!\n");

                    stbInfo->childTblOffset = 0;
                }
9732 9733
                stbInfo->childTblLimit =
                    stbInfo->childTblCount - stbInfo->childTblOffset;
9734
            }
9735

9736 9737
            offset = stbInfo->childTblOffset;
            limit = stbInfo->childTblLimit;
9738
        } else {
9739
            limit = stbInfo->childTblCount;
9740 9741
            offset = 0;
        }
9742

9743 9744
        ntables = limit;
        tableFrom = offset;
9745

9746 9747 9748
        if ((stbInfo->childTblExists != TBL_NO_EXISTS)
                && ((stbInfo->childTblOffset + stbInfo->childTblLimit)
                    > stbInfo->childTblCount)) {
9749 9750 9751
            printf("WARNING: specified offset + limit > child table count!\n");
            prompt();
        }
9752

9753 9754
        if ((stbInfo->childTblExists != TBL_NO_EXISTS)
                && (0 == stbInfo->childTblLimit)) {
9755 9756 9757
            printf("WARNING: specified limit = 0, which cannot find table name to insert or query! \n");
            prompt();
        }
9758

9759
        stbInfo->childTblName = (char*)calloc(1,
9760
                limit * TSDB_TABLE_NAME_LEN);
9761
        if (stbInfo->childTblName == NULL) {
9762
            taos_close(taos0);
9763
            errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
9764
            exit(EXIT_FAILURE);
9765
        }
9766

9767 9768 9769
        int64_t childTblCount;
        getChildNameOfSuperTableWithLimitAndOffset(
                taos0,
9770
                db_name, stbInfo->stbName,
9771
                &stbInfo->childTblName, &childTblCount,
9772 9773
                limit,
                offset);
9774
        ntables = childTblCount; // CBD
9775
    } else {
9776
        ntables = g_args.ntables;
9777 9778
        tableFrom = 0;
    }
9779

9780
    taos_close(taos0);
9781

9782 9783 9784 9785 9786
    int64_t a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
    }
9787

9788 9789 9790 9791
    int64_t b = 0;
    if (threads != 0) {
        b = ntables % threads;
    }
9792

9793 9794
    if ((stbInfo)
            && (stbInfo->iface == REST_IFACE)) {
9795 9796
        if (convertHostToServAddr(
                    g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0) {
9797
            ERROR_EXIT("convert host to server address");
9798 9799
        }
    }
9800

9801 9802
    pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
    threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
9803
    assert(pids != NULL);
9804
    assert(infos != NULL);
9805

9806 9807
    char *stmtBuffer = calloc(1, BUFFER_SIZE);
    assert(stmtBuffer);
9808 9809

#if STMT_BIND_PARAM_BATCH == 1
9810
    uint32_t interlaceRows = 0;
9811 9812 9813
    uint32_t batch;

    if (stbInfo) {
9814
        if (stbInfo->interlaceRows < stbInfo->insertRows)
9815 9816
            interlaceRows = stbInfo->interlaceRows;
    } else {
9817 9818
        if (g_args.interlaceRows < g_args.insertRows)
            interlaceRows = g_args.interlaceRows;
9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829
    }

    if (interlaceRows > 0) {
        batch = interlaceRows;
    } else {
        batch = (g_args.reqPerReq>g_args.insertRows)?
            g_args.insertRows:g_args.reqPerReq;
    }

#endif

9830 9831 9832 9833 9834 9835 9836 9837 9838
    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(?",
9839
                    stbInfo->stbName);
9840 9841 9842 9843 9844 9845 9846 9847 9848
            for (int tag = 0; tag < (stbInfo->tagCount - 1);
                    tag ++ ) {
                pstr += sprintf(pstr, ",?");
            }
            pstr += sprintf(pstr, ") VALUES(?");
        } else {
            pstr += sprintf(pstr, "INSERT INTO ? VALUES(?");
        }

9849 9850 9851
        int columnCount = (stbInfo)?
            stbInfo->columnCount:
            g_args.columnCount;
9852 9853 9854 9855 9856 9857 9858

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

        debugPrint("%s() LN%d, stmtBuffer: %s", __func__, __LINE__, stmtBuffer);
9859 9860 9861
#if STMT_BIND_PARAM_BATCH == 1
        parseSamplefileToStmtBatch(stbInfo);
#endif
9862 9863
    }

9864 9865 9866
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
        pThreadInfo->threadID = i;
9867

9868 9869
        tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
        pThreadInfo->time_precision = timePrec;
9870
        pThreadInfo->stbInfo = stbInfo;
9871

9872
        pThreadInfo->start_time = startTime;
9873 9874
        pThreadInfo->minDelay = UINT64_MAX;

9875 9876
        if ((NULL == stbInfo) ||
                (stbInfo->iface != REST_IFACE)) {
9877 9878 9879 9880 9881
            //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) {
9882
                free(infos);
9883
                errorPrint2(
9884 9885 9886
                        "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n",
                        __func__, __LINE__,
                        taos_errstr(NULL));
9887
                exit(EXIT_FAILURE);
9888
            }
9889

9890
            if ((g_args.iface == STMT_IFACE)
9891 9892
                    || ((stbInfo)
                        && (stbInfo->iface == STMT_IFACE))) {
9893

9894 9895
                pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos);
                if (NULL == pThreadInfo->stmt) {
9896 9897
                    free(pids);
                    free(infos);
9898
                    errorPrint2(
9899 9900 9901
                            "%s() LN%d, failed init stmt, reason: %s\n",
                            __func__, __LINE__,
                            taos_errstr(NULL));
9902
                    exit(EXIT_FAILURE);
9903
                }
9904

9905
                if (0 != taos_stmt_prepare(pThreadInfo->stmt, stmtBuffer, 0)) {
9906 9907
                    free(pids);
                    free(infos);
9908
                    free(stmtBuffer);
9909
                    errorPrint2("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n",
9910 9911
                            ret, taos_stmt_errstr(pThreadInfo->stmt));
                    exit(EXIT_FAILURE);
9912
                }
9913
                pThreadInfo->bind_ts = malloc(sizeof(int64_t));
9914 9915

                if (stbInfo) {
9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928
#if STMT_BIND_PARAM_BATCH == 1
                    parseStbSampleToStmtBatchForThread(
                            pThreadInfo, stbInfo, timePrec, batch);
#else
                    parseStbSampleToStmt(pThreadInfo, stbInfo, timePrec);
#endif
                } else {
#if STMT_BIND_PARAM_BATCH == 1
                    parseNtbSampleToStmtBatchForThread(
                            pThreadInfo, timePrec, batch);
#else
                    parseNtbSampleToStmt(pThreadInfo, timePrec);
#endif
9929
                }
9930 9931
            }
        } else {
9932
            pThreadInfo->taos = NULL;
9933
        }
9934

9935 9936
        /*    if ((NULL == stbInfo)
              || (0 == stbInfo->multiThreadWriteOneTbl)) {
9937 9938 9939 9940 9941 9942 9943
              */
        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;
9944
              pThreadInfo->ntables = stbInfo->childTblCount;
9945 9946 9947 9948 9949 9950 9951 9952
              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);
9953
        }
9954 9955
    }

9956 9957
    free(stmtBuffer);

9958
    int64_t start = taosGetTimestampUs();
9959

9960 9961
    for (int i = 0; i < threads; i++) {
        pthread_join(pids[i], NULL);
9962
    }
H
Hui Li 已提交
9963

9964 9965 9966 9967 9968
    uint64_t totalDelay = 0;
    uint64_t maxDelay = 0;
    uint64_t minDelay = UINT64_MAX;
    uint64_t cntDelay = 1;
    double  avgDelay = 0;
9969

9970 9971
    for (int i = 0; i < threads; i++) {
        threadInfo *pThreadInfo = infos + i;
9972

9973 9974 9975
        tsem_destroy(&(pThreadInfo->lock_sem));
        taos_close(pThreadInfo->taos);

9976 9977 9978
        if (pThreadInfo->stmt) {
            taos_stmt_close(pThreadInfo->stmt);
        }
9979

9980
        tmfree((char *)pThreadInfo->bind_ts);
9981
#if STMT_BIND_PARAM_BATCH == 1
9982 9983 9984 9985
        tmfree((char *)pThreadInfo->bind_ts_array);
        tmfree(pThreadInfo->bindParams);
        tmfree(pThreadInfo->is_null);
#else
9986
        if (pThreadInfo->sampleBindArray) {
9987
            for (int k = 0; k < MAX_SAMPLES; k++) {
9988 9989 9990
                uintptr_t *tmp = (uintptr_t *)(*(uintptr_t *)(
                            pThreadInfo->sampleBindArray
                            + sizeof(uintptr_t *) * k));
9991 9992 9993 9994
                int columnCount = (pThreadInfo->stbInfo)?
                    pThreadInfo->stbInfo->columnCount:
                    g_args.columnCount;
                for (int c = 1; c < columnCount + 1; c++) {
9995 9996 9997 9998 9999 10000 10001 10002
                    TAOS_BIND *bind = (TAOS_BIND *)((char *)tmp + (sizeof(TAOS_BIND) * c));
                    if (bind)
                        tmfree(bind->buffer);
                }
                tmfree((char *)tmp);
            }
            tmfree(pThreadInfo->sampleBindArray);
        }
10003
#endif
10004

10005 10006 10007 10008
        debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
                __func__, __LINE__,
                pThreadInfo->threadID, pThreadInfo->totalInsertRows,
                pThreadInfo->totalAffectedRows);
10009 10010 10011
        if (stbInfo) {
            stbInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
            stbInfo->totalInsertRows += pThreadInfo->totalInsertRows;
10012 10013 10014 10015
        } else {
            g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
            g_args.totalInsertRows += pThreadInfo->totalInsertRows;
        }
H
Hui Li 已提交
10016

10017 10018 10019 10020 10021
        totalDelay  += pThreadInfo->totalDelay;
        cntDelay   += pThreadInfo->cntDelay;
        if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
        if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
    }
10022

10023 10024
    if (cntDelay == 0)    cntDelay = 1;
    avgDelay = (double)totalDelay / cntDelay;
10025

10026
    int64_t end = taosGetTimestampUs();
10027
    int64_t t = end - start;
10028
    if (0 == t) t = 1;
10029

10030
    double tInMs = (double) t / 1000000.0;
10031

10032
    if (stbInfo) {
10033
        fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
10034 10035
                tInMs, stbInfo->totalInsertRows,
                stbInfo->totalAffectedRows,
10036
                threads, db_name, stbInfo->stbName,
10037
                (double)(stbInfo->totalInsertRows/tInMs));
10038 10039 10040

        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
10041
                    "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
10042 10043
                    tInMs, stbInfo->totalInsertRows,
                    stbInfo->totalAffectedRows,
10044
                    threads, db_name, stbInfo->stbName,
10045
                    (double)(stbInfo->totalInsertRows/tInMs));
10046 10047
        }
    } else {
10048
        fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
10049 10050 10051
                tInMs, g_args.totalInsertRows,
                g_args.totalAffectedRows,
                threads, db_name,
10052
                (double)(g_args.totalInsertRows/tInMs));
10053 10054
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
10055
                    "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
10056 10057 10058
                    tInMs, g_args.totalInsertRows,
                    g_args.totalAffectedRows,
                    threads, db_name,
10059
                    (double)(g_args.totalInsertRows/tInMs));
10060
        }
10061
    }
10062

10063 10064 10065 10066
    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);
10067
    if (g_fpOfInsertResult) {
10068 10069 10070 10071
        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);
10072
    }
10073

10074
    //taos_close(taos);
10075

10076 10077
    free(pids);
    free(infos);
H
Hui Li 已提交
10078 10079
}

10080
static void *queryNtableAggrFunc(void *sarg) {
10081 10082
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    TAOS *taos = pThreadInfo->taos;
10083
    setThreadName("queryNtableAggrFunc");
10084 10085 10086
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);

10087
    uint64_t startTime = pThreadInfo->start_time;
10088 10089 10090
    char *tb_prefix = pThreadInfo->tb_prefix;
    FILE *fp = fopen(pThreadInfo->filePath, "a");
    if (NULL == fp) {
10091
        errorPrint2("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
10092
        free(command);
10093
        return NULL;
10094
    }
H
hzcheng 已提交
10095

10096
    int64_t insertRows;
10097
    /*  if (pThreadInfo->stbInfo) {
10098
        insertRows = pThreadInfo->stbInfo->insertRows; //  nrecords_per_table;
10099 10100
        } else {
        */
10101
    insertRows = g_args.insertRows;
10102 10103
    //  }

10104
    int64_t ntables = pThreadInfo->ntables; // pThreadInfo->end_table_to - pThreadInfo->start_table_from + 1;
10105
    int64_t totalData = insertRows * ntables;
10106 10107 10108 10109
    bool aggr_func = g_Dbs.aggr_func;

    char **aggreFunc;
    int n;
10110

10111 10112 10113 10114 10115 10116 10117 10118 10119
    if (g_args.demo_mode) {
        aggreFunc = g_aggreFuncDemo;
        n = aggr_func?(sizeof(g_aggreFuncDemo) / sizeof(g_aggreFuncDemo[0])) : 2;
    } else {
        aggreFunc = g_aggreFunc;
        n = aggr_func?(sizeof(g_aggreFunc) / sizeof(g_aggreFunc[0])) : 2;
    }

    if (!aggr_func) {
10120 10121 10122 10123 10124 10125 10126 10127
        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;
10128 10129
        for (int64_t i = 0; i < ntables; i++) {
            sprintf(command, "SELECT %s FROM %s%"PRId64" WHERE ts>= %" PRIu64,
10130
                    aggreFunc[j], tb_prefix, i, startTime);
10131

10132 10133 10134
            double t = taosGetTimestampUs();
            debugPrint("%s() LN%d, sql command: %s\n",
                    __func__, __LINE__, command);
10135 10136 10137 10138
            TAOS_RES *pSql = taos_query(taos, command);
            int32_t code = taos_errno(pSql);

            if (code != 0) {
10139
                errorPrint2("Failed to query:%s\n", taos_errstr(pSql));
10140 10141 10142
                taos_free_result(pSql);
                taos_close(taos);
                fclose(fp);
10143
                free(command);
10144 10145
                return NULL;
            }
H
hzcheng 已提交
10146

10147 10148 10149
            while(taos_fetch_row(pSql) != NULL) {
                count++;
            }
H
hzcheng 已提交
10150

10151
            t = taosGetTimestampUs() - t;
10152 10153 10154 10155
            totalT += t;

            taos_free_result(pSql);
        }
H
hzcheng 已提交
10156

10157
        fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
10158 10159 10160
                aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
                (double)(ntables * insertRows) / totalT, totalT / 1000000);
        printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT / 1000000);
10161 10162 10163
    }
    fprintf(fp, "\n");
    fclose(fp);
10164
    free(command);
10165
    return NULL;
H
hzcheng 已提交
10166 10167
}

10168
static void *queryStableAggrFunc(void *sarg) {
10169 10170
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    TAOS *taos = pThreadInfo->taos;
10171
    setThreadName("queryStableAggrFunc");
10172 10173 10174
    char *command = calloc(1, BUFFER_SIZE);
    assert(command);

10175 10176 10177
    FILE *fp = fopen(pThreadInfo->filePath, "a");
    if (NULL == fp) {
        printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
10178
        free(command);
10179 10180
        return NULL;
    }
10181

10182
    int64_t insertRows = pThreadInfo->stbInfo->insertRows;
10183
    int64_t ntables = pThreadInfo->ntables; // pThreadInfo->end_table_to - pThreadInfo->start_table_from + 1;
10184
    int64_t totalData = insertRows * ntables;
10185 10186 10187 10188
    bool aggr_func = g_Dbs.aggr_func;

    char **aggreFunc;
    int n;
H
hzcheng 已提交
10189

10190 10191 10192 10193 10194 10195 10196 10197 10198
    if (g_args.demo_mode) {
        aggreFunc = g_aggreFuncDemo;
        n = aggr_func?(sizeof(g_aggreFuncDemo) / sizeof(g_aggreFuncDemo[0])) : 2;
    } else {
        aggreFunc = g_aggreFunc;
        n = aggr_func?(sizeof(g_aggreFunc) / sizeof(g_aggreFunc[0])) : 2;
    }

    if (!aggr_func) {
10199 10200
        printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n");
    }
10201

10202 10203
    printf("%"PRId64" records:\n", totalData);
    fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
10204

10205 10206 10207
    for (int j = 0; j < n; j++) {
        char condition[COND_BUF_LEN] = "\0";
        char tempS[64] = "\0";
H
hzcheng 已提交
10208

10209
        int64_t m = 10 < ntables ? 10 : ntables;
H
hzcheng 已提交
10210

10211 10212
        for (int64_t i = 1; i <= m; i++) {
            if (i == 1) {
10213 10214 10215 10216 10217
                if (g_args.demo_mode) {
                    sprintf(tempS, "groupid = %"PRId64"", i);
                } else {
                    sprintf(tempS, "t0 = %"PRId64"", i);
                }
10218
            } else {
10219 10220 10221 10222 10223
                if (g_args.demo_mode) {
                    sprintf(tempS, " or groupid = %"PRId64" ", i);
                } else {
                    sprintf(tempS, " or t0 = %"PRId64" ", i);
                }
10224 10225
            }
            strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
10226

10227
            sprintf(command, "SELECT %s FROM meters WHERE %s", aggreFunc[j], condition);
H
hzcheng 已提交
10228

10229
            printf("Where condition: %s\n", condition);
10230 10231 10232

            debugPrint("%s() LN%d, sql command: %s\n",
                    __func__, __LINE__, command);
10233
            fprintf(fp, "%s\n", command);
H
hzcheng 已提交
10234

10235
            double t = taosGetTimestampUs();
H
hzcheng 已提交
10236

10237 10238
            TAOS_RES *pSql = taos_query(taos, command);
            int32_t code = taos_errno(pSql);
S
Shuaiqiang Chang 已提交
10239

10240
            if (code != 0) {
10241
                errorPrint2("Failed to query:%s\n", taos_errstr(pSql));
10242 10243 10244
                taos_free_result(pSql);
                taos_close(taos);
                fclose(fp);
10245
                free(command);
10246 10247 10248 10249 10250 10251
                return NULL;
            }
            int count = 0;
            while(taos_fetch_row(pSql) != NULL) {
                count++;
            }
10252
            t = taosGetTimestampUs() - t;
H
hzcheng 已提交
10253

10254
            fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
10255 10256
                    ntables * insertRows / (t / 1000), t);
            printf("select %10s took %.6f second(s)\n\n", aggreFunc[j], t / 1000000);
H
hzcheng 已提交
10257

10258 10259 10260
            taos_free_result(pSql);
        }
        fprintf(fp, "\n");
H
hzcheng 已提交
10261
    }
10262
    fclose(fp);
10263
    free(command);
10264

10265
    return NULL;
H
hzcheng 已提交
10266 10267
}

10268 10269
static void prompt()
{
10270 10271 10272 10273
    if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
    }
10274
}
H
Hui Li 已提交
10275

10276
static int insertTestProcess() {
10277

10278 10279 10280
    setupForAnsiEscape();
    int ret = printfInsertMeta();
    resetAfterAnsiEscape();
10281

10282 10283
    if (ret == -1)
        exit(EXIT_FAILURE);
10284

10285 10286 10287
    debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
    g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
    if (NULL == g_fpOfInsertResult) {
10288
        errorPrint("Failed to open %s for save result\n", g_Dbs.resultFile);
10289 10290
        return -1;
    }
10291

10292 10293
    if (g_fpOfInsertResult)
        printfInsertMetaToFile(g_fpOfInsertResult);
10294

10295
    prompt();
10296

10297
    init_rand_data();
10298

10299
    // create database and super tables
10300 10301 10302 10303
    char *cmdBuffer = calloc(1, BUFFER_SIZE);
    assert(cmdBuffer);

    if(createDatabasesAndStables(cmdBuffer) != 0) {
10304 10305
        if (g_fpOfInsertResult)
            fclose(g_fpOfInsertResult);
10306
        free(cmdBuffer);
10307 10308
        return -1;
    }
10309
    free(cmdBuffer);
10310

10311
    // pretreatment
10312 10313 10314 10315 10316
    if (prepareSampleData() != 0) {
        if (g_fpOfInsertResult)
            fclose(g_fpOfInsertResult);
        return -1;
    }
10317

10318 10319
    double start;
    double end;
10320

10321
    if (g_totalChildTables > 0) {
10322 10323
        fprintf(stderr,
                "creating %"PRId64" table(s) with %d thread(s)\n\n",
10324
                g_totalChildTables, g_Dbs.threadCountForCreateTbl);
10325 10326 10327
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
                "creating %"PRId64" table(s) with %d thread(s)\n\n",
10328
                g_totalChildTables, g_Dbs.threadCountForCreateTbl);
10329 10330 10331 10332 10333 10334 10335 10336
        }

        // create child tables
        start = taosGetTimestampMs();
        createChildTables();
        end = taosGetTimestampMs();

        fprintf(stderr,
10337
                "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n",
10338
                (end - start)/1000.0, g_totalChildTables,
10339
                g_Dbs.threadCountForCreateTbl, g_actualChildTables);
10340 10341
        if (g_fpOfInsertResult) {
            fprintf(g_fpOfInsertResult,
10342
                "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n",
10343
                (end - start)/1000.0, g_totalChildTables,
10344
                g_Dbs.threadCountForCreateTbl, g_actualChildTables);
10345
        }
10346
    }
10347

10348 10349 10350 10351 10352 10353
    // 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++) {
10354

10355
                    SSuperTable* stbInfo = &g_Dbs.db[i].superTbls[j];
10356

10357
                    if (stbInfo && (stbInfo->insertRows > 0)) {
10358 10359 10360 10361
                        startMultiThreadInsertData(
                                g_Dbs.threadCount,
                                g_Dbs.db[i].dbName,
                                g_Dbs.db[i].dbCfg.precision,
10362
                                stbInfo);
10363 10364 10365 10366
                    }
                }
            }
        } else {
10367
            startMultiThreadInsertData(
10368 10369 10370 10371
                    g_Dbs.threadCount,
                    g_Dbs.db[i].dbName,
                    g_Dbs.db[i].dbCfg.precision,
                    NULL);
10372
        }
H
Hui Li 已提交
10373
    }
10374
    //end = taosGetTimestampMs();
10375

10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386
    //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;
10387 10388
}

10389
static void *specifiedTableQuery(void *sarg) {
10390
    threadInfo *pThreadInfo = (threadInfo *)sarg;
10391

10392
    setThreadName("specTableQuery");
10393

10394 10395 10396 10397 10398 10399 10400 10401
    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) {
10402
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
10403 10404 10405 10406 10407
                    pThreadInfo->threadID, taos_errstr(NULL));
            return NULL;
        } else {
            pThreadInfo->taos = taos;
        }
10408 10409
    }

10410 10411 10412 10413
    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);
10414
        errorPrint("use database %s failed!\n\n",
10415
                g_queryInfo.dbName);
10416 10417
        return NULL;
    }
10418

10419 10420
    uint64_t st = 0;
    uint64_t et = 0;
10421

10422
    uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
10423

10424 10425 10426
    uint64_t totalQueried = 0;
    uint64_t lastPrintTime = taosGetTimestampMs();
    uint64_t startTs = taosGetTimestampMs();
10427

10428 10429
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
        sprintf(pThreadInfo->filePath, "%s-%d",
10430 10431
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
10432 10433
    }

10434 10435 10436 10437 10438 10439 10440
    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();
10441

10442 10443
        selectAndGetResult(pThreadInfo,
                g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
10444

10445 10446 10447
        et = taosGetTimestampMs();
        printf("=thread[%"PRId64"] use %s complete one sql, Spent %10.3f s\n",
                taosGetSelfPthreadId(), g_queryInfo.queryMode, (et - st)/1000.0);
10448

10449 10450
        totalQueried ++;
        g_queryInfo.specifiedQueryInfo.totalQueried ++;
10451

10452 10453 10454
        uint64_t  currentPrintTime = taosGetTimestampMs();
        uint64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
10455
            debugPrint("%s() LN%d, endTs=%"PRIu64" ms, startTs=%"PRIu64" ms\n",
10456 10457
                    __func__, __LINE__, endTs, startTs);
            printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
10458 10459
                    pThreadInfo->threadID,
                    totalQueried,
10460
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
10461 10462
            lastPrintTime = currentPrintTime;
        }
10463
    }
10464
    return NULL;
10465
}
H
Hui Li 已提交
10466

10467
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
10468
    char sourceString[32] = "xxxx";
10469
    char subTblName[TSDB_TABLE_NAME_LEN];
10470 10471 10472
    sprintf(subTblName, "%s.%s",
            g_queryInfo.dbName,
            g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
10473

10474
    //printf("inSql: %s\n", inSql);
10475

10476 10477 10478 10479 10480 10481 10482
    char* pos = strstr(inSql, sourceString);
    if (0 == pos) {
        return;
    }

    tstrncpy(outSql, inSql, pos - inSql + 1);
    //printf("1: %s\n", outSql);
10483
    strncat(outSql, subTblName, BUFFER_SIZE - 1);
10484
    //printf("2: %s\n", outSql);
10485
    strncat(outSql, pos+strlen(sourceString), BUFFER_SIZE - 1);
10486
    //printf("3: %s\n", outSql);
H
Hui Li 已提交
10487 10488
}

10489
static void *superTableQuery(void *sarg) {
10490 10491 10492
    char *sqlstr = calloc(1, BUFFER_SIZE);
    assert(sqlstr);

10493
    threadInfo *pThreadInfo = (threadInfo *)sarg;
10494

10495
    setThreadName("superTableQuery");
10496

10497 10498 10499 10500 10501 10502 10503 10504 10505 10506
    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));
10507
            free(sqlstr);
10508 10509 10510 10511
            return NULL;
        } else {
            pThreadInfo->taos = taos;
        }
10512
    }
10513

10514 10515
    uint64_t st = 0;
    uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
10516

10517 10518 10519
    uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
    uint64_t totalQueried = 0;
    uint64_t  startTs = taosGetTimestampMs();
H
Hui Li 已提交
10520

10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531
    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++) {
10532
                memset(sqlstr, 0, BUFFER_SIZE);
10533 10534 10535 10536 10537 10538 10539
                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);
10540

10541 10542
                totalQueried++;
                g_queryInfo.superQueryInfo.totalQueried ++;
10543

10544 10545 10546 10547 10548 10549 10550 10551 10552 10553
                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;
                }
            }
10554
        }
10555 10556 10557 10558 10559 10560
        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 已提交
10561
    }
10562

10563
    free(sqlstr);
10564
    return NULL;
10565 10566
}

10567
static int queryTestProcess() {
10568

10569 10570 10571
    setupForAnsiEscape();
    printfQueryMeta();
    resetAfterAnsiEscape();
10572

10573 10574 10575 10576 10577 10578 10579
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
            g_queryInfo.user,
            g_queryInfo.password,
            NULL,
            g_queryInfo.port);
    if (taos == NULL) {
10580
        errorPrint("Failed to connect to TDengine, reason:%s\n",
10581
                taos_errstr(NULL));
10582
        exit(EXIT_FAILURE);
10583
    }
10584

10585 10586 10587
    if (0 != g_queryInfo.superQueryInfo.sqlCount) {
        getAllChildNameOfSuperTable(taos,
                g_queryInfo.dbName,
10588
                g_queryInfo.superQueryInfo.stbName,
10589 10590 10591
                &g_queryInfo.superQueryInfo.childTblName,
                &g_queryInfo.superQueryInfo.childTblCount);
    }
10592

10593
    prompt();
10594

10595 10596 10597
    if (g_args.debug_print || g_args.verbose_print) {
        printfQuerySystemInfo(taos);
    }
10598

10599 10600 10601
    if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
        if (convertHostToServAddr(
                    g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
10602
            ERROR_EXIT("convert host to server address");
10603
    }
10604

10605 10606 10607 10608 10609
    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;
10610

10611
    uint64_t startTs = taosGetTimestampMs();
10612

10613
    if ((nSqlCount > 0) && (nConcurrent > 0)) {
10614

10615 10616
        pids  = calloc(1, nConcurrent * nSqlCount * sizeof(pthread_t));
        infos = calloc(1, nConcurrent * nSqlCount * sizeof(threadInfo));
10617

10618 10619 10620 10621
        if ((NULL == pids) || (NULL == infos)) {
            taos_close(taos);
            ERROR_EXIT("memory allocation failed for create threads\n");
        }
10622

10623 10624 10625 10626 10627 10628 10629 10630 10631
        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)) {

10632 10633
                    char sqlStr[TSDB_DB_NAME_LEN + 5];
                    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
10634 10635 10636 10637
                    if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
                        taos_close(taos);
                        free(infos);
                        free(pids);
10638
                        errorPrint2("use database %s failed!\n\n",
10639 10640 10641
                                g_queryInfo.dbName);
                        return -1;
                    }
10642
                }
10643

10644
                pThreadInfo->taos = NULL;// workaround to use separate taos connection;
10645

10646 10647 10648
                pthread_create(pids + seq, NULL, specifiedTableQuery,
                        pThreadInfo);
            }
10649
        }
10650 10651
    } else {
        g_queryInfo.specifiedQueryInfo.concurrent = 0;
10652 10653
    }

10654
    taos_close(taos);
10655

10656 10657 10658 10659 10660 10661 10662
    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));
10663

10664 10665 10666
        if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
            free(infos);
            free(pids);
10667

10668 10669
            ERROR_EXIT("memory allocation failed for create threads\n");
        }
10670

10671 10672
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
10673

10674 10675 10676 10677 10678
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
10679

10680 10681 10682 10683
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
10684

10685 10686 10687 10688
        uint64_t tableFrom = 0;
        for (int i = 0; i < threads; i++) {
            threadInfo *pThreadInfo = infosOfSub + i;
            pThreadInfo->threadID = i;
10689

10690 10691 10692 10693
            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;
10694
            pThreadInfo->taos = NULL; // workaround to use separate taos connection;
10695 10696
            pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
        }
10697

10698 10699 10700 10701
        g_queryInfo.superQueryInfo.threadCnt = threads;
    } else {
        g_queryInfo.superQueryInfo.threadCnt = 0;
    }
10702

10703 10704 10705 10706 10707 10708
    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);
            }
        }
10709
    }
S
Shuaiqiang Chang 已提交
10710

10711 10712
    tmfree((char*)pids);
    tmfree((char*)infos);
10713

10714 10715 10716
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
        pthread_join(pidsOfSub[i], NULL);
    }
H
Hui Li 已提交
10717

10718 10719
    tmfree((char*)pidsOfSub);
    tmfree((char*)infosOfSub);
10720

10721
    //  taos_close(taos);// workaround to use separate taos connection;
10722
    uint64_t endTs = taosGetTimestampMs();
10723

10724 10725
    uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
        g_queryInfo.superQueryInfo.totalQueried;
10726

10727 10728 10729 10730
    fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
            totalQueried,
            (double)(totalQueried/((endTs-startTs)/1000.0)));
    return 0;
10731 10732
}

10733 10734
static void stable_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
10735
    if (res == NULL || taos_errno(res) != 0) {
10736
        errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
10737 10738 10739
                __func__, __LINE__, code, taos_errstr(res));
        return;
    }
10740

10741 10742
    if (param)
        fetchResult(res, (threadInfo *)param);
10743
    // tao_unsubscribe() will free result.
10744 10745 10746 10747
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
10748
    if (res == NULL || taos_errno(res) != 0) {
10749
        errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
10750 10751 10752
                __func__, __LINE__, code, taos_errstr(res));
        return;
    }
10753

10754 10755
    if (param)
        fetchResult(res, (threadInfo *)param);
10756
    // tao_unsubscribe() will free result.
H
hzcheng 已提交
10757 10758
}

10759
static TAOS_SUB* subscribeImpl(
10760 10761 10762 10763
        QUERY_CLASS class,
        threadInfo *pThreadInfo,
        char *sql, char* topic, bool restart, uint64_t interval)
{
10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781 10782 10783 10784 10785 10786 10787
    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) {
10788
        errorPrint2("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
10789 10790 10791 10792
        return NULL;
    }

    return tsub;
10793
}
H
hzcheng 已提交
10794

10795
static void *superSubscribe(void *sarg) {
10796
    threadInfo *pThreadInfo = (threadInfo *)sarg;
10797 10798 10799
    char *subSqlStr = calloc(1, BUFFER_SIZE);
    assert(subSqlStr);

10800 10801 10802
    TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
    uint64_t tsubSeq;

10803 10804
    setThreadName("superSub");

10805
    if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
10806
        free(subSqlStr);
10807 10808
        errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
                pThreadInfo->ntables, MAX_QUERY_SQL_COUNT);
10809
        exit(EXIT_FAILURE);
10810
    }
10811

10812
    if (pThreadInfo->taos == NULL) {
10813 10814 10815 10816 10817 10818
        pThreadInfo->taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                g_queryInfo.dbName,
                g_queryInfo.port);
        if (pThreadInfo->taos == NULL) {
10819
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
10820
                    pThreadInfo->threadID, taos_errstr(NULL));
10821
            free(subSqlStr);
10822 10823
            return NULL;
        }
10824 10825
    }

10826 10827
    char sqlStr[TSDB_DB_NAME_LEN + 5];
    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
10828 10829
    if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
        taos_close(pThreadInfo->taos);
10830
        errorPrint2("use database %s failed!\n\n",
10831
                g_queryInfo.dbName);
10832
        free(subSqlStr);
10833 10834
        return NULL;
    }
10835

10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846
    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);
10847
        memset(subSqlStr, 0, BUFFER_SIZE);
10848 10849
        replaceChildTblName(
                g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
10850
                subSqlStr, i);
10851 10852 10853 10854 10855
        if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
            sprintf(pThreadInfo->filePath, "%s-%d",
                    g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                    pThreadInfo->threadID);
        }
10856

10857 10858
        verbosePrint("%s() LN%d, [%d] subSqlStr: %s\n",
                __func__, __LINE__, pThreadInfo->threadID, subSqlStr);
10859 10860
        tsub[tsubSeq] = subscribeImpl(
                STABLE_CLASS,
10861
                pThreadInfo, subSqlStr, topic,
10862 10863 10864 10865
                g_queryInfo.superQueryInfo.subscribeRestart,
                g_queryInfo.superQueryInfo.subscribeInterval);
        if (NULL == tsub[tsubSeq]) {
            taos_close(pThreadInfo->taos);
10866
            free(subSqlStr);
10867 10868 10869
            return NULL;
        }
    }
10870

10871 10872 10873 10874 10875 10876
    // 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;
10877

10878
    uint64_t st = 0, et = 0;
10879

10880 10881 10882 10883
    while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
            || (g_queryInfo.superQueryInfo.endAfterConsume >
                consumed[pThreadInfo->end_table_to
                - pThreadInfo->start_table_from])) {
10884

10885 10886 10887 10888 10889 10890 10891 10892 10893 10894 10895 10896 10897 10898 10899 10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922
        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,
10923
                            pThreadInfo, subSqlStr, topic,
10924 10925 10926 10927 10928
                            g_queryInfo.superQueryInfo.subscribeRestart,
                            g_queryInfo.superQueryInfo.subscribeInterval
                            );
                    if (NULL == tsub[tsubSeq]) {
                        taos_close(pThreadInfo->taos);
10929
                        free(subSqlStr);
10930 10931 10932 10933 10934 10935 10936 10937 10938 10939 10940
                        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);
10941

10942 10943
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
10944 10945
        tsubSeq = i - pThreadInfo->start_table_from;
        taos_unsubscribe(tsub[tsubSeq], 0);
H
hzcheng 已提交
10946
    }
10947

10948
    taos_close(pThreadInfo->taos);
10949
    free(subSqlStr);
10950
    return NULL;
H
hzcheng 已提交
10951 10952
}

10953
static void *specifiedSubscribe(void *sarg) {
10954 10955
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    //  TAOS_SUB*  tsub = NULL;
10956

10957
    setThreadName("specSub");
10958

10959
    if (pThreadInfo->taos == NULL) {
10960 10961 10962 10963 10964 10965
        pThreadInfo->taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                g_queryInfo.dbName,
                g_queryInfo.port);
        if (pThreadInfo->taos == NULL) {
10966
            errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n",
10967 10968 10969
                    pThreadInfo->threadID, taos_errstr(NULL));
            return NULL;
        }
10970 10971
    }

10972 10973
    char sqlStr[TSDB_DB_NAME_LEN + 5];
    sprintf(sqlStr, "USE %s", g_queryInfo.dbName);
10974 10975 10976 10977 10978 10979 10980 10981 10982 10983 10984
    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",
10985 10986
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
10987 10988 10989 10990 10991 10992 10993 10994 10995 10996 10997 10998 10999
    }
    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
11000

11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 11030 11031 11032 11033 11034 11035 11036 11037 11038 11039 11040 11041 11042 11043 11044 11045 11046 11047 11048 11049 11050 11051 11052 11053 11054 11055 11056
    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 已提交
11057 11058
}

11059
static int subscribeTestProcess() {
11060 11061 11062 11063 11064 11065 11066 11067 11068 11069
    setupForAnsiEscape();
    printfQueryMeta();
    resetAfterAnsiEscape();

    prompt();

    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
            g_queryInfo.user,
            g_queryInfo.password,
11070
            g_queryInfo.dbName,
11071 11072
            g_queryInfo.port);
    if (taos == NULL) {
11073
        errorPrint2("Failed to connect to TDengine, reason:%s\n",
11074
                taos_errstr(NULL));
11075
        exit(EXIT_FAILURE);
S
Shengliang Guan 已提交
11076
    }
11077

11078 11079 11080
    if (0 != g_queryInfo.superQueryInfo.sqlCount) {
        getAllChildNameOfSuperTable(taos,
                g_queryInfo.dbName,
11081
                g_queryInfo.superQueryInfo.stbName,
11082 11083
                &g_queryInfo.superQueryInfo.childTblName,
                &g_queryInfo.superQueryInfo.childTblCount);
S
Shengliang Guan 已提交
11084
    }
11085

11086
    taos_close(taos); // workaround to use separate taos connection;
11087 11088 11089 11090 11091 11092 11093 11094 11095

    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) {
11096
        debugPrint("%s() LN%d, specified query sqlCount %d.\n",
11097 11098 11099 11100
                __func__, __LINE__,
                g_queryInfo.specifiedQueryInfo.sqlCount);
    } else {
        if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
11101
            errorPrint2("%s() LN%d, specified query sqlCount %d.\n",
11102 11103
                    __func__, __LINE__,
                    g_queryInfo.specifiedQueryInfo.sqlCount);
11104
            exit(EXIT_FAILURE);
11105
        }
11106

11107
        pids  = calloc(
11108
                1,
11109 11110 11111 11112
                g_queryInfo.specifiedQueryInfo.sqlCount *
                g_queryInfo.specifiedQueryInfo.concurrent *
                sizeof(pthread_t));
        infos = calloc(
11113
                1,
11114 11115 11116 11117
                g_queryInfo.specifiedQueryInfo.sqlCount *
                g_queryInfo.specifiedQueryInfo.concurrent *
                sizeof(threadInfo));
        if ((NULL == pids) || (NULL == infos)) {
11118
            errorPrint2("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
11119
            exit(EXIT_FAILURE);
11120
        }
11121

11122 11123 11124 11125 11126 11127
        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;
11128
                pThreadInfo->taos = NULL;  // workaround to use separate taos connection;
11129 11130
                pthread_create(pids + seq, NULL, specifiedSubscribe, pThreadInfo);
            }
11131
        }
11132
    }
11133

11134 11135 11136 11137 11138 11139 11140 11141 11142 11143 11144 11145 11146 11147 11148 11149 11150 11151 11152
    //==== 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)) {
11153
                errorPrint2("%s() LN%d, malloc failed for create threads\n",
11154 11155
                        __func__, __LINE__);
                // taos_close(taos);
11156
                exit(EXIT_FAILURE);
11157
            }
11158

11159 11160
            int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
            int threads = g_queryInfo.superQueryInfo.threadCnt;
11161

11162 11163 11164 11165
            int64_t a = ntables / threads;
            if (a < 1) {
                threads = ntables;
                a = 1;
11166
            }
11167

11168 11169 11170 11171 11172 11173 11174 11175 11176 11177 11178 11179 11180 11181 11182 11183 11184
            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;
11185
                    pThreadInfo->taos = NULL; // workaround to use separate taos connection;
11186 11187 11188 11189
                    pthread_create(pidsOfStable + seq,
                            NULL, superSubscribe, pThreadInfo);
                }
            }
11190

11191 11192 11193 11194 11195 11196 11197
            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);
                }
11198 11199
            }
        }
11200
    }
11201

11202 11203 11204 11205 11206
    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);
        }
11207
    }
H
hzcheng 已提交
11208

11209 11210
    tmfree((char*)pids);
    tmfree((char*)infos);
H
hzcheng 已提交
11211

11212 11213 11214 11215
    tmfree((char*)pidsOfStable);
    tmfree((char*)infosOfStable);
    //   taos_close(taos);
    return 0;
H
hzcheng 已提交
11216 11217
}

11218
static void initOfInsertMeta() {
11219
    memset(&g_Dbs, 0, sizeof(SDbs));
11220

11221 11222 11223 11224
    // 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);
11225
    tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, SHELL_MAX_PASSWORD_LEN);
11226
    g_Dbs.threadCount = 2;
11227

11228
    g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
11229 11230
}

11231
static void initOfQueryMeta() {
11232
    memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
11233

11234 11235 11236 11237
    // 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);
11238
    tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, SHELL_MAX_PASSWORD_LEN);
L
Liu Tao 已提交
11239 11240
}

11241
static void setParaFromArg() {
11242 11243 11244 11245 11246
    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);
    }
11247

11248 11249 11250
    if (g_args.user) {
        tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
    }
11251

11252
    tstrncpy(g_Dbs.password, g_args.password, SHELL_MAX_PASSWORD_LEN);
L
Liu Tao 已提交
11253

11254 11255 11256
    if (g_args.port) {
        g_Dbs.port = g_args.port;
    }
11257

11258 11259
    g_Dbs.threadCount = g_args.nthreads;
    g_Dbs.threadCountForCreateTbl = g_args.nthreads;
11260

11261 11262
    g_Dbs.dbCount = 1;
    g_Dbs.db[0].drop = true;
L
Liu Tao 已提交
11263

11264 11265
    tstrncpy(g_Dbs.db[0].dbName, g_args.database, TSDB_DB_NAME_LEN);
    g_Dbs.db[0].dbCfg.replica = g_args.replica;
11266
    tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", SMALL_BUFF_LEN);
11267

11268
    tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
11269

11270
    g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
11271

11272
    g_Dbs.aggr_func = g_args.aggr_func;
11273

11274
    char dataString[TSDB_MAX_BYTES_PER_ROW];
11275 11276
    char *data_type = g_args.data_type;
    char **dataType = g_args.dataType;
L
Liu Tao 已提交
11277

11278
    memset(dataString, 0, TSDB_MAX_BYTES_PER_ROW);
H
hzcheng 已提交
11279

11280 11281 11282
    if ((data_type[0] == TSDB_DATA_TYPE_BINARY)
            || (data_type[0] == TSDB_DATA_TYPE_BOOL)
            || (data_type[0] == TSDB_DATA_TYPE_NCHAR)) {
11283
        g_Dbs.aggr_func = false;
11284
    }
11285

11286 11287
    if (g_args.use_metric) {
        g_Dbs.db[0].superTblCount = 1;
11288 11289 11290 11291
        tstrncpy(g_Dbs.db[0].superTbls[0].stbName, "meters", TSDB_TABLE_NAME_LEN);
        g_Dbs.db[0].superTbls[0].childTblCount = g_args.ntables;
        g_Dbs.threadCount = g_args.nthreads;
        g_Dbs.threadCountForCreateTbl = g_args.nthreads;
11292
        g_Dbs.asyncMode = g_args.async_mode;
11293

11294 11295 11296 11297 11298
        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,
11299 11300
                g_args.tb_prefix, TBNAME_PREFIX_LEN);
        tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", SMALL_BUFF_LEN);
11301

11302 11303 11304 11305 11306 11307 11308
        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);
11309
        g_Dbs.db[0].superTbls[0].timeStampStep = g_args.timestamp_step;
11310

11311
        g_Dbs.db[0].superTbls[0].insertRows = g_args.insertRows;
11312
        g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
11313

11314 11315
        g_Dbs.db[0].superTbls[0].columnCount = 0;
        for (int i = 0; i < MAX_NUM_COLUMNS; i++) {
11316
            if (data_type[i] == TSDB_DATA_TYPE_NULL) {
11317 11318
                break;
            }
11319

11320
            g_Dbs.db[0].superTbls[0].columns[i].data_type = data_type[i];
11321
            tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
11322
                    dataType[i], min(DATATYPE_BUFF_LEN, strlen(dataType[i]) + 1));
11323
            g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.binwidth;
11324 11325 11326
            g_Dbs.db[0].superTbls[0].columnCount++;
        }

11327 11328
        if (g_Dbs.db[0].superTbls[0].columnCount > g_args.columnCount) {
            g_Dbs.db[0].superTbls[0].columnCount = g_args.columnCount;
11329 11330
        } else {
            for (int i = g_Dbs.db[0].superTbls[0].columnCount;
11331 11332
                    i < g_args.columnCount; i++) {
                g_Dbs.db[0].superTbls[0].columns[i].data_type = TSDB_DATA_TYPE_INT;
11333
                tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
11334
                        "INT", min(DATATYPE_BUFF_LEN, strlen("INT") + 1));
11335 11336 11337 11338 11339 11340
                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,
11341
                "INT", min(DATATYPE_BUFF_LEN, strlen("INT") + 1));
11342 11343 11344
        g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;

        tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
11345
                "BINARY", min(DATATYPE_BUFF_LEN, strlen("BINARY") + 1));
11346
        g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.binwidth;
11347 11348
        g_Dbs.db[0].superTbls[0].tagCount = 2;
    } else {
11349
        g_Dbs.threadCountForCreateTbl = g_args.nthreads;
11350 11351
        g_Dbs.db[0].superTbls[0].tagCount = 0;
    }
11352 11353 11354 11355
}

/* Function to do regular expression check */
static int regexMatch(const char *s, const char *reg, int cflags) {
11356 11357 11358 11359 11360
    regex_t regex;
    char    msgbuf[100] = {0};

    /* Compile regular expression */
    if (regcomp(&regex, reg, cflags) != 0) {
11361
        ERROR_EXIT("Fail to compile regex\n");
11362 11363 11364 11365 11366 11367 11368 11369 11370 11371 11372 11373 11374
    }

    /* 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);
11375 11376
        printf("Regex match failed: %s\n", msgbuf);
        exit(EXIT_FAILURE);
11377 11378
    }

11379 11380 11381 11382
    return 0;
}

static int isCommentLine(char *line) {
11383
    if (line == NULL) return 1;
11384

11385
    return regexMatch(line, "^\\s*#.*", REG_EXTENDED);
11386 11387
}

11388
static void querySqlFile(TAOS* taos, char* sqlFile)
11389
{
11390 11391 11392 11393 11394
    FILE *fp = fopen(sqlFile, "r");
    if (fp == NULL) {
        printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
        return;
    }
11395

11396 11397 11398 11399 11400
    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;
11401

11402
    double t = taosGetTimestampMs();
11403

11404 11405 11406
    while((read_len = tgetline(&line, &line_len, fp)) != -1) {
        if (read_len >= TSDB_MAX_BYTES_PER_ROW) continue;
        line[--read_len] = '\0';
11407

11408 11409 11410
        if (read_len == 0 || isCommentLine(line)) {  // line starts with #
            continue;
        }
11411

11412 11413 11414 11415 11416 11417
        if (line[read_len - 1] == '\\') {
            line[read_len - 1] = ' ';
            memcpy(cmd + cmd_len, line, read_len);
            cmd_len += read_len;
            continue;
        }
11418

11419 11420
        memcpy(cmd + cmd_len, line, read_len);
        if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
11421
            errorPrint2("%s() LN%d, queryDbExec %s failed!\n",
11422 11423 11424 11425 11426 11427 11428 11429
                    __func__, __LINE__, cmd);
            tmfree(cmd);
            tmfree(line);
            tmfclose(fp);
            return;
        }
        memset(cmd, 0, TSDB_MAX_BYTES_PER_ROW);
        cmd_len = 0;
11430
    }
H
hzcheng 已提交
11431

11432 11433
    t = taosGetTimestampMs() - t;
    printf("run %s took %.6f second(s)\n\n", sqlFile, t);
11434

11435 11436 11437 11438
    tmfree(cmd);
    tmfree(line);
    tmfclose(fp);
    return;
H
hzcheng 已提交
11439 11440
}

11441
static void testMetaFile() {
11442
    if (INSERT_TEST == g_args.test_mode) {
11443 11444
        if (g_Dbs.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
11445

11446
        insertTestProcess();
11447

11448
    } else if (QUERY_TEST == g_args.test_mode) {
11449 11450
        if (g_queryInfo.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
11451

11452
        queryTestProcess();
11453

11454
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
11455 11456
        if (g_queryInfo.cfgDir[0])
            taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
11457

11458
        subscribeTestProcess();
11459

11460
    }  else {
11461
        ;
11462
    }
11463
}
11464

11465
static void queryAggrFunc() {
11466 11467 11468 11469 11470
    // query data

    pthread_t read_id;
    threadInfo *pThreadInfo = calloc(1, sizeof(threadInfo));
    assert(pThreadInfo);
11471
    pThreadInfo->start_time = DEFAULT_START_TIME;  // 2017-07-14 10:40:00.000
11472 11473 11474 11475 11476
    pThreadInfo->start_table_from = 0;

    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;
11477
        pThreadInfo->stbInfo = &g_Dbs.db[0].superTbls[0];
11478
        tstrncpy(pThreadInfo->tb_prefix,
11479
                g_Dbs.db[0].superTbls[0].childTblPrefix, TBNAME_PREFIX_LEN);
11480
    } else {
11481 11482
        pThreadInfo->ntables = g_args.ntables;
        pThreadInfo->end_table_to = g_args.ntables -1;
11483 11484 11485 11486 11487 11488 11489 11490 11491 11492
        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) {
11493
        free(pThreadInfo);
11494
        errorPrint2("Failed to connect to TDengine, reason:%s\n",
11495
                taos_errstr(NULL));
11496
        exit(EXIT_FAILURE);
11497 11498 11499 11500 11501
    }

    tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);

    if (!g_Dbs.use_metric) {
11502
        pthread_create(&read_id, NULL, queryNtableAggrFunc, pThreadInfo);
11503
    } else {
11504
        pthread_create(&read_id, NULL, queryStableAggrFunc, pThreadInfo);
11505 11506 11507
    }
    pthread_join(read_id, NULL);
    taos_close(pThreadInfo->taos);
11508
    free(pThreadInfo);
11509 11510
}

11511 11512
static void testCmdLine() {

11513 11514 11515
    if (strlen(configDir)) {
        wordexp_t full_path;
        if (wordexp(configDir, &full_path, 0) != 0) {
11516
            errorPrint("Invalid path %s\n", configDir);
11517 11518 11519 11520
            return;
        }
        taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
        wordfree(&full_path);
11521 11522
    }

11523 11524
    g_args.test_mode = INSERT_TEST;
    insertTestProcess();
11525

11526 11527 11528
    if (g_Dbs.aggr_func) {
        queryAggrFunc();
    }
11529 11530
}

11531
int main(int argc, char *argv[]) {
11532
    parse_args(argc, argv, &g_args);
11533

11534
    debugPrint("meta file: %s\n", g_args.metaFile);
11535

11536
    if (g_args.metaFile) {
11537
        g_totalChildTables = 0;
11538 11539
        initOfInsertMeta();
        initOfQueryMeta();
11540

11541 11542 11543 11544
        if (false == getInfoFromJsonFile(g_args.metaFile)) {
            printf("Failed to read %s\n", g_args.metaFile);
            return 1;
        }
11545

11546
        testMetaFile();
11547
    } else {
11548 11549 11550 11551 11552 11553 11554 11555 11556 11557 11558 11559
        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);
11560

11561 11562 11563
        } else {
            testCmdLine();
        }
11564

11565 11566 11567 11568 11569
        if (g_dupstr)
            free(g_dupstr);
    }

    return 0;
H
hzcheng 已提交
11570
}
11571