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

#include <argp.h>
#include <assert.h>
S
#1022  
slguan 已提交
18 19
#ifndef _ALPINE
  #include <error.h>
F
Frozen 已提交
20
#endif
H
hzcheng 已提交
21 22 23 24 25 26 27 28
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wordexp.h>
S
slguan 已提交
29
#include <iconv.h>
H
Hui Li 已提交
30
#include <time.h>
H
hzcheng 已提交
31

H
Hui Li 已提交
32
#include "os.h"
H
hzcheng 已提交
33
#include "taos.h"
H
Hui Li 已提交
34
#include "taosdef.h"
H
hzcheng 已提交
35
#include "taosmsg.h"
H
Hui Li 已提交
36
#include "tglobal.h"
H
hzcheng 已提交
37
#include "tsclient.h"
H
Hui Li 已提交
38
#include "tsdb.h"
H
hzcheng 已提交
39 40 41
#include "tutil.h"

#define COMMAND_SIZE 65536
H
Hui Li 已提交
42
//#define DEFAULT_DUMP_FILE "taosdump.sql"
S
Shengliang Guan 已提交
43

S
slguan 已提交
44 45 46 47 48
int  converStringToReadable(char *str, int size, char *buf, int bufsize);
int  convertNCharToReadable(char *str, int size, char *buf, int bufsize);
void taosDumpCharset(FILE *fp);
void taosLoadFileCharset(FILE *fp, char *fcharset);

H
hzcheng 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
typedef struct {
  short bytes;
  int8_t type;
} SOColInfo;

// -------------------------- SHOW DATABASE INTERFACE-----------------------
enum _show_db_index {
  TSDB_SHOW_DB_NAME_INDEX,
  TSDB_SHOW_DB_CREATED_TIME_INDEX,
  TSDB_SHOW_DB_VGROUPS_INDEX,
  TSDB_SHOW_DB_NTABLES_INDEX,
  TSDB_SHOW_DB_REPLICA_INDEX,
  TSDB_SHOW_DB_DAYS_INDEX,
  TSDB_SHOW_DB_KEEP_INDEX,
  TSDB_SHOW_DB_TABLES_INDEX,
  TSDB_SHOW_DB_ROWS_INDEX,
  TSDB_SHOW_DB_CACHE_INDEX,
  TSDB_SHOW_DB_ABLOCKS_INDEX,
  TSDB_SHOW_DB_TBLOCKS_INDEX,
  TSDB_SHOW_DB_CTIME_INDEX,
  TSDB_SHOW_DB_CLOG_INDEX,
  TSDB_SHOW_DB_COMP_INDEX,
  TSDB_MAX_SHOW_DB
};

S
slguan 已提交
74
// -----------------------------------------SHOW TABLES CONFIGURE -------------------------------------
H
hzcheng 已提交
75 76 77 78 79 80 81 82
enum _show_tables_index {
  TSDB_SHOW_TABLES_NAME_INDEX,
  TSDB_SHOW_TABLES_CREATED_TIME_INDEX,
  TSDB_SHOW_TABLES_COLUMNS_INDEX,
  TSDB_SHOW_TABLES_METRIC_INDEX,
  TSDB_MAX_SHOW_TABLES
};

S
slguan 已提交
83
// ---------------------------------- DESCRIBE METRIC CONFIGURE ------------------------------
H
hzcheng 已提交
84 85 86 87 88 89 90 91 92
enum _describe_table_index {
  TSDB_DESCRIBE_METRIC_FIELD_INDEX,
  TSDB_DESCRIBE_METRIC_TYPE_INDEX,
  TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
  TSDB_DESCRIBE_METRIC_NOTE_INDEX,
  TSDB_MAX_DESCRIBE_METRIC
};

typedef struct {
H
Hui Li 已提交
93
  char field[TSDB_COL_NAME_LEN + 1];
H
hzcheng 已提交
94 95
  char type[16];
  int length;
S
slguan 已提交
96
  char note[128];
H
hzcheng 已提交
97 98 99
} SColDes;

typedef struct {
H
Hui Li 已提交
100
  char name[TSDB_COL_NAME_LEN + 1];
H
hzcheng 已提交
101 102 103 104 105 106
  SColDes cols[];
} STableDef;

extern char version[];

typedef struct {
H
Hui Li 已提交
107
  char name[TSDB_DB_NAME_LEN + 1];
H
hzcheng 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121
  int32_t replica;
  int32_t days;
  int32_t keep;
  int32_t tables;
  int32_t rows;
  int32_t cache;
  int32_t ablocks;
  int32_t tblocks;
  int32_t ctime;
  int32_t clog;
  int32_t comp;
} SDbInfo;

typedef struct {
H
Hui Li 已提交
122 123
  char name[TSDB_TABLE_NAME_LEN + 1];
  char metric[TSDB_TABLE_NAME_LEN + 1];
H
hzcheng 已提交
124 125 126 127 128 129 130
} STableRecord;

typedef struct {
  bool isMetric;
  STableRecord tableRecord;
} STableRecordInfo;

H
Hui Li 已提交
131 132 133 134 135 136 137 138 139 140
typedef struct {
  pthread_t threadID;
  int32_t   threadIndex;
  int32_t   totalThreads;
  char      dbName[TSDB_TABLE_NAME_LEN + 1];
  void     *taosCon;
} SThreadParaObj;

static int64_t totalDumpOutRows = 0;

H
hzcheng 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154
SDbInfo **dbInfos = NULL;

const char *argp_program_version = version;
const char *argp_program_bug_address = "<support@taosdata.com>";

/* Program documentation. */
static char doc[] = "";
/* "Argp example #4 -- a program with somewhat more complicated\ */
/*         options\ */
/*         \vThis part of the documentation comes *after* the options;\ */
/*         note that the text is automatically filled, but it's possible\ */
/*         to force a line-break, e.g.\n<-- here."; */

/* A description of the arguments we accept. */
H
Hui Li 已提交
155
static char args_doc[] = "dbname [tbname ...]\n--databases dbname ...\n--all-databases\n-i inpath\n-o outpath";
H
hzcheng 已提交
156 157 158 159 160 161 162

/* Keys for options without short-options. */
#define OPT_ABORT 1 /* –abort */

/* The options we understand. */
static struct argp_option options[] = {
  // connection option
H
Hui Li 已提交
163 164 165 166 167 168
  {"host",          'h', "HOST",        0,  "Server host dumping data from. Default is localhost.",        0},
  {"user",          'u', "USER",        0,  "User name used to connect to server. Default is root.",       0},
  {"password",      'p', "PASSWORD",    0,  "User password to connect to server. Default is taosdata.",    0},
  {"port",          'P', "PORT",        0,  "Port to connect",                                             0},
  {"cversion",      'v', "CVERION",     0,  "client version",                                              0},
  {"mysqlFlag",     'q', "MYSQLFLAG",   0,  "mysqlFlag, Default is 0",                                     0},
H
hzcheng 已提交
169
  // input/output file
H
Hui Li 已提交
170 171 172 173
  {"outpath",       'o', "OUTPATH",     0,  "Output file path.",                                          1},
  {"inpath",        'i', "INPATH",      0,  "Input file path.",                                           1},
  {"config",        'c', "CONFIG_DIR",  0,  "Configure directory. Default is /etc/taos/taos.cfg.",        1},
  {"encode",        'e', "ENCODE",      0,  "Input file encoding.",                                       1},
H
hzcheng 已提交
174
  // dump unit options
H
Hui Li 已提交
175 176
  {"all-databases", 'A', 0,             0,  "Dump all databases.",                                         2},
  {"databases",     'B', 0,             0,  "Dump assigned databases",                                     2},
H
hzcheng 已提交
177
  // dump format options
H
Hui Li 已提交
178 179 180 181 182
  {"schemaonly",    's', 0,             0,  "Only dump schema.",                                           3},
  {"with-property", 'M', 0,             0,  "Dump schema with properties.",                                3},
  {"start-time",    'S', "START_TIME",  0,  "Start time to dump.",                                         3},
  {"end-time",      'E', "END_TIME",    0,  "End time to dump.",                                           3},
  {"data-batch",    'N', "DATA_BATCH",  0,  "Number of data point per insert statement. Default is 1.",    3},
H
Hui Li 已提交
183 184
  {"table-batch",   't', "TABLE_BATCH", 0,  "Number of table dumpout into one output file. Default is 1.", 3},
  {"thread_num",    'T', "THREAD_NUM",  0,  "Number of thread for dump in file. Default is 5.",            3},  
H
Hui Li 已提交
185
  {"allow-sys",     'a', 0,             0,  "Allow to dump sys database",                                  3},
H
hzcheng 已提交
186 187 188
  {0}};

/* Used by main to communicate with parse_opt. */
H
Hui Li 已提交
189
struct arguments {
H
hzcheng 已提交
190
  // connection option
H
Hui Li 已提交
191 192 193 194
  char    *host;
  char    *user;
  char    *password;
  uint16_t port;  
H
Hui Li 已提交
195
  char     cversion[12];
H
Hui Li 已提交
196
  uint16_t mysqlFlag;
H
hzcheng 已提交
197
  // output file
H
Hui Li 已提交
198 199 200
  char     outpath[TSDB_FILENAME_LEN+1];
  char     inpath[TSDB_FILENAME_LEN+1];
  char    *encode;
H
hzcheng 已提交
201
  // dump unit option
H
Hui Li 已提交
202 203
  bool     all_databases;
  bool     databases;
H
hzcheng 已提交
204
  // dump format option
H
Hui Li 已提交
205 206 207 208 209 210 211
  bool     schemaonly;
  bool     with_property;
  int64_t  start_time;
  int64_t  end_time;
  int32_t  data_batch;
  int32_t  table_batch; // num of table which will be dump into one output file.
  bool     allow_sys;
H
hzcheng 已提交
212
  // other options
H
Hui Li 已提交
213 214 215 216 217 218
  int32_t  thread_num;
  int      abort;
  char   **arg_list;
  int      arg_list_len;
  bool     isDumpIn;
};
H
hzcheng 已提交
219 220 221 222 223

/* Parse a single option. */
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
  /* Get the input argument from argp_parse, which we
     know is a pointer to our arguments structure. */
H
Hui Li 已提交
224
  struct arguments *arguments = state->input;
H
hzcheng 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
  wordexp_t full_path;

  switch (key) {
    // connection option
    case 'a':
      arguments->allow_sys = true;
      break;
    case 'h':
      arguments->host = arg;
      break;
    case 'u':
      arguments->user = arg;
      break;
    case 'p':
      arguments->password = arg;
      break;
    case 'P':
      arguments->port = atoi(arg);
      break;
H
Hui Li 已提交
244 245 246 247 248 249 250 251
    case 'q':
      arguments->mysqlFlag = atoi(arg);
      break;
    case 'v':
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid client vesion %s\n", arg);
        return -1;
      }
H
Hui Li 已提交
252
      tstrncpy(arguments->cversion, full_path.we_wordv[0], 11);
H
Hui Li 已提交
253 254 255
      wordfree(&full_path);
      break;
    // output file path
H
hzcheng 已提交
256 257 258 259 260
    case 'o':
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid path %s\n", arg);
        return -1;
      }
H
Hui Li 已提交
261
      tstrncpy(arguments->outpath, full_path.we_wordv[0], TSDB_FILENAME_LEN);
H
hzcheng 已提交
262 263 264 265 266 267 268 269
      wordfree(&full_path);
      break;
    case 'i':
      arguments->isDumpIn = true;
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid path %s\n", arg);
        return -1;
      }
H
Hui Li 已提交
270
      tstrncpy(arguments->inpath, full_path.we_wordv[0], TSDB_FILENAME_LEN);
H
hzcheng 已提交
271 272 273 274 275 276 277
      wordfree(&full_path);
      break;
    case 'c':
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid path %s\n", arg);
        return -1;
      }
H
Hui Li 已提交
278
      tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN);
H
hzcheng 已提交
279 280
      wordfree(&full_path);
      break;
S
slguan 已提交
281 282 283 284
    case 'e':
      arguments->encode = arg;
      break;
    // dump unit option
H
hzcheng 已提交
285 286 287 288 289 290
    case 'A':
      arguments->all_databases = true;
      break;
    case 'B':
      arguments->databases = true;
      break;
S
slguan 已提交
291
    // dump format option
H
hzcheng 已提交
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    case 's':
      arguments->schemaonly = true;
      break;
    case 'M':
      arguments->with_property = true;
      break;
    case 'S':
      // parse time here.
      arguments->start_time = atol(arg);
      break;
    case 'E':
      arguments->end_time = atol(arg);
      break;
    case 'N':
      arguments->data_batch = atoi(arg);
      break;
H
Hui Li 已提交
308
    case 't':
H
Hui Li 已提交
309 310
      arguments->table_batch = atoi(arg);
      break;
H
Hui Li 已提交
311
    case 'T':
H
Hui Li 已提交
312 313
      arguments->thread_num = atoi(arg);
      break;
H
hzcheng 已提交
314 315 316 317
    case OPT_ABORT:
      arguments->abort = 1;
      break;
    case ARGP_KEY_ARG:
H
Hui Li 已提交
318
      arguments->arg_list     = &state->argv[state->next - 1];
H
hzcheng 已提交
319
      arguments->arg_list_len = state->argc - state->next + 1;
H
Hui Li 已提交
320
      state->next             = state->argc;
H
hzcheng 已提交
321 322 323 324 325 326 327 328 329 330 331
      break;

    default:
      return ARGP_ERR_UNKNOWN;
  }
  return 0;
}

/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc};

H
Hui Li 已提交
332 333
int taosDumpOut(struct arguments *arguments);
int taosDumpIn(struct arguments *arguments);
H
hzcheng 已提交
334
void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp);
H
Hui Li 已提交
335 336 337 338 339 340 341 342 343
int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon);
int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon);
void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp);
void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp);
int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon);
int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon);
int taosCheckParam(struct arguments *arguments);
void taosFreeDbInfos();
static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t  numOfThread, char *dbName);
H
hzcheng 已提交
344

H
Hui Li 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
struct arguments tsArguments = {
  // connection option
  NULL, 
  "root", 
  "taosdata", 
  0,
  "",
  0,
  // outpath and inpath
  "", 
  "", 
  NULL,
  // dump unit option
  false, 
  false,
  // dump format option
  false, 
  false, 
  0, 
  INT64_MAX, 
  1,
  1,
  false,
  // other options
  5,
  0,
  NULL, 
  0, 
  false
};
H
hzcheng 已提交
375

H
Hui Li 已提交
376 377 378 379 380 381 382 383 384 385 386 387
int queryDB(TAOS *taos, char *command) {
  TAOS_RES *pSql = NULL;
  int32_t   code = -1;
    
  pSql = taos_query(taos, command);
  code = taos_errno(pSql);
  if (code) {
    fprintf(stderr, "sql error: %s, reason:%s\n", command, taos_errstr(pSql));
  } 
  taos_free_result(pSql);
  return code;
}
H
hzcheng 已提交
388 389 390 391 392

int main(int argc, char *argv[]) {

  /* Parse our arguments; every option seen by parse_opt will be
     reflected in arguments. */
H
Hui Li 已提交
393
  argp_parse(&argp, argc, argv, 0, 0, &tsArguments);
H
hzcheng 已提交
394

H
Hui Li 已提交
395
  if (tsArguments.abort) {
S
#1022  
slguan 已提交
396
    #ifndef _ALPINE
F
Frozen 已提交
397 398 399 400 401
      error(10, 0, "ABORTED");
    #else
      abort();
    #endif
  }
H
hzcheng 已提交
402

H
Hui Li 已提交
403 404 405 406 407 408 409
  printf("====== arguments config ======\n");
  {
    printf("host: %s\n", tsArguments.host);
    printf("user: %s\n", tsArguments.user);
    printf("password: %s\n", tsArguments.password);
    printf("port: %u\n", tsArguments.port);
    printf("cversion: %s\n", tsArguments.cversion);    
H
Hui Li 已提交
410
    printf("mysqlFlag: %d\n", tsArguments.mysqlFlag);    
H
Hui Li 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
    printf("outpath: %s\n", tsArguments.outpath);
    printf("inpath: %s\n", tsArguments.inpath);
    printf("encode: %s\n", tsArguments.encode);
    printf("all_databases: %d\n", tsArguments.all_databases);
    printf("databases: %d\n", tsArguments.databases);
    printf("schemaonly: %d\n", tsArguments.schemaonly);
    printf("with_property: %d\n", tsArguments.with_property);
    printf("start_time: %" PRId64 "\n", tsArguments.start_time);
    printf("end_time: %" PRId64 "\n", tsArguments.end_time);
    printf("data_batch: %d\n", tsArguments.data_batch);
    printf("table_batch: %d\n", tsArguments.table_batch);
    printf("allow_sys: %d\n", tsArguments.allow_sys);
    printf("abort: %d\n", tsArguments.abort);
    printf("isDumpIn: %d\n", tsArguments.isDumpIn);
    printf("arg_list_len: %d\n", tsArguments.arg_list_len);

    for (int32_t i = 0; i < tsArguments.arg_list_len; i++) {
      printf("arg_list[%d]: %s\n", i, tsArguments.arg_list[i]);
    }
  }  
  printf("==============================\n");

  if (tsArguments.cversion[0] != 0){
H
Hui Li 已提交
434
    tstrncpy(version, tsArguments.cversion, 11);
H
Hui Li 已提交
435 436 437
  }

  if (taosCheckParam(&tsArguments) < 0) {
H
hzcheng 已提交
438 439 440
    exit(EXIT_FAILURE);
  }

H
Hui Li 已提交
441 442
  if (tsArguments.isDumpIn) {
    if (taosDumpIn(&tsArguments) < 0) return -1;
H
hzcheng 已提交
443
  } else {
H
Hui Li 已提交
444
    if (taosDumpOut(&tsArguments) < 0) return -1;
H
hzcheng 已提交
445 446 447 448 449 450 451
  }

  return 0;
}

void taosFreeDbInfos() {
  if (dbInfos == NULL) return;
S
Shengliang Guan 已提交
452 453
  for (int i = 0; i < 128; i++) taosTFree(dbInfos[i]);
  taosTFree(dbInfos);
H
hzcheng 已提交
454 455
}

H
Hui Li 已提交
456 457
// check table is normal table or super table
int taosGetTableRecordInfo(char *table, STableRecordInfo *pTableRecordInfo, TAOS *taosCon) {
H
hzcheng 已提交
458 459
  TAOS_ROW row = NULL;
  bool isSet = false;
H
Hui Li 已提交
460
  TAOS_RES *result     = NULL;
H
hzcheng 已提交
461 462 463

  memset(pTableRecordInfo, 0, sizeof(STableRecordInfo));

H
Hui Li 已提交
464 465 466 467 468
  char* tempCommand = (char *)malloc(COMMAND_SIZE);
  if (tempCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return -1;
  }
H
hzcheng 已提交
469

H
Hui Li 已提交
470 471 472 473 474
  sprintf(tempCommand, "show tables like %s", table);
  
  result = taos_query(taosCon, tempCommand);  
  int32_t code = taos_errno(result);
  
S
Shuaiqiang Chang 已提交
475
  if (code != 0) {
H
Hui Li 已提交
476 477
    fprintf(stderr, "failed to run command %s\n", tempCommand);
    free(tempCommand);
S
Shuaiqiang Chang 已提交
478
    taos_free_result(result);
H
hzcheng 已提交
479 480 481 482 483
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(result);

H
Hui Li 已提交
484
  while ((row = taos_fetch_row(result)) != NULL) {
H
hzcheng 已提交
485 486 487 488 489 490
    isSet = true;
    pTableRecordInfo->isMetric = false;
    strncpy(pTableRecordInfo->tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX],
            fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
    strncpy(pTableRecordInfo->tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX],
            fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes);
H
Hui Li 已提交
491
    break;
H
hzcheng 已提交
492 493 494 495 496
  }

  taos_free_result(result);
  result = NULL;

H
Hui Li 已提交
497 498 499 500 501 502 503 504
  if (isSet) {
    free(tempCommand);
    return 0;
  }
  
  sprintf(tempCommand, "show stables like %s", table);
  
  result = taos_query(taosCon, tempCommand);  
S
Shuaiqiang Chang 已提交
505
  code = taos_errno(result);
H
Hui Li 已提交
506
  
S
Shuaiqiang Chang 已提交
507
  if (code != 0) {
H
Hui Li 已提交
508 509
    fprintf(stderr, "failed to run command %s\n", tempCommand);
    free(tempCommand);
S
Shuaiqiang Chang 已提交
510
    taos_free_result(result);
H
hzcheng 已提交
511 512 513
    return -1;
  }

H
Hui Li 已提交
514
  while ((row = taos_fetch_row(result)) != NULL) {
H
hzcheng 已提交
515 516
    isSet = true;
    pTableRecordInfo->isMetric = true;
H
Hui Li 已提交
517
    tstrncpy(pTableRecordInfo->tableRecord.metric, table, TSDB_TABLE_NAME_LEN);
H
Hui Li 已提交
518
    break;
H
hzcheng 已提交
519 520 521 522 523
  }

  taos_free_result(result);
  result = NULL;

H
Hui Li 已提交
524 525 526 527
  if (isSet) {
    free(tempCommand);
    return 0;
  }
H
hzcheng 已提交
528
  fprintf(stderr, "invalid table/metric %s\n", table);
H
Hui Li 已提交
529
  free(tempCommand);
H
hzcheng 已提交
530 531 532
  return -1;
}

H
Hui Li 已提交
533 534 535 536 537 538 539 540 541 542 543 544

int32_t taosSaveAllNormalTableToTempFile(TAOS *taosCon, char*meter, char* metric, int* fd) {
  STableRecord tableRecord;

  if (-1 == *fd) {
    *fd = open(".tables.tmp.0", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
    if (*fd == -1) {
      fprintf(stderr, "failed to open temp file: .tables.tmp.0\n");
      return -1;
    }
  }
  
H
Hui Li 已提交
545 546 547
  memset(&tableRecord, 0, sizeof(STableRecord));
  tstrncpy(tableRecord.name, meter, TSDB_TABLE_NAME_LEN);
  tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN);
H
Hui Li 已提交
548

S
Shengliang Guan 已提交
549
  taosTWrite(*fd, &tableRecord, sizeof(STableRecord));
H
Hui Li 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
  return 0;
}


int32_t taosSaveTableOfMetricToTempFile(TAOS *taosCon, char* metric, struct arguments *arguments, int32_t*  totalNumOfThread) {
  TAOS_ROW row;
  int fd = -1;
  STableRecord tableRecord;

  char* tmpCommand = (char *)malloc(COMMAND_SIZE);
  if (tmpCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return -1;
  }

  sprintf(tmpCommand, "select tbname from %s", metric);
  
  TAOS_RES *result = taos_query(taosCon, tmpCommand);  
  int32_t code = taos_errno(result);
  if (code != 0) {
    fprintf(stderr, "failed to run command %s\n", tmpCommand);
    free(tmpCommand);
    taos_free_result(result);
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(result);

  int32_t  numOfTable  = 0;
  int32_t  numOfThread = *totalNumOfThread;
  char     tmpFileName[TSDB_FILENAME_LEN + 1];
  while ((row = taos_fetch_row(result)) != NULL) {
    if (0 == numOfTable) {
      memset(tmpFileName, 0, TSDB_FILENAME_LEN);
      sprintf(tmpFileName, ".tables.tmp.%d", numOfThread);
      fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
      if (fd == -1) {
        fprintf(stderr, "failed to open temp file: %s\n", tmpFileName);
        taos_free_result(result);
        for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) {
          sprintf(tmpFileName, ".tables.tmp.%d", loopCnt);
H
Hui Li 已提交
591
          (void)remove(tmpFileName);
H
Hui Li 已提交
592 593 594 595 596 597 598 599
        }
        free(tmpCommand);
        return -1;
      }
      
      numOfThread++;
    }
  
H
Hui Li 已提交
600
    memset(&tableRecord, 0, sizeof(STableRecord));
H
Hui Li 已提交
601
    tstrncpy(tableRecord.name, (char *)row[0], fields[0].bytes);
H
Hui Li 已提交
602
    tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN);
H
Hui Li 已提交
603

S
Shengliang Guan 已提交
604
    taosTWrite(fd, &tableRecord, sizeof(STableRecord));
H
Hui Li 已提交
605 606 607 608 609

    numOfTable++;

    if (numOfTable >= arguments->table_batch) {
      numOfTable = 0;
H
Hui Li 已提交
610
      close(fd);
H
Hui Li 已提交
611 612 613
      fd = -1;
    }
  }
H
Hui Li 已提交
614 615 616 617 618 619
  
  if (fd >= 0) {
    close(fd);
    fd = -1;
  }
  
H
Hui Li 已提交
620 621 622 623 624 625 626 627 628 629 630 631 632 633
  taos_free_result(result);

  *totalNumOfThread = numOfThread;
 
  free(tmpCommand);

  return 0;
}

int taosDumpOut(struct arguments *arguments) {
  TAOS     *taos       = NULL;
  TAOS_RES *result     = NULL;
  char     *command    = NULL;

H
hzcheng 已提交
634 635
  TAOS_ROW row;
  FILE *fp = NULL;
H
Hui Li 已提交
636
  int32_t count = 0;
H
hzcheng 已提交
637 638
  STableRecordInfo tableRecordInfo;

H
Hui Li 已提交
639 640 641 642 643 644 645 646
  char tmpBuf[TSDB_FILENAME_LEN+9] = {0};
  if (arguments->outpath[0] != 0) {
      sprintf(tmpBuf, "%s/dbs.sql", arguments->outpath);
  } else {
    sprintf(tmpBuf, "dbs.sql");
  }
  
  fp = fopen(tmpBuf, "w");
H
hzcheng 已提交
647
  if (fp == NULL) {
H
Hui Li 已提交
648
    fprintf(stderr, "failed to open file %s\n", tmpBuf);
H
hzcheng 已提交
649 650 651
    return -1;
  }

H
Hui Li 已提交
652
  dbInfos = (SDbInfo **)calloc(128, sizeof(SDbInfo *));
H
hzcheng 已提交
653 654 655 656 657
  if (dbInfos == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    goto _exit_failure;
  }

H
Hui Li 已提交
658 659
  command = (char *)malloc(COMMAND_SIZE);
  if (command == NULL) {
H
hzcheng 已提交
660 661 662 663 664 665 666
    fprintf(stderr, "failed to allocate memory\n");
    goto _exit_failure;
  }

  /* Connect to server */
  taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port);
  if (taos == NULL) {
S
slguan 已提交
667
    fprintf(stderr, "failed to connect to TDengine server\n");
H
hzcheng 已提交
668 669 670
    goto _exit_failure;
  }

S
slguan 已提交
671 672
  /* --------------------------------- Main Code -------------------------------- */
  /* if (arguments->databases || arguments->all_databases) { // dump part of databases or all databases */
H
hzcheng 已提交
673
  /*  */
S
slguan 已提交
674 675
  taosDumpCharset(fp);

H
hzcheng 已提交
676
  sprintf(command, "show databases");
H
Hui Li 已提交
677
  result = taos_query(taos, command);  
S
Shuaiqiang Chang 已提交
678
  int32_t code = taos_errno(result);
H
Hui Li 已提交
679
  
S
Shuaiqiang Chang 已提交
680
  if (code != 0) {
H
Hui Li 已提交
681
    fprintf(stderr, "failed to run command: %s, reason: %s\n", command, taos_errstr(taos));
H
hzcheng 已提交
682 683 684 685 686 687
    goto _exit_failure;
  }

  TAOS_FIELD *fields = taos_fetch_fields(result);

  while ((row = taos_fetch_row(result)) != NULL) {
H
Hui Li 已提交
688
    // sys database name : 'monitor', but subsequent version changed to 'log'
689
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "monitor", fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0 &&
H
hzcheng 已提交
690 691 692
        (!arguments->allow_sys))
      continue;

H
Hui Li 已提交
693
    if (arguments->databases) {  // input multi dbs
H
hzcheng 已提交
694
      for (int i = 0; arguments->arg_list[i]; i++) {
695
        if (strncasecmp(arguments->arg_list[i], (char *)row[TSDB_SHOW_DB_NAME_INDEX],
H
hzcheng 已提交
696 697 698 699
                        fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0)
          goto _dump_db_point;
      }
      continue;
H
Hui Li 已提交
700
    } else if (!arguments->all_databases) {  // only input one db
H
hzcheng 已提交
701 702 703 704 705 706 707
      if (strncasecmp(arguments->arg_list[0], (char *)row[TSDB_SHOW_DB_NAME_INDEX],
                      fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0)
        goto _dump_db_point;
      else
        continue;
    }

S
slguan 已提交
708
  _dump_db_point:
H
hzcheng 已提交
709 710 711 712 713 714 715 716

    dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo));
    if (dbInfos[count] == NULL) {
      fprintf(stderr, "failed to allocate memory\n");
      goto _exit_failure;
    }

    strncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX], fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
H
Hui Li 已提交
717 718 719 720 721 722 723 724 725 726 727 728 729
 #if 0   
    dbInfos[count]->replica = (int)(*((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]));
    dbInfos[count]->days = (int)(*((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]));
    dbInfos[count]->keep = *((int *)row[TSDB_SHOW_DB_KEEP_INDEX]);
    dbInfos[count]->tables = *((int *)row[TSDB_SHOW_DB_TABLES_INDEX]);
    dbInfos[count]->rows = *((int *)row[TSDB_SHOW_DB_ROWS_INDEX]);
    dbInfos[count]->cache = *((int *)row[TSDB_SHOW_DB_CACHE_INDEX]);
    dbInfos[count]->ablocks = *((int *)row[TSDB_SHOW_DB_ABLOCKS_INDEX]);
    dbInfos[count]->tblocks = (int)(*((int16_t *)row[TSDB_SHOW_DB_TBLOCKS_INDEX]));
    dbInfos[count]->ctime = *((int *)row[TSDB_SHOW_DB_CTIME_INDEX]);
    dbInfos[count]->clog = (int)(*((int8_t *)row[TSDB_SHOW_DB_CLOG_INDEX]));
    dbInfos[count]->comp = (int)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX]));
#endif
H
hzcheng 已提交
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745

    count++;

    if (arguments->databases) {
      if (count > arguments->arg_list_len) break;

    } else if (!arguments->all_databases) {
      if (count >= 1) break;
    }
  }

  if (count == 0) {
    fprintf(stderr, "No databases valid to dump\n");
    goto _exit_failure;
  }

H
Hui Li 已提交
746
  if (arguments->databases || arguments->all_databases) { // case: taosdump --databases dbx dby ...   OR  taosdump --all-databases
H
hzcheng 已提交
747
    for (int i = 0; i < count; i++) {
H
Hui Li 已提交
748
      taosDumpDb(dbInfos[i], arguments, fp, taos);
H
hzcheng 已提交
749 750
    }
  } else {
H
Hui Li 已提交
751 752 753
    if (arguments->arg_list_len == 1) {             // case: taosdump <db>
      taosDumpDb(dbInfos[0], arguments, fp, taos);
    } else {                                        // case: taosdump <db> tablex tabley ...
H
hzcheng 已提交
754 755 756
      taosDumpCreateDbClause(dbInfos[0], arguments->with_property, fp);

      sprintf(command, "use %s", dbInfos[0]->name);
H
Hui Li 已提交
757 758 759 760
      
      result = taos_query(taos, command);  
      int32_t code = taos_errno(result);
      if (code != 0) {
H
hzcheng 已提交
761 762 763 764 765 766
        fprintf(stderr, "invalid database %s\n", dbInfos[0]->name);
        goto _exit_failure;
      }

      fprintf(fp, "USE %s;\n\n", dbInfos[0]->name);

H
Hui Li 已提交
767 768 769
      int32_t totalNumOfThread = 1;  // 0: all normal talbe into .tables.tmp.0
      int  normalTblFd = -1;
      int32_t retCode;
H
hzcheng 已提交
770
      for (int i = 1; arguments->arg_list[i]; i++) {
H
Hui Li 已提交
771 772
        if (taosGetTableRecordInfo(arguments->arg_list[i], &tableRecordInfo, taos) < 0) {
          fprintf(stderr, "input the invalide table %s\n", arguments->arg_list[i]);
H
hzcheng 已提交
773 774 775
          continue;
        }

H
Hui Li 已提交
776 777 778 779 780 781 782 783 784 785 786 787
        if (tableRecordInfo.isMetric) {  // dump all table of this metric
          (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos);
          retCode = taosSaveTableOfMetricToTempFile(taos, tableRecordInfo.tableRecord.metric, arguments, &totalNumOfThread);
        } else {
          if (tableRecordInfo.tableRecord.metric[0] != '\0') {  // dump this sub table and it's metric
            (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos);          
          }
          retCode = taosSaveAllNormalTableToTempFile(taos, tableRecordInfo.tableRecord.name, tableRecordInfo.tableRecord.metric, &normalTblFd);
        }

        if (retCode < 0) {
          if (-1 != normalTblFd){
S
Shengliang Guan 已提交
788
            taosClose(normalTblFd);
H
Hui Li 已提交
789 790
          }
          goto _clean_tmp_file;
H
hzcheng 已提交
791 792
        }
      }
H
Hui Li 已提交
793 794

      if (-1 != normalTblFd){
S
Shengliang Guan 已提交
795
        taosClose(normalTblFd);
H
Hui Li 已提交
796 797 798 799 800 801 802 803 804 805 806
      }

      // start multi threads to dumpout
      taosStartDumpOutWorkThreads(arguments, totalNumOfThread, dbInfos[0]->name);

      char tmpFileName[TSDB_FILENAME_LEN + 1];
      _clean_tmp_file:
      for (int loopCnt = 0; loopCnt < totalNumOfThread; loopCnt++) {
        sprintf(tmpFileName, ".tables.tmp.%d", loopCnt);
        remove(tmpFileName);
      }
H
hzcheng 已提交
807 808 809 810 811 812 813
    }
  }

  /* Close the handle and return */
  fclose(fp);
  taos_close(taos);
  taos_free_result(result);
S
Shengliang Guan 已提交
814
  taosTFree(command);
H
Hui Li 已提交
815 816
  taosFreeDbInfos();  
  fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows);
H
hzcheng 已提交
817 818
  return 0;

S
slguan 已提交
819
_exit_failure:
H
hzcheng 已提交
820 821 822
  fclose(fp);
  taos_close(taos);
  taos_free_result(result);
S
Shengliang Guan 已提交
823
  taosTFree(command);
H
hzcheng 已提交
824
  taosFreeDbInfos();
H
Hui Li 已提交
825
  fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows);
H
hzcheng 已提交
826 827 828
  return -1;
}

H
Hui Li 已提交
829
int taosGetTableDes(char *table, STableDef *tableDes, TAOS* taosCon, bool isSuperTable) {
H
Hui Li 已提交
830 831 832
  TAOS_ROW row = NULL;
  TAOS_RES *tmpResult = NULL;
  int count = 0;
H
hzcheng 已提交
833

H
Hui Li 已提交
834 835 836
  char* tempCommand = (char *)malloc(COMMAND_SIZE);
  if (tempCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
H
hzcheng 已提交
837 838 839
    return -1;
  }

H
Hui Li 已提交
840 841 842 843 844 845 846
  char* tbuf = (char *)malloc(COMMAND_SIZE);
  if (tbuf == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    free(tempCommand);
    return -1;
  }

H
Hui Li 已提交
847 848 849 850
  sprintf(tempCommand, "describe %s", table);
  
  tmpResult = taos_query(taosCon, tempCommand);  
  int32_t code = taos_errno(tmpResult);
S
Shuaiqiang Chang 已提交
851
  if (code != 0) {
H
Hui Li 已提交
852 853
    fprintf(stderr, "failed to run command %s\n", tempCommand);
    free(tempCommand);
H
Hui Li 已提交
854
    free(tbuf);
H
Hui Li 已提交
855
    taos_free_result(tmpResult);
H
hzcheng 已提交
856 857 858
    return -1;
  }

H
Hui Li 已提交
859
  TAOS_FIELD *fields = taos_fetch_fields(tmpResult);
H
hzcheng 已提交
860

H
Hui Li 已提交
861
  tstrncpy(tableDes->name, table, TSDB_COL_NAME_LEN);
H
hzcheng 已提交
862

H
Hui Li 已提交
863 864 865 866 867 868 869 870
  while ((row = taos_fetch_row(tmpResult)) != NULL) {
    strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
            fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
    strncpy(tableDes->cols[count].type, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
            fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
    tableDes->cols[count].length = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
    strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
            fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
H
hzcheng 已提交
871

H
Hui Li 已提交
872
    count++;
H
hzcheng 已提交
873 874
  }

H
Hui Li 已提交
875 876
  taos_free_result(tmpResult);
  tmpResult = NULL;
H
hzcheng 已提交
877

H
Hui Li 已提交
878 879
  if (isSuperTable) {
    free(tempCommand);
H
Hui Li 已提交
880
    free(tbuf);
H
Hui Li 已提交
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
    return count;
  }
  
  // if chidl-table have tag, using  select tagName from table to get tagValue
  for (int i = 0 ; i < count; i++) {
    if (strcmp(tableDes->cols[i].note, "TAG") != 0) continue;


    sprintf(tempCommand, "select %s from %s", tableDes->cols[i].field, table);
    
    tmpResult = taos_query(taosCon, tempCommand);  
    code = taos_errno(tmpResult);
    if (code != 0) {
      fprintf(stderr, "failed to run command %s\n", tempCommand);
      free(tempCommand);
H
Hui Li 已提交
896
      free(tbuf);
H
Hui Li 已提交
897 898 899 900 901 902 903 904 905 906
      taos_free_result(tmpResult);
      return -1;
    }
    
    fields = taos_fetch_fields(tmpResult); 

    row = taos_fetch_row(tmpResult);
    if (NULL == row) {
      fprintf(stderr, " fetch failed to run command %s\n", tempCommand);
      free(tempCommand);
H
Hui Li 已提交
907
      free(tbuf);
H
Hui Li 已提交
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
      taos_free_result(tmpResult);
      return -1;
    }
  
    switch (fields[0].type) {
      case TSDB_DATA_TYPE_BOOL:
        sprintf(tableDes->cols[i].note, "%d", ((((int)(*((char *)row[0]))) == 1) ? 1 : 0));
        break;
      case TSDB_DATA_TYPE_TINYINT:
        sprintf(tableDes->cols[i].note, "%d", (int)(*((char *)row[0])));
        break;
      case TSDB_DATA_TYPE_SMALLINT:
        sprintf(tableDes->cols[i].note, "%d", (int)(*((short *)row[0])));
        break;
      case TSDB_DATA_TYPE_INT:
        sprintf(tableDes->cols[i].note, "%d", *((int *)row[0]));
        break;
      case TSDB_DATA_TYPE_BIGINT:
        sprintf(tableDes->cols[i].note, "%" PRId64 "", *((int64_t *)row[0]));
        break;
      case TSDB_DATA_TYPE_FLOAT:
        sprintf(tableDes->cols[i].note, "%f", GET_FLOAT_VAL(row[0]));
        break;
      case TSDB_DATA_TYPE_DOUBLE:
        sprintf(tableDes->cols[i].note, "%f", GET_DOUBLE_VAL(row[0]));
        break;
      case TSDB_DATA_TYPE_BINARY:
        tableDes->cols[i].note[0] = '\'';
        converStringToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE);
        char* pstr = stpcpy(&(tableDes->cols[i].note[1]), tbuf);
        *(pstr++) = '\'';
        break;
      case TSDB_DATA_TYPE_NCHAR:
        convertNCharToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE);
        sprintf(tableDes->cols[i].note, "\'%s\'", tbuf);
        break;
      case TSDB_DATA_TYPE_TIMESTAMP:
        sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]);
        #if 0
        if (!arguments->mysqlFlag) {
          sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]);
        } else {
          char buf[64] = "\0";
          int64_t ts = *((int64_t *)row[0]);
          time_t tt = (time_t)(ts / 1000);
          struct tm *ptm = localtime(&tt);
          strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm);
          sprintf(tableDes->cols[i].note, "\'%s.%03d\'", buf, (int)(ts % 1000));
        }
        #endif
        break;
      default:
        break;
    }
  
    taos_free_result(tmpResult);
    tmpResult = NULL;    
  }

H
Hui Li 已提交
967
  free(tempCommand);
H
Hui Li 已提交
968
  free(tbuf);
H
hzcheng 已提交
969

H
Hui Li 已提交
970 971
  return count;
}
H
hzcheng 已提交
972

H
Hui Li 已提交
973 974
int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon) {
  int count = 0;
H
hzcheng 已提交
975

H
Hui Li 已提交
976
  STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS);
H
hzcheng 已提交
977

H
Hui Li 已提交
978 979 980 981 982 983 984 985
  if (metric != NULL && metric[0] != '\0') {  // dump table schema which is created by using super table
    /*
    count = taosGetTableDes(metric, tableDes, taosCon);

    if (count < 0) {
      free(tableDes);
      return -1;
    }
H
hzcheng 已提交
986

H
Hui Li 已提交
987
    taosDumpCreateTableClause(tableDes, count, fp);
H
hzcheng 已提交
988

H
Hui Li 已提交
989 990
    memset(tableDes, 0, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS);
    */
H
hzcheng 已提交
991

H
Hui Li 已提交
992
    count = taosGetTableDes(table, tableDes, taosCon, false);
H
Hui Li 已提交
993 994 995 996

    if (count < 0) {
      free(tableDes);
      return -1;
H
hzcheng 已提交
997 998
    }

H
Hui Li 已提交
999
    // create child-table using super-table
H
Hui Li 已提交
1000 1001 1002
    taosDumpCreateMTableClause(tableDes, metric, count, fp);

  } else {  // dump table definition
H
Hui Li 已提交
1003
    count = taosGetTableDes(table, tableDes, taosCon, false);
H
Hui Li 已提交
1004 1005 1006 1007

    if (count < 0) {
      free(tableDes);
      return -1;
H
hzcheng 已提交
1008
    }
H
Hui Li 已提交
1009

H
Hui Li 已提交
1010
    // create normal-table or super-table
H
Hui Li 已提交
1011
    taosDumpCreateTableClause(tableDes, count, fp);
H
hzcheng 已提交
1012 1013
  }

H
Hui Li 已提交
1014
  free(tableDes);
H
hzcheng 已提交
1015

H
Hui Li 已提交
1016 1017
  return taosDumpTableData(fp, table, arguments, taosCon);
}
H
hzcheng 已提交
1018

H
Hui Li 已提交
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp) {

  char* tmpCommand = (char *)malloc(COMMAND_SIZE);
  if (tmpCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return;
  }

  char *pstr = tmpCommand;

  pstr += sprintf(pstr, "CREATE DATABASE IF NOT EXISTS %s", dbInfo->name);
  if (isDumpProperty) {
    pstr += sprintf(pstr,
        " REPLICA %d DAYS %d KEEP %d TABLES %d ROWS %d CACHE %d ABLOCKS %d TBLOCKS %d CTIME %d CLOG %d COMP %d",
        dbInfo->replica, dbInfo->days, dbInfo->keep, dbInfo->tables, dbInfo->rows, dbInfo->cache,
        dbInfo->ablocks, dbInfo->tblocks, dbInfo->ctime, dbInfo->clog, dbInfo->comp);
H
hzcheng 已提交
1035 1036
  }

H
Hui Li 已提交
1037
  pstr += sprintf(pstr, ";");
H
hzcheng 已提交
1038

H
Hui Li 已提交
1039 1040
  fprintf(fp, "%s\n\n", tmpCommand);
  free(tmpCommand);
H
hzcheng 已提交
1041 1042
}

H
Hui Li 已提交
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
void* taosDumpOutWorkThreadFp(void *arg)
{
  SThreadParaObj *pThread = (SThreadParaObj*)arg;
  STableRecord    tableRecord;
  int fd;  
  
  char tmpFileName[TSDB_FILENAME_LEN*4] = {0};
  sprintf(tmpFileName, ".tables.tmp.%d", pThread->threadIndex);
  fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
  if (fd == -1) {
    fprintf(stderr, "taosDumpTableFp() failed to open temp file: %s\n", tmpFileName);
    return NULL;
  }
H
hzcheng 已提交
1056

H
Hui Li 已提交
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
  FILE *fp = NULL;
  memset(tmpFileName, 0, TSDB_FILENAME_LEN + 128);
  
  if (tsArguments.outpath[0] != 0) {
    sprintf(tmpFileName, "%s/%s.tables.%d.sql", tsArguments.outpath, pThread->dbName, pThread->threadIndex);
  } else {
    sprintf(tmpFileName, "%s.tables.%d.sql", pThread->dbName, pThread->threadIndex);
  }
  
  fp = fopen(tmpFileName, "w");
  if (fp == NULL) {
    fprintf(stderr, "failed to open file %s\n", tmpFileName);
H
Hui Li 已提交
1069
    close(fd);
H
Hui Li 已提交
1070 1071
    return NULL;
  }
H
hzcheng 已提交
1072

H
Hui Li 已提交
1073 1074 1075 1076 1077 1078 1079 1080
  memset(tmpFileName, 0, TSDB_FILENAME_LEN);
  sprintf(tmpFileName, "use %s", pThread->dbName);
  
  TAOS_RES* tmpResult = taos_query(pThread->taosCon, tmpFileName);  
  int32_t code = taos_errno(tmpResult);
  if (code != 0) {
    fprintf(stderr, "invalid database %s\n", pThread->dbName);
    taos_free_result(tmpResult);
H
Hui Li 已提交
1081 1082
    fclose(fp);  
    close(fd);
H
Hui Li 已提交
1083
    return NULL;
H
hzcheng 已提交
1084 1085
  }

H
Hui Li 已提交
1086
  fprintf(fp, "USE %s\n\n", pThread->dbName);
H
Hui Li 已提交
1087 1088 1089
  while (1) {
    ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord));
    if (readLen <= 0) break;
H
Hui Li 已提交
1090 1091
    taosDumpTable(tableRecord.name, tableRecord.metric, &tsArguments, fp, pThread->taosCon);
  }
H
hzcheng 已提交
1092

H
Hui Li 已提交
1093
  taos_free_result(tmpResult);
H
Hui Li 已提交
1094
  close(fd);
H
Hui Li 已提交
1095
  fclose(fp);  
1096

H
Hui Li 已提交
1097 1098
  return NULL;
}
1099

H
Hui Li 已提交
1100 1101 1102 1103 1104 1105 1106 1107
static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t  numOfThread, char *dbName)
{
  pthread_attr_t thattr;
  SThreadParaObj *threadObj = (SThreadParaObj *)calloc(numOfThread, sizeof(SThreadParaObj));
  for (int t = 0; t < numOfThread; ++t) {
    SThreadParaObj *pThread = threadObj + t;
    pThread->threadIndex = t;
    pThread->totalThreads = numOfThread;
H
Hui Li 已提交
1108
    tstrncpy(pThread->dbName, dbName, TSDB_TABLE_NAME_LEN);
H
Hui Li 已提交
1109 1110 1111 1112 1113
    pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port);
                                
    if (pThread->taosCon == NULL) {
      fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon));
      exit(0);
1114 1115
    }

H
Hui Li 已提交
1116 1117 1118 1119 1120 1121
    pthread_attr_init(&thattr);
    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);

    if (pthread_create(&(pThread->threadID), &thattr, taosDumpOutWorkThreadFp, (void*)pThread) != 0) {
      fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex);
      exit(0);
1122
    }
H
Hui Li 已提交
1123
  }
1124

H
Hui Li 已提交
1125 1126 1127
  for (int32_t t = 0; t < numOfThread; ++t) {
    pthread_join(threadObj[t].threadID, NULL);
  }
1128

H
Hui Li 已提交
1129 1130 1131 1132 1133
  for (int32_t t = 0; t < numOfThread; ++t) {
    taos_close(threadObj[t].taosCon);
  }
  free(threadObj);
}
H
hzcheng 已提交
1134

H
Hui Li 已提交
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145


int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon) {
  int count = 0;

  STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS);
  if (NULL == tableDes) {
    fprintf(stderr, "failed to allocate memory\n");
    exit(-1);
  }

H
Hui Li 已提交
1146
  count = taosGetTableDes(table, tableDes, taosCon, true);
H
Hui Li 已提交
1147 1148 1149 1150 1151

  if (count < 0) {
    free(tableDes);
    fprintf(stderr, "failed to get stable schema\n");
    exit(-1);
H
hzcheng 已提交
1152 1153
  }

H
Hui Li 已提交
1154
  taosDumpCreateTableClause(tableDes, count, fp);
H
hzcheng 已提交
1155

H
Hui Li 已提交
1156 1157
  free(tableDes);
  return 0;
H
hzcheng 已提交
1158 1159 1160
}


H
Hui Li 已提交
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
int32_t taosDumpCreateSuperTableClause(TAOS* taosCon, char* dbName, FILE *fp) 
{
  TAOS_ROW row;
  int fd = -1;
  STableRecord tableRecord;

  char* tmpCommand = (char *)malloc(COMMAND_SIZE);
  if (tmpCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    exit(-1);
  }
H
hzcheng 已提交
1172

H
Hui Li 已提交
1173 1174 1175 1176
  sprintf(tmpCommand, "use %s", dbName);
  
  TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand);  
  int32_t code = taos_errno(tmpResult);
S
Shuaiqiang Chang 已提交
1177
  if (code != 0) {
H
Hui Li 已提交
1178 1179 1180 1181
    fprintf(stderr, "invalid database %s, error: %s\n", dbName, taos_errstr(taosCon));
    free(tmpCommand);
    taos_free_result(tmpResult);
    exit(-1);
H
hzcheng 已提交
1182
  }
H
Hui Li 已提交
1183 1184
  
  taos_free_result(tmpResult);
H
hzcheng 已提交
1185

H
Hui Li 已提交
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
  sprintf(tmpCommand, "show stables");
  
  tmpResult = taos_query(taosCon, tmpCommand);  
  code = taos_errno(tmpResult);
  if (code != 0) {
    fprintf(stderr, "failed to run command %s, error: %s\n", tmpCommand, taos_errstr(taosCon));
    free(tmpCommand);
    taos_free_result(tmpResult);
    exit(-1);
  }
H
hzcheng 已提交
1196

H
Hui Li 已提交
1197
  TAOS_FIELD *fields = taos_fetch_fields(tmpResult);
H
hzcheng 已提交
1198

H
Hui Li 已提交
1199 1200 1201 1202 1203 1204 1205 1206
  char     tmpFileName[TSDB_FILENAME_LEN + 1];
  memset(tmpFileName, 0, TSDB_FILENAME_LEN);
  sprintf(tmpFileName, ".stables.tmp");
  fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
  if (fd == -1) {
    fprintf(stderr, "failed to open temp file: %s\n", tmpFileName);
    taos_free_result(tmpResult);
    free(tmpCommand);
H
Hui Li 已提交
1207
    (void)remove(".stables.tmp");
H
Hui Li 已提交
1208
    exit(-1);
H
hzcheng 已提交
1209
  }
H
Hui Li 已提交
1210 1211 1212 1213
  
  while ((row = taos_fetch_row(tmpResult)) != NULL) {  
    memset(&tableRecord, 0, sizeof(STableRecord));
    strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
S
Shengliang Guan 已提交
1214
    taosTWrite(fd, &tableRecord, sizeof(STableRecord));
H
Hui Li 已提交
1215 1216 1217
  }  
  
  taos_free_result(tmpResult);
H
Hui Li 已提交
1218
  (void)lseek(fd, 0, SEEK_SET);
H
hzcheng 已提交
1219

H
Hui Li 已提交
1220 1221 1222 1223
  while (1) {
    ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord));
    if (readLen <= 0) break;
    
H
Hui Li 已提交
1224 1225
    (void)taosDumpStable(tableRecord.name, fp, taosCon);
  }
H
hzcheng 已提交
1226

H
Hui Li 已提交
1227 1228
  close(fd);
  (void)remove(".stables.tmp");
H
Hui Li 已提交
1229 1230 1231
  
  free(tmpCommand);
  return 0;  
H
hzcheng 已提交
1232 1233 1234
}


H
Hui Li 已提交
1235 1236 1237 1238
int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon) {
  TAOS_ROW row;
  int fd = -1;
  STableRecord tableRecord;
H
hzcheng 已提交
1239

H
Hui Li 已提交
1240
  taosDumpCreateDbClause(dbInfo, arguments->with_property, fp);
H
hzcheng 已提交
1241

H
Hui Li 已提交
1242 1243 1244 1245 1246
  char* tmpCommand = (char *)malloc(COMMAND_SIZE);
  if (tmpCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return -1;
  }
H
hzcheng 已提交
1247

H
Hui Li 已提交
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
  sprintf(tmpCommand, "use %s", dbInfo->name);
  
  TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand);  
  int32_t code = taos_errno(tmpResult);
  if (code != 0) {
    fprintf(stderr, "invalid database %s\n", dbInfo->name);
    free(tmpCommand);
    taos_free_result(tmpResult);
    return -1;
  }
  taos_free_result(tmpResult);
H
hzcheng 已提交
1259

H
Hui Li 已提交
1260 1261 1262
  fprintf(fp, "USE %s\n\n", dbInfo->name);
  
  (void)taosDumpCreateSuperTableClause(taosCon, dbInfo->name, fp);
H
hzcheng 已提交
1263

H
Hui Li 已提交
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
  sprintf(tmpCommand, "show tables");
  
  tmpResult = taos_query(taosCon, tmpCommand);  
  code = taos_errno(tmpResult);
  if (code != 0) {
    fprintf(stderr, "failed to run command %s\n", tmpCommand);
    free(tmpCommand);
    taos_free_result(tmpResult);
    return -1;
  }
H
hzcheng 已提交
1274

H
Hui Li 已提交
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
  TAOS_FIELD *fields = taos_fetch_fields(tmpResult);

  int32_t  numOfTable  = 0;
  int32_t  numOfThread = 0;
  char     tmpFileName[TSDB_FILENAME_LEN + 1];
  while ((row = taos_fetch_row(tmpResult)) != NULL) {
    if (0 == numOfTable) {
      memset(tmpFileName, 0, TSDB_FILENAME_LEN);
      sprintf(tmpFileName, ".tables.tmp.%d", numOfThread);
      fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
      if (fd == -1) {
        fprintf(stderr, "failed to open temp file: %s\n", tmpFileName);
        taos_free_result(tmpResult);
        for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) {
          sprintf(tmpFileName, ".tables.tmp.%d", loopCnt);
H
Hui Li 已提交
1290
          (void)remove(tmpFileName);
H
Hui Li 已提交
1291 1292 1293 1294 1295 1296
        }
        free(tmpCommand);
        return -1;
      }

      numOfThread++;
H
Hongze Cheng 已提交
1297
    }
H
Hui Li 已提交
1298 1299
  
    memset(&tableRecord, 0, sizeof(STableRecord));
H
Hui Li 已提交
1300 1301
    tstrncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
    tstrncpy(tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes);
H
hzcheng 已提交
1302

S
Shengliang Guan 已提交
1303
    taosTWrite(fd, &tableRecord, sizeof(STableRecord));
H
hzcheng 已提交
1304

H
Hui Li 已提交
1305
    numOfTable++;
H
hzcheng 已提交
1306

H
Hui Li 已提交
1307 1308
    if (numOfTable >= arguments->table_batch) {
      numOfTable = 0;
H
Hui Li 已提交
1309
      close(fd);
H
Hui Li 已提交
1310
      fd = -1;
H
Hongze Cheng 已提交
1311
    }
H
Hui Li 已提交
1312
  }
H
Hui Li 已提交
1313 1314 1315 1316 1317 1318

  if (fd >= 0) {
    close(fd);
    fd = -1;
  }
  
H
Hui Li 已提交
1319 1320 1321 1322 1323 1324
  taos_free_result(tmpResult);

  // start multi threads to dumpout
  taosStartDumpOutWorkThreads(arguments, numOfThread, dbInfo->name);
  for (int loopCnt = 0; loopCnt < numOfThread; loopCnt++) {
    sprintf(tmpFileName, ".tables.tmp.%d", loopCnt);
H
Hui Li 已提交
1325
    (void)remove(tmpFileName);
H
Hui Li 已提交
1326 1327 1328
  }
  
  free(tmpCommand);
H
hzcheng 已提交
1329

H
Hui Li 已提交
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
  return 0;
}

void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp) {
  int counter = 0;
  int count_temp = 0;

  char* tmpBuf = (char *)malloc(COMMAND_SIZE);
  if (tmpBuf == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return;
H
hzcheng 已提交
1341 1342
  }

H
Hui Li 已提交
1343
  char* pstr = tmpBuf;
H
Hongze Cheng 已提交
1344

H
Hui Li 已提交
1345
  pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s", tableDes->name);
H
hzcheng 已提交
1346

H
Hui Li 已提交
1347 1348
  for (; counter < numOfCols; counter++) {
    if (tableDes->cols[counter].note[0] != '\0') break;
H
hzcheng 已提交
1349

H
Hui Li 已提交
1350 1351 1352 1353 1354
    if (counter == 0) {
      pstr += sprintf(pstr, " (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type);
    } else {
      pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type);
    }
H
hzcheng 已提交
1355

H
Hui Li 已提交
1356 1357 1358 1359
    if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 ||
        strcasecmp(tableDes->cols[counter].type, "nchar") == 0) {
      pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length);
    }
H
hzcheng 已提交
1360 1361
  }

H
Hui Li 已提交
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
  count_temp = counter;

  for (; counter < numOfCols; counter++) {
    if (counter == count_temp) {
      pstr += sprintf(pstr, ") TAGS (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type);
    } else {
      pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type);
    }

    if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 ||
        strcasecmp(tableDes->cols[counter].type, "nchar") == 0) {
      pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length);
    }
H
hzcheng 已提交
1375 1376
  }

H
Hui Li 已提交
1377
  pstr += sprintf(pstr, ");");
H
hzcheng 已提交
1378

H
Hui Li 已提交
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
  fprintf(fp, "%s\n", tmpBuf);

  free(tmpBuf);
}

void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp) {
  int counter = 0;
  int count_temp = 0;

  char* tmpBuf = (char *)malloc(COMMAND_SIZE);
  if (tmpBuf == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return;
H
hzcheng 已提交
1392 1393
  }

H
Hui Li 已提交
1394 1395
  char *pstr = NULL;
  pstr = tmpBuf;
H
hzcheng 已提交
1396

H
Hui Li 已提交
1397
  pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s USING %s TAGS (", tableDes->name, metric);
H
hzcheng 已提交
1398

H
Hui Li 已提交
1399 1400
  for (; counter < numOfCols; counter++) {
    if (tableDes->cols[counter].note[0] != '\0') break;
H
hzcheng 已提交
1401 1402
  }

H
Hui Li 已提交
1403 1404
  assert(counter < numOfCols);
  count_temp = counter;
H
hzcheng 已提交
1405

H
Hui Li 已提交
1406 1407 1408 1409
  for (; counter < numOfCols; counter++) {
    if (counter != count_temp) {
      if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 ||
          strcasecmp(tableDes->cols[counter].type, "nchar") == 0) {
H
Hui Li 已提交
1410 1411
        //pstr += sprintf(pstr, ", \'%s\'", tableDes->cols[counter].note);
        pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note);
H
Hui Li 已提交
1412 1413 1414 1415 1416 1417
      } else {
        pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note);
      }
    } else {
      if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 ||
          strcasecmp(tableDes->cols[counter].type, "nchar") == 0) {
H
Hui Li 已提交
1418 1419
        //pstr += sprintf(pstr, "\'%s\'", tableDes->cols[counter].note);
        pstr += sprintf(pstr, "%s", tableDes->cols[counter].note);
H
Hui Li 已提交
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
      } else {
        pstr += sprintf(pstr, "%s", tableDes->cols[counter].note);
      }
      /* pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); */
    }

    /* if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || strcasecmp(tableDes->cols[counter].type, "nchar")
     * == 0) { */
    /*     pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); */
    /* } */
  }

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

  fprintf(fp, "%s\n", tmpBuf);
  free(tmpBuf);
H
hzcheng 已提交
1436 1437
}

H
Hui Li 已提交
1438
int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon) {
H
hzcheng 已提交
1439
  /* char       temp[MAX_COMMAND_SIZE] = "\0"; */
H
Hui Li 已提交
1440
  int64_t totalRows = 0;
H
hzcheng 已提交
1441 1442 1443 1444
  int count = 0;
  char *pstr = NULL;
  TAOS_ROW row = NULL;
  int numFields = 0;
S
slguan 已提交
1445
  char *tbuf = NULL;
H
hzcheng 已提交
1446

H
Hui Li 已提交
1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
  char* tmpCommand = (char *)calloc(1, COMMAND_SIZE);
  if (tmpCommand == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return -1;
  }

  char* tmpBuffer = (char *)calloc(1, COMMAND_SIZE);
  if (tmpBuffer == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    free(tmpCommand);
    return -1;
  }

  pstr = tmpBuffer;
H
hzcheng 已提交
1461

H
Hui Li 已提交
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
  if (arguments->schemaonly) {
    free(tmpCommand);
    free(tmpBuffer);
    return 0;
  }
  
  sprintf(tmpCommand, 
          "select * from %s where _c0 >= %" PRId64 " and _c0 <= %" PRId64 " order by _c0 asc", 
          tbname, 
          arguments->start_time,
H
hzcheng 已提交
1472
          arguments->end_time);
H
Hui Li 已提交
1473 1474 1475
  
  TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand);  
  int32_t code = taos_errno(tmpResult);
S
Shuaiqiang Chang 已提交
1476
  if (code != 0) {
H
Hui Li 已提交
1477 1478 1479 1480
    fprintf(stderr, "failed to run command %s, reason: %s\n", tmpCommand, taos_errstr(taosCon));
    free(tmpCommand);
    free(tmpBuffer);
    taos_free_result(tmpResult);
H
hzcheng 已提交
1481 1482 1483
    return -1;
  }

H
Hui Li 已提交
1484
  numFields = taos_field_count(tmpResult);
H
hzcheng 已提交
1485
  assert(numFields > 0);
H
Hui Li 已提交
1486
  TAOS_FIELD *fields = taos_fetch_fields(tmpResult);
S
slguan 已提交
1487 1488 1489
  tbuf = (char *)malloc(COMMAND_SIZE);
  if (tbuf == NULL) {
    fprintf(stderr, "No enough memory\n");
H
Hui Li 已提交
1490 1491 1492
    free(tmpCommand);
    free(tmpBuffer);
    taos_free_result(tmpResult);
S
slguan 已提交
1493 1494
    return -1;
  }
H
hzcheng 已提交
1495

H
Hui Li 已提交
1496 1497 1498 1499 1500 1501 1502 1503
  char sqlStr[8] = "\0";
  if (arguments->mysqlFlag) {
    sprintf(sqlStr, "INSERT");
  } else {
    sprintf(sqlStr, "IMPORT");
  }

  int rowFlag = 0;
H
hzcheng 已提交
1504
  count = 0;
H
Hui Li 已提交
1505 1506
  while ((row = taos_fetch_row(tmpResult)) != NULL) {
    pstr = tmpBuffer;
H
hzcheng 已提交
1507 1508

    if (count == 0) {
H
Hui Li 已提交
1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
      pstr += sprintf(pstr, "%s INTO %s VALUES (", sqlStr, tbname);
    } else {      
      if (arguments->mysqlFlag) {
        if (0 == rowFlag) {
          pstr += sprintf(pstr, "(");
          rowFlag++;
        } else {
          pstr += sprintf(pstr, ", (");
        }
      } else {
        pstr += sprintf(pstr, "(");
      }
H
hzcheng 已提交
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
    }

    for (int col = 0; col < numFields; col++) {
      if (col != 0) pstr += sprintf(pstr, ", ");

      if (row[col] == NULL) {
        pstr += sprintf(pstr, "NULL");
        continue;
      }

      switch (fields[col].type) {
        case TSDB_DATA_TYPE_BOOL:
          pstr += sprintf(pstr, "%d", ((((int)(*((char *)row[col]))) == 1) ? 1 : 0));
          break;
        case TSDB_DATA_TYPE_TINYINT:
          pstr += sprintf(pstr, "%d", (int)(*((char *)row[col])));
          break;
        case TSDB_DATA_TYPE_SMALLINT:
          pstr += sprintf(pstr, "%d", (int)(*((short *)row[col])));
          break;
        case TSDB_DATA_TYPE_INT:
          pstr += sprintf(pstr, "%d", *((int *)row[col]));
          break;
        case TSDB_DATA_TYPE_BIGINT:
H
Hui Li 已提交
1545
          pstr += sprintf(pstr, "%" PRId64 "", *((int64_t *)row[col]));
H
hzcheng 已提交
1546 1547
          break;
        case TSDB_DATA_TYPE_FLOAT:
L
lihui 已提交
1548
          pstr += sprintf(pstr, "%f", GET_FLOAT_VAL(row[col]));
H
hzcheng 已提交
1549 1550
          break;
        case TSDB_DATA_TYPE_DOUBLE:
L
lihui 已提交
1551
          pstr += sprintf(pstr, "%f", GET_DOUBLE_VAL(row[col]));
H
hzcheng 已提交
1552 1553 1554
          break;
        case TSDB_DATA_TYPE_BINARY:
          *(pstr++) = '\'';
S
slguan 已提交
1555 1556
          converStringToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE);
          pstr = stpcpy(pstr, tbuf);
H
hzcheng 已提交
1557 1558 1559
          *(pstr++) = '\'';
          break;
        case TSDB_DATA_TYPE_NCHAR:
S
slguan 已提交
1560 1561
          convertNCharToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE);
          pstr += sprintf(pstr, "\'%s\'", tbuf);
H
hzcheng 已提交
1562 1563
          break;
        case TSDB_DATA_TYPE_TIMESTAMP:
H
Hui Li 已提交
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
          if (!arguments->mysqlFlag) {
            pstr += sprintf(pstr, "%" PRId64 "", *(int64_t *)row[col]);
          } else {
            char buf[64] = "\0";
            int64_t ts = *((int64_t *)row[col]);
            time_t tt = (time_t)(ts / 1000);
            struct tm *ptm = localtime(&tt);
            strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm);
            pstr += sprintf(pstr, "\'%s.%03d\'", buf, (int)(ts % 1000));
          }
H
hzcheng 已提交
1574 1575 1576 1577 1578 1579
          break;
        default:
          break;
      }
    }

H
Hui Li 已提交
1580 1581 1582
    pstr += sprintf(pstr, ") ");

    totalRows++;
H
hzcheng 已提交
1583
    count++;
H
Hui Li 已提交
1584
    fprintf(fp, "%s", tmpBuffer);
H
hzcheng 已提交
1585 1586

    if (count >= arguments->data_batch) {
H
Hui Li 已提交
1587
      fprintf(fp, ";\n");
H
hzcheng 已提交
1588
      count = 0;
H
Hui Li 已提交
1589 1590 1591
    } //else {
      //fprintf(fp, "\\\n");
    //}
H
hzcheng 已提交
1592 1593
  }

H
Hui Li 已提交
1594 1595
  atomic_add_fetch_64(&totalDumpOutRows, totalRows);

H
hzcheng 已提交
1596 1597
  fprintf(fp, "\n");

H
Hui Li 已提交
1598 1599 1600 1601 1602 1603 1604 1605
  if (tbuf) {
    free(tbuf);
  }
  
  taos_free_result(tmpResult);
  tmpResult = NULL;
  free(tmpCommand);
  free(tmpBuffer);
H
hzcheng 已提交
1606 1607 1608
  return 0;
}

H
Hui Li 已提交
1609
int taosCheckParam(struct arguments *arguments) {
H
hzcheng 已提交
1610 1611 1612 1613 1614 1615 1616 1617 1618
  if (arguments->all_databases && arguments->databases) {
    fprintf(stderr, "conflict option --all-databases and --databases\n");
    return -1;
  }

  if (arguments->start_time > arguments->end_time) {
    fprintf(stderr, "start time is larger than end time\n");
    return -1;
  }
H
Hui Li 已提交
1619
  
H
hzcheng 已提交
1620 1621
  if (arguments->arg_list_len == 0) {
    if ((!arguments->all_databases) && (!arguments->isDumpIn)) {
S
slguan 已提交
1622
      fprintf(stderr, "taosdump requires parameters\n");
H
hzcheng 已提交
1623 1624 1625
      return -1;
    }
  }
H
Hui Li 已提交
1626 1627 1628
/*
  if (arguments->isDumpIn && (strcmp(arguments->outpath, DEFAULT_DUMP_FILE) != 0)) {
    fprintf(stderr, "duplicate parameter input and output file path\n");
H
hzcheng 已提交
1629 1630
    return -1;
  }
H
Hui Li 已提交
1631
*/
S
slguan 已提交
1632 1633 1634 1635 1636
  if (!arguments->isDumpIn && arguments->encode != NULL) {
    fprintf(stderr, "invalid option in dump out\n");
    return -1;
  }

H
Hui Li 已提交
1637 1638 1639 1640 1641
  if (arguments->table_batch <= 0) {
    fprintf(stderr, "invalid option in dump out\n");
    return -1;
  }

H
hzcheng 已提交
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
  return 0;
}

bool isEmptyCommand(char *cmd) {
  char *pchar = cmd;

  while (*pchar != '\0') {
    if (*pchar != ' ') return false;
    pchar++;
  }

  return true;
}

S
slguan 已提交
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
void taosReplaceCtrlChar(char *str) {
  _Bool ctrlOn = false;
  char *pstr = NULL;

  for (pstr = str; *str != '\0'; ++str) {
    if (ctrlOn) {
      switch (*str) {
        case 'n':
          *pstr = '\n';
          pstr++;
          break;
        case 'r':
          *pstr = '\r';
          pstr++;
          break;
        case 't':
          *pstr = '\t';
          pstr++;
          break;
        case '\\':
          *pstr = '\\';
          pstr++;
          break;
        case '\'':
          *pstr = '\'';
          pstr++;
          break;
        default:
          break;
      }
      ctrlOn = false;
    } else {
      if (*str == '\\') {
        ctrlOn = true;
      } else {
        *pstr = *str;
        pstr++;
      }
    }
  }

  *pstr = '\0';
}

H
Hui Li 已提交
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742
char *ascii_literal_list[] = {
    "\\x00", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\x07", "\\x08", "\\t",   "\\n",   "\\x0b", "\\x0c",
    "\\r",   "\\x0e", "\\x0f", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19",
    "\\x1a", "\\x1b", "\\x1c", "\\x1d", "\\x1e", "\\x1f", " ",     "!",     "\\\"",  "#",     "$",     "%",     "&",
    "\\'",   "(",     ")",     "*",     "+",     ",",     "-",     ".",     "/",     "0",     "1",     "2",     "3",
    "4",     "5",     "6",     "7",     "8",     "9",     ":",     ";",     "<",     "=",     ">",     "?",     "@",
    "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",
    "[",     "\\\\",  "]",     "^",     "_",     "`",     "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",     "{",     "|",     "}",     "~",     "\\x7f", "\\x80", "\\x81",
    "\\x82", "\\x83", "\\x84", "\\x85", "\\x86", "\\x87", "\\x88", "\\x89", "\\x8a", "\\x8b", "\\x8c", "\\x8d", "\\x8e",
    "\\x8f", "\\x90", "\\x91", "\\x92", "\\x93", "\\x94", "\\x95", "\\x96", "\\x97", "\\x98", "\\x99", "\\x9a", "\\x9b",
    "\\x9c", "\\x9d", "\\x9e", "\\x9f", "\\xa0", "\\xa1", "\\xa2", "\\xa3", "\\xa4", "\\xa5", "\\xa6", "\\xa7", "\\xa8",
    "\\xa9", "\\xaa", "\\xab", "\\xac", "\\xad", "\\xae", "\\xaf", "\\xb0", "\\xb1", "\\xb2", "\\xb3", "\\xb4", "\\xb5",
    "\\xb6", "\\xb7", "\\xb8", "\\xb9", "\\xba", "\\xbb", "\\xbc", "\\xbd", "\\xbe", "\\xbf", "\\xc0", "\\xc1", "\\xc2",
    "\\xc3", "\\xc4", "\\xc5", "\\xc6", "\\xc7", "\\xc8", "\\xc9", "\\xca", "\\xcb", "\\xcc", "\\xcd", "\\xce", "\\xcf",
    "\\xd0", "\\xd1", "\\xd2", "\\xd3", "\\xd4", "\\xd5", "\\xd6", "\\xd7", "\\xd8", "\\xd9", "\\xda", "\\xdb", "\\xdc",
    "\\xdd", "\\xde", "\\xdf", "\\xe0", "\\xe1", "\\xe2", "\\xe3", "\\xe4", "\\xe5", "\\xe6", "\\xe7", "\\xe8", "\\xe9",
    "\\xea", "\\xeb", "\\xec", "\\xed", "\\xee", "\\xef", "\\xf0", "\\xf1", "\\xf2", "\\xf3", "\\xf4", "\\xf5", "\\xf6",
    "\\xf7", "\\xf8", "\\xf9", "\\xfa", "\\xfb", "\\xfc", "\\xfd", "\\xfe", "\\xff"};

int converStringToReadable(char *str, int size, char *buf, int bufsize) {
  char *pstr = str;
  char *pbuf = buf;
  while (size > 0) {
    if (*pstr == '\0') break;
    pbuf = stpcpy(pbuf, ascii_literal_list[((uint8_t)(*pstr))]);
    pstr++;
    size--;
  }
  *pbuf = '\0';
  return 0;
}

int convertNCharToReadable(char *str, int size, char *buf, int bufsize) {
  char *pstr = str;
  char *pbuf = buf;
  // TODO
  wchar_t wc;
  while (size > 0) {
    if (*pstr == '\0') break;
    int byte_width = mbtowc(&wc, pstr, MB_CUR_MAX);
H
Hui Li 已提交
1743 1744 1745 1746
    if (byte_width < 0) {
      fprintf(stderr, "mbtowc() return fail.\n");
      exit(-1);
    }
H
Hui Li 已提交
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764

    if ((int)wc < 256) {
      pbuf = stpcpy(pbuf, ascii_literal_list[(int)wc]);
    } else {
      memcpy(pbuf, pstr, byte_width);
      pbuf += byte_width;
    }
    pstr += byte_width;
  }

  *pbuf = '\0';

  return 0;
}

void taosDumpCharset(FILE *fp) {
  char charsetline[256];

H
Hui Li 已提交
1765
  (void)fseek(fp, 0, SEEK_SET);
H
Hui Li 已提交
1766
  sprintf(charsetline, "#!%s\n", tsCharset);
H
Hui Li 已提交
1767
  (void)fwrite(charsetline, strlen(charsetline), 1, fp);
H
Hui Li 已提交
1768 1769 1770 1771 1772 1773
}

void taosLoadFileCharset(FILE *fp, char *fcharset) {
  char * line = NULL;
  size_t line_size = 0;

H
Hui Li 已提交
1774
  (void)fseek(fp, 0, SEEK_SET);
H
Hui Li 已提交
1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788
  ssize_t size = getline(&line, &line_size, fp);
  if (size <= 2) {
    goto _exit_no_charset;
  }

  if (strncmp(line, "#!", 2) != 0) {
    goto _exit_no_charset;
  }
  if (line[size - 1] == '\n') {
    line[size - 1] = '\0';
    size--;
  }
  strcpy(fcharset, line + 2);

S
Shengliang Guan 已提交
1789
  taosTFree(line);
H
Hui Li 已提交
1790 1791 1792
  return;

_exit_no_charset:
H
Hui Li 已提交
1793
  (void)fseek(fp, 0, SEEK_SET);
H
Hui Li 已提交
1794
  *fcharset = '\0';
S
Shengliang Guan 已提交
1795
  taosTFree(line);
H
Hui Li 已提交
1796 1797 1798 1799
  return;
}

// ========  dumpIn support multi threads functions ================================//
H
hzcheng 已提交
1800

H
Hui Li 已提交
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
static char    **tsDumpInSqlFiles   = NULL;
static int32_t   tsSqlFileNum = 0;
static char      tsDbSqlFile[TSDB_FILENAME_LEN] = {0};
static char      tsfCharset[64] = {0};
static int taosGetFilesNum(const char *directoryName, const char *prefix)
{
  char cmd[1024] = { 0 };
  sprintf(cmd, "ls %s/*.%s | wc -l ", directoryName, prefix);

  FILE *fp = popen(cmd, "r");
H
hzcheng 已提交
1811
  if (fp == NULL) {
H
Hui Li 已提交
1812 1813
    fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
    exit(0);
H
hzcheng 已提交
1814 1815
  }

H
Hui Li 已提交
1816 1817 1818 1819 1820
  int fileNum = 0;
  if (fscanf(fp, "%d", &fileNum) != 1) {
    fprintf(stderr, "ERROR: failed to execute:%s, parse result error\n", cmd);
    exit(0);
  }
S
slguan 已提交
1821

H
Hui Li 已提交
1822 1823 1824
  if (fileNum <= 0) {
    fprintf(stderr, "ERROR: directory:%s is empry\n", directoryName);
    exit(0);
H
hzcheng 已提交
1825 1826
  }

H
Hui Li 已提交
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
  pclose(fp);
  return fileNum;
}

static void taosParseDirectory(const char *directoryName, const char *prefix, char **fileArray, int totalFiles)
{
  char cmd[1024] = { 0 };
  sprintf(cmd, "ls %s/*.%s | sort", directoryName, prefix);

  FILE *fp = popen(cmd, "r");
  if (fp == NULL) {
    fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
    exit(0);
  }

  int fileNum = 0;
H
Hui Li 已提交
1843
  while (fscanf(fp, "%128s", fileArray[fileNum++])) {
H
Hui Li 已提交
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853
    if (strcmp(fileArray[fileNum-1], tsDbSqlFile) == 0) {
      fileNum--;
    }
    if (fileNum >= totalFiles) {
      break;
    }
  }

  if (fileNum != totalFiles) {
    fprintf(stderr, "ERROR: directory:%s changed while read\n", directoryName);
H
Hui Li 已提交
1854
    pclose(fp);
H
Hui Li 已提交
1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
    exit(0);
  }

  pclose(fp);
}

static void taosCheckTablesSQLFile(const char *directoryName)
{
  char cmd[1024] = { 0 };
  sprintf(cmd, "ls %s/dbs.sql", directoryName);

  FILE *fp = popen(cmd, "r");
  if (fp == NULL) {
    fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno));
    exit(0);
  }

H
Hui Li 已提交
1872
  while (fscanf(fp, "%128s", tsDbSqlFile)) {
H
Hui Li 已提交
1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
    break;
  }

  pclose(fp);
}

static void taosMallocSQLFiles()
{
  tsDumpInSqlFiles = (char**)calloc(tsSqlFileNum, sizeof(char*));
  for (int i = 0; i < tsSqlFileNum; i++) {
    tsDumpInSqlFiles[i] = calloc(1, TSDB_FILENAME_LEN);
  }
}

static void taosFreeSQLFiles()
{
  for (int i = 0; i < tsSqlFileNum; i++) {
S
Shengliang Guan 已提交
1890
    taosTFree(tsDumpInSqlFiles[i]);
H
Hui Li 已提交
1891
  }
S
Shengliang Guan 已提交
1892
  taosTFree(tsDumpInSqlFiles);
H
Hui Li 已提交
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
}

static void taosGetDirectoryFileList(char *inputDir)
{
  struct stat fileStat;
  if (stat(inputDir, &fileStat) < 0) {
    fprintf(stderr, "ERROR: %s not exist\n", inputDir);
    exit(0);
  }

  if (fileStat.st_mode & S_IFDIR) {
    taosCheckTablesSQLFile(inputDir);
    tsSqlFileNum = taosGetFilesNum(inputDir, "sql");
    int totalSQLFileNum = tsSqlFileNum;
    if (tsDbSqlFile[0] != 0) {
      tsSqlFileNum--;
    }
    taosMallocSQLFiles();
    taosParseDirectory(inputDir, "sql", tsDumpInSqlFiles, tsSqlFileNum);
    fprintf(stdout, "\nstart to dispose %d files in %s\n", totalSQLFileNum, inputDir);
  }
  else {
    fprintf(stderr, "ERROR: %s is not a directory\n", inputDir);
    exit(0);
  }
}

static FILE*  taosOpenDumpInFile(char *fptr) {
  wordexp_t full_path;

  if (wordexp(fptr, &full_path, 0) != 0) {
    fprintf(stderr, "ERROR: illegal file name: %s\n", fptr);
    return NULL;
  }

  char *fname = full_path.we_wordv[0];
  
  FILE *f = fopen(fname, "r");
  if (f == NULL) {
    fprintf(stderr, "ERROR: failed to open file %s\n", fname);
    wordfree(&full_path);
    return NULL;
  }

  wordfree(&full_path);

  return f;
}

int taosDumpInOneFile_old(TAOS     * taos, FILE* fp, char* fcharset, char* encode) {
  char     *command       = NULL;
  char     *lcommand      = NULL;
  int       tsize         = 0;
  char     *line          = NULL;
  _Bool     isRun         = true;
  size_t    line_size     = 0;
  char     *pstr          = NULL;
  char     *lstr          = NULL;
  size_t    inbytesleft   = 0;
  size_t    outbytesleft  = COMMAND_SIZE;
  char     *tcommand      = NULL;
  char     *charsetOfFile = NULL;
  iconv_t   cd            = (iconv_t)(-1);

  command  = (char *)malloc(COMMAND_SIZE);
S
slguan 已提交
1958 1959
  lcommand = (char *)malloc(COMMAND_SIZE);
  if (command == NULL || lcommand == NULL) {
H
hzcheng 已提交
1960 1961 1962 1963
    fprintf(stderr, "failed to connect to allocate memory\n");
    goto _dumpin_exit_failure;
  }

S
slguan 已提交
1964 1965
  // Resolve locale
  if (*fcharset != '\0') {
H
Hui Li 已提交
1966 1967 1968
    charsetOfFile = fcharset;
  } else {
    charsetOfFile = encode;
S
slguan 已提交
1969 1970
  }

H
Hui Li 已提交
1971 1972 1973
  if (charsetOfFile != NULL && strcasecmp(tsCharset, charsetOfFile) != 0) {
    cd = iconv_open(tsCharset, charsetOfFile);
    if (cd == ((iconv_t)(-1))) {
S
slguan 已提交
1974 1975 1976 1977 1978
      fprintf(stderr, "Failed to open iconv handle\n");
      goto _dumpin_exit_failure;
    }
  }

H
hzcheng 已提交
1979
  pstr = command;
S
slguan 已提交
1980
  int64_t linenu = 0;
H
hzcheng 已提交
1981 1982
  while (1) {
    ssize_t size = getline(&line, &line_size, fp);
S
slguan 已提交
1983
    linenu++;
H
hzcheng 已提交
1984 1985 1986
    if (size <= 0) break;
    if (size == 1) {
      if (pstr != command) {
S
slguan 已提交
1987 1988 1989 1990 1991
        inbytesleft = pstr - command;
        memset(lcommand, 0, COMMAND_SIZE);
        pstr = command;
        lstr = lcommand;
        outbytesleft = COMMAND_SIZE;
H
Hui Li 已提交
1992
        if (cd != ((iconv_t)(-1))) {
S
slguan 已提交
1993 1994 1995 1996 1997
          iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft);
          tcommand = lcommand;
        } else {
          tcommand = command;
        }
H
Hui Li 已提交
1998
        
S
slguan 已提交
1999
        taosReplaceCtrlChar(tcommand);
H
Hui Li 已提交
2000 2001 2002 2003
        
        if (queryDB(taos, tcommand) != 0) {
          fprintf(stderr, "error sql: linenu: %" PRId64 " failed\n", linenu);
          exit(0);
2004
        }
H
Hui Li 已提交
2005
        
H
hzcheng 已提交
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037
        pstr = command;
        pstr[0] = '\0';
        tsize = 0;
        isRun = true;
      }

      continue;
    }

    /* if (line[0] == '-' && line[1] == '-') continue; */

    line[size - 1] = 0;

    if (tsize + size - 1 > COMMAND_SIZE) {
      fprintf(stderr, "command is too long\n");
      goto _dumpin_exit_failure;
    }

    if (line[size - 2] == '\\') {
      line[size - 2] = ' ';
      isRun = false;
    } else {
      isRun = true;
    }

    memcpy(pstr, line, size - 1);
    pstr += (size - 1);
    *pstr = '\0';

    if (!isRun) continue;

    if (command != pstr && !isEmptyCommand(command)) {
S
slguan 已提交
2038 2039 2040 2041 2042
      inbytesleft = pstr - command;
      memset(lcommand, 0, COMMAND_SIZE);
      pstr = command;
      lstr = lcommand;
      outbytesleft = COMMAND_SIZE;
H
Hui Li 已提交
2043
      if (cd != ((iconv_t)(-1))) {
S
slguan 已提交
2044 2045 2046 2047 2048 2049
        iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft);
        tcommand = lcommand;
      } else {
        tcommand = command;
      }
      taosReplaceCtrlChar(tcommand);
H
Hui Li 已提交
2050 2051 2052
      if (queryDB(taos, tcommand) != 0) {
        fprintf(stderr, "error sql: linenu:%" PRId64 " failed\n", linenu);
        exit(0); 
S
Shuaiqiang Chang 已提交
2053
      }
H
hzcheng 已提交
2054 2055 2056 2057 2058 2059 2060 2061
    }

    pstr = command;
    *pstr = '\0';
    tsize = 0;
  }

  if (pstr != command) {
S
slguan 已提交
2062 2063 2064 2065 2066
    inbytesleft = pstr - command;
    memset(lcommand, 0, COMMAND_SIZE);
    pstr = command;
    lstr = lcommand;
    outbytesleft = COMMAND_SIZE;
H
Hui Li 已提交
2067
    if (cd != ((iconv_t)(-1))) {
S
slguan 已提交
2068 2069 2070 2071 2072 2073
      iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft);
      tcommand = lcommand;
    } else {
      tcommand = command;
    }
    taosReplaceCtrlChar(lcommand);
H
Hui Li 已提交
2074 2075
    if (queryDB(taos, tcommand) != 0)
      fprintf(stderr, "error sql: linenu:%" PRId64 " failed \n", linenu);
H
hzcheng 已提交
2076 2077
  }

H
Hui Li 已提交
2078
  if (cd != ((iconv_t)(-1))) iconv_close(cd);
S
Shengliang Guan 已提交
2079 2080 2081
  taosTFree(line);
  taosTFree(command);
  taosTFree(lcommand);
H
hzcheng 已提交
2082 2083 2084 2085
  taos_close(taos);
  fclose(fp);
  return 0;

S
slguan 已提交
2086
_dumpin_exit_failure:
H
Hui Li 已提交
2087
  if (cd != ((iconv_t)(-1))) iconv_close(cd);
S
Shengliang Guan 已提交
2088 2089
  taosTFree(command);
  taosTFree(lcommand);
H
hzcheng 已提交
2090 2091 2092 2093
  taos_close(taos);
  fclose(fp);
  return -1;
}
S
slguan 已提交
2094

H
Hui Li 已提交
2095 2096 2097 2098 2099 2100
int taosDumpInOneFile(TAOS     * taos, FILE* fp, char* fcharset, char* encode, char* fileName) {
  int       read_len = 0;
  char *    cmd      = NULL;
  size_t    cmd_len  = 0;
  char *    line     = NULL;
  size_t    line_len = 0;
S
slguan 已提交
2101

H
Hui Li 已提交
2102 2103 2104 2105
  cmd  = (char *)malloc(COMMAND_SIZE);
  if (cmd == NULL) {
    fprintf(stderr, "failed to allocate memory\n");
    return -1;
S
slguan 已提交
2106 2107
  }

H
Hui Li 已提交
2108 2109 2110 2111 2112
  int lineNo = 0;
  while ((read_len = getline(&line, &line_len, fp)) != -1) {
    ++lineNo;
    if (read_len >= COMMAND_SIZE) continue;
    line[--read_len] = '\0';
S
slguan 已提交
2113

H
Hui Li 已提交
2114 2115 2116
    //if (read_len == 0 || isCommentLine(line)) {  // line starts with #
    if (read_len == 0 ) { 
      continue;
S
slguan 已提交
2117 2118
    }

H
Hui Li 已提交
2119 2120 2121 2122 2123 2124
    if (line[read_len - 1] == '\\') {
      line[read_len - 1] = ' ';
      memcpy(cmd + cmd_len, line, read_len);
      cmd_len += read_len;
      continue;
    }
S
slguan 已提交
2125

H
Hui Li 已提交
2126
    memcpy(cmd + cmd_len, line, read_len);
H
Hui Li 已提交
2127
    cmd[read_len + cmd_len]= '\0';
H
Hui Li 已提交
2128 2129 2130 2131 2132 2133 2134 2135
    if (queryDB(taos, cmd)) {
      fprintf(stderr, "error sql: linenu:%d, file:%s\n", lineNo, fileName);
    }

    memset(cmd, 0, COMMAND_SIZE);
    cmd_len = 0;
  }

S
Shengliang Guan 已提交
2136 2137
  taosTFree(cmd);
  taosTFree(line);
H
Hui Li 已提交
2138
  fclose(fp);
S
slguan 已提交
2139 2140 2141
  return 0;
}

H
Hui Li 已提交
2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
void* taosDumpInWorkThreadFp(void *arg)
{
  SThreadParaObj *pThread = (SThreadParaObj*)arg;
  for (int32_t f = 0; f < tsSqlFileNum; ++f) {
    if (f % pThread->totalThreads == pThread->threadIndex) {
      char *SQLFileName = tsDumpInSqlFiles[f];
      FILE* fp = taosOpenDumpInFile(SQLFileName);
      if (NULL == fp) {
        continue;
      }
      fprintf(stderr, "Success Open input file: %s\n", SQLFileName);
      taosDumpInOneFile(pThread->taosCon, fp, tsfCharset, tsArguments.encode, SQLFileName);
    }
  }
S
slguan 已提交
2156

H
Hui Li 已提交
2157
  return NULL;
S
slguan 已提交
2158 2159
}

H
Hui Li 已提交
2160 2161 2162 2163 2164
static void taosStartDumpInWorkThreads(struct arguments *args)
{
  pthread_attr_t  thattr;
  SThreadParaObj *pThread;
  int32_t         totalThreads = args->thread_num;
S
slguan 已提交
2165

H
Hui Li 已提交
2166 2167
  if (totalThreads > tsSqlFileNum) {
    totalThreads = tsSqlFileNum;
S
slguan 已提交
2168
  }
H
Hui Li 已提交
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179
  
  SThreadParaObj *threadObj = (SThreadParaObj *)calloc(totalThreads, sizeof(SThreadParaObj));
  for (int32_t t = 0; t < totalThreads; ++t) {
    pThread = threadObj + t;
    pThread->threadIndex = t;
    pThread->totalThreads = totalThreads;
    pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port);
    if (pThread->taosCon == NULL) {
      fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon));
      exit(0);
    }
S
slguan 已提交
2180

H
Hui Li 已提交
2181 2182 2183 2184 2185 2186 2187
    pthread_attr_init(&thattr);
    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);

    if (pthread_create(&(pThread->threadID), &thattr, taosDumpInWorkThreadFp, (void*)pThread) != 0) {
      fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex);
      exit(0);
    }
S
slguan 已提交
2188
  }
H
Hui Li 已提交
2189 2190 2191

  for (int t = 0; t < totalThreads; ++t) {
    pthread_join(threadObj[t].threadID, NULL);
S
slguan 已提交
2192 2193
  }

H
Hui Li 已提交
2194 2195 2196 2197 2198
  for (int t = 0; t < totalThreads; ++t) {
    taos_close(threadObj[t].taosCon);
  }
  free(threadObj);
}
S
slguan 已提交
2199

H
Hui Li 已提交
2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232

int taosDumpIn(struct arguments *arguments) {
  assert(arguments->isDumpIn);
  
  TAOS     *taos    = NULL;
  FILE     *fp      = NULL;

  taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port);
  if (taos == NULL) {
    fprintf(stderr, "failed to connect to TDengine server\n");
    return -1;
  }

  taosGetDirectoryFileList(arguments->inpath);

  if (tsDbSqlFile[0] != 0) {
    fp = taosOpenDumpInFile(tsDbSqlFile);
    if (NULL == fp) {
      fprintf(stderr, "failed to open input file %s\n", tsDbSqlFile);
      return -1;
    }
    fprintf(stderr, "Success Open input file: %s\n", tsDbSqlFile);
    
    taosLoadFileCharset(fp, tsfCharset);
    
    taosDumpInOneFile(taos, fp, tsfCharset, arguments->encode, tsDbSqlFile);
  }

  taosStartDumpInWorkThreads(arguments);

  taos_close(taos);
  taosFreeSQLFiles();
  return 0;
L
lihui 已提交
2233
}
H
Hui Li 已提交
2234 2235