diff --git a/src/kit/shell/inc/shell.h b/src/kit/shell/inc/shell.h index e23378b179e7a2291368c03226532d2287ee0232..eca04b31c2013e93610cfdf2b7f6c1d64bfcbe9a 100644 --- a/src/kit/shell/inc/shell.h +++ b/src/kit/shell/inc/shell.h @@ -76,8 +76,8 @@ void source_file(TAOS* con, char* fptr); void get_history_path(char* history); void cleanup_handler(void* arg); void exitShell(); -int shellDumpResult(TAOS* con, char* fname, int* error_no); -void shellPrintNChar(char* str, int width); +int shellDumpResult(TAOS* con, char* fname, int* error_no, bool printMode); +void shellPrintNChar(char* str, int width, bool printMode); #define max(a, b) ((int)(a) < (int)(b) ? (int)(b) : (int)(a)) /**************** Global variable declarations ****************/ diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index 0b276f2f879a5ed03560682c7383612486e0a3ba..15a0114b2ad1043a75efdeb0e4d72ed3918dce28 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -33,13 +33,13 @@ #include "tutil.h" /**************** Global variables ****************/ -char CLIENT_VERSION[] = "Welcome to the TDengine shell, client version:%s "; -char SERVER_VERSION[] = "server version:%s\nCopyright (c) 2017 by TAOS Data, Inc. All rights reserved.\n\n"; -char PROMPT_HEADER[] = "taos> "; -char CONTINUE_PROMPT[] = " -> "; -int prompt_size = 6; +char CLIENT_VERSION[] = "Welcome to the TDengine shell, client version:%s "; +char SERVER_VERSION[] = "server version:%s\nCopyright (c) 2017 by TAOS Data, Inc. All rights reserved.\n\n"; +char PROMPT_HEADER[] = "taos> "; +char CONTINUE_PROMPT[] = " -> "; +int prompt_size = 6; TAOS_RES *result = NULL; -History history; +History history; /* * FUNCTION: Initialize the shell. @@ -111,7 +111,7 @@ TAOS *shellInit(struct arguments *args) { void shellReplaceCtrlChar(char *str) { _Bool ctrlOn = false; char *pstr = NULL; - char quote = 0; + char quote = 0; for (pstr = str; *str != '\0'; ++str) { if (ctrlOn) { @@ -128,6 +128,10 @@ void shellReplaceCtrlChar(char *str) { *pstr = '\t'; pstr++; break; + case 'G': + *pstr++ = '\\'; + *pstr++ = *str; + break; case '\\': *pstr = '\\'; pstr++; @@ -206,11 +210,12 @@ void shellRunCommand(TAOS *con, char *command) { } void shellRunCommandOnServer(TAOS *con, char command[]) { - int64_t st, et; + int64_t st, et; wordexp_t full_path; - char *sptr = NULL; - char *cptr = NULL; - char *fname = NULL; + char * sptr = NULL; + char * cptr = NULL; + char * fname = NULL; + bool printMode = false; if ((sptr = strstr(command, ">>")) != NULL) { cptr = strstr(command, ";"); @@ -226,6 +231,16 @@ void shellRunCommandOnServer(TAOS *con, char command[]) { fname = full_path.we_wordv[0]; } + if ((sptr = strstr(command, "\\G")) != NULL) { + cptr = strstr(command, ";"); + if (cptr != NULL) { + *cptr = '\0'; + } + + *sptr = '\0'; + printMode = true; // When output to a file, the switch does not work. + } + st = taosGetTimestampUs(); if (taos_query(con, command)) { @@ -242,7 +257,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) { int num_fields = taos_field_count(con); if (num_fields != 0) { // select and show kinds of commands int error_no = 0; - int numOfRows = shellDumpResult(con, fname, &error_no); + int numOfRows = shellDumpResult(con, fname, &error_no, printMode); if (numOfRows < 0) return; et = taosGetTimestampUs(); @@ -268,7 +283,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) { /* Function to do regular expression check */ int regex_match(const char *s, const char *reg, int cflags) { regex_t regex; - char msgbuf[100]; + char msgbuf[100]; /* Compile regular expression */ if (regcomp(®ex, reg, cflags) != 0) { @@ -294,16 +309,16 @@ int regex_match(const char *s, const char *reg, int cflags) { return 0; } -int shellDumpResult(TAOS *con, char *fname, int *error_no) { - TAOS_ROW row = NULL; - int numOfRows = 0; - time_t tt; - char buf[25] = "\0"; +int shellDumpResult(TAOS *con, char *fname, int *error_no, bool printMode) { + TAOS_ROW row = NULL; + int numOfRows = 0; + time_t tt; + char buf[25] = "\0"; struct tm *ptm; - int output_bytes = 0; - FILE *fp = NULL; - int num_fields = taos_field_count(con); - wordexp_t full_path; + int output_bytes = 0; + FILE * fp = NULL; + int num_fields = taos_field_count(con); + wordexp_t full_path; assert(num_fields != 0); @@ -333,138 +348,221 @@ int shellDumpResult(TAOS *con, char *fname, int *error_no) { row = taos_fetch_row(result); char t_str[TSDB_MAX_BYTES_PER_ROW] = "\0"; - int l[TSDB_MAX_COLUMNS] = {0}; + int l[TSDB_MAX_COLUMNS] = {0}; + int maxLenColumnName = 0; if (row) { // Print the header indicator if (fname == NULL) { // print to standard output - for (int col = 0; col < num_fields; col++) { - switch (fields[col].type) { - case TSDB_DATA_TYPE_BOOL: - l[col] = max(BOOL_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_TINYINT: - l[col] = max(TINYINT_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_SMALLINT: - l[col] = max(SMALLINT_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_INT: - l[col] = max(INT_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_BIGINT: - l[col] = max(BIGINT_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_FLOAT: - l[col] = max(FLOAT_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_DOUBLE: - l[col] = max(DOUBLE_OUTPUT_LENGTH, strlen(fields[col].name)); - break; - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_NCHAR: - l[col] = max(fields[col].bytes, strlen(fields[col].name)); - /* l[col] = max(BINARY_OUTPUT_LENGTH, strlen(fields[col].name)); */ - break; - case TSDB_DATA_TYPE_TIMESTAMP: { - int32_t defaultWidth = TIMESTAMP_OUTPUT_LENGTH; - if (args.is_raw_time) { - defaultWidth = 14; - } - if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { - defaultWidth += 3; - } - l[col] = max(defaultWidth, strlen(fields[col].name)); - - break; - } - default: - break; - } - - int spaces = (int)(l[col] - strlen(fields[col].name)); - int left_space = spaces / 2; - int right_space = (spaces % 2 ? left_space + 1 : left_space); - printf("%*.s%s%*.s|", left_space, " ", fields[col].name, right_space, " "); - output_bytes += (l[col] + 1); - } - printf("\n"); - for (int k = 0; k < output_bytes; k++) printf("="); - printf("\n"); - - // print the elements - do { - for (int i = 0; i < num_fields; i++) { - if (row[i] == NULL) { - printf("%*s|", l[i], TSDB_DATA_NULL_STR); - continue; - } - - switch (fields[i].type) { + if (!printMode) { + for (int col = 0; col < num_fields; col++) { + switch (fields[col].type) { case TSDB_DATA_TYPE_BOOL: - printf("%*s|", l[i], ((((int)(*((char *)row[i]))) == 1) ? "true" : "false")); + l[col] = max(BOOL_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_TINYINT: - printf("%*d|", l[i], (int)(*((char *)row[i]))); + l[col] = max(TINYINT_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_SMALLINT: - printf("%*d|", l[i], (int)(*((short *)row[i]))); + l[col] = max(SMALLINT_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_INT: - printf("%*d|", l[i], *((int *)row[i])); + l[col] = max(INT_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_BIGINT: -#ifdef WINDOWS - printf("%*lld|", l[i], *((int64_t *)row[i])); -#else - printf("%*ld|", l[i], *((int64_t *)row[i])); -#endif + l[col] = max(BIGINT_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_FLOAT: - printf("%*.5f|", l[i], *((float *)row[i])); + l[col] = max(FLOAT_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_DOUBLE: - printf("%*.9f|", l[i], *((double *)row[i])); + l[col] = max(DOUBLE_OUTPUT_LENGTH, strlen(fields[col].name)); break; case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: - memset(t_str, 0, TSDB_MAX_BYTES_PER_ROW); - memcpy(t_str, row[i], fields[i].bytes); - /* printf("%-*s|",max(fields[i].bytes, strlen(fields[i].name)), - * t_str); */ - /* printf("%-*s|", l[i], t_str); */ - shellPrintNChar(t_str, l[i]); + l[col] = max(fields[col].bytes, strlen(fields[col].name)); + /* l[col] = max(BINARY_OUTPUT_LENGTH, strlen(fields[col].name)); */ break; - case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_TIMESTAMP: { + int32_t defaultWidth = TIMESTAMP_OUTPUT_LENGTH; if (args.is_raw_time) { + defaultWidth = 14; + } + if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { + defaultWidth += 3; + } + l[col] = max(defaultWidth, strlen(fields[col].name)); + + break; + } + default: + break; + } + + int spaces = (int)(l[col] - strlen(fields[col].name)); + int left_space = spaces / 2; + int right_space = (spaces % 2 ? left_space + 1 : left_space); + printf("%*.s%s%*.s|", left_space, " ", fields[col].name, right_space, " "); + output_bytes += (l[col] + 1); + } + printf("\n"); + for (int k = 0; k < output_bytes; k++) printf("="); + printf("\n"); + } else { + for (int col = 0; col < num_fields; col++) { + if (strlen(fields[col].name) > maxLenColumnName) maxLenColumnName = strlen(fields[col].name); + } + } + + // print the elements + do { + if (!printMode) { + for (int i = 0; i < num_fields; i++) { + if (row[i] == NULL) { + printf("%*s|", l[i], TSDB_DATA_NULL_STR); + continue; + } + + switch (fields[i].type) { + case TSDB_DATA_TYPE_BOOL: + printf("%*s|", l[i], ((((int)(*((char *)row[i]))) == 1) ? "true" : "false")); + break; + case TSDB_DATA_TYPE_TINYINT: + printf("%*d|", l[i], (int)(*((char *)row[i]))); + break; + case TSDB_DATA_TYPE_SMALLINT: + printf("%*d|", l[i], (int)(*((short *)row[i]))); + break; + case TSDB_DATA_TYPE_INT: + printf("%*d|", l[i], *((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: #ifdef WINDOWS - printf(" %lld|", *(int64_t *)row[i]); + printf("%*lld|", l[i], *((int64_t *)row[i])); #else - printf(" %ld|", *(int64_t *)row[i]); + printf("%*ld|", l[i], *((int64_t *)row[i])); +#endif + break; + case TSDB_DATA_TYPE_FLOAT: + printf("%*.5f|", l[i], *((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + printf("%*.9f|", l[i], *((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + memset(t_str, 0, TSDB_MAX_BYTES_PER_ROW); + memcpy(t_str, row[i], fields[i].bytes); + /* printf("%-*s|",max(fields[i].bytes, strlen(fields[i].name)), + * t_str); */ + /* printf("%-*s|", l[i], t_str); */ + shellPrintNChar(t_str, l[i], printMode); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + if (args.is_raw_time) { +#ifdef WINDOWS + printf(" %lld|", *(int64_t *)row[i]); +#else + printf(" %ld|", *(int64_t *)row[i]); #endif - } else { - if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { - tt = *(int64_t *)row[i] / 1000000; } else { - tt = *(int64_t *)row[i] / 1000; + if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { + tt = *(int64_t *)row[i] / 1000000; + } else { + tt = *(int64_t *)row[i] / 1000; + } + + ptm = localtime(&tt); + strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); + + if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { + printf(" %s.%06d|", buf, (int)(*(int64_t *)row[i] % 1000000)); + } else { + printf(" %s.%03d|", buf, (int)(*(int64_t *)row[i] % 1000)); + } } + break; + default: + break; + } + } + printf("\n"); + } else { + printf("*************************** %d.row ***************************\n", numOfRows + 1); + for (int i = 0; i < num_fields; i++) { + // 1. print column name + int left_space = (int)(maxLenColumnName - strlen(fields[i].name)); + printf("%*.s%s: ", left_space, " ", fields[i].name); + + // 2. print column value + if (row[i] == NULL) { + printf("%s\n", TSDB_DATA_NULL_STR); + continue; + } - ptm = localtime(&tt); - strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); - - if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { - printf(" %s.%06d|", buf, (int)(*(int64_t *)row[i] % 1000000)); + switch (fields[i].type) { + case TSDB_DATA_TYPE_BOOL: + printf("%s\n", ((((int)(*((char *)row[i]))) == 1) ? "true" : "false")); + break; + case TSDB_DATA_TYPE_TINYINT: + printf("%d\n", (int)(*((char *)row[i]))); + break; + case TSDB_DATA_TYPE_SMALLINT: + printf("%d\n", (int)(*((short *)row[i]))); + break; + case TSDB_DATA_TYPE_INT: + printf("%d\n", *((int *)row[i])); + break; + case TSDB_DATA_TYPE_BIGINT: +#ifdef WINDOWS + printf("%lld\n", *((int64_t *)row[i])); +#else + printf("%ld\n", *((int64_t *)row[i])); +#endif + break; + case TSDB_DATA_TYPE_FLOAT: + printf("%.5f\n", *((float *)row[i])); + break; + case TSDB_DATA_TYPE_DOUBLE: + printf("%.9f\n", *((double *)row[i])); + break; + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + memset(t_str, 0, TSDB_MAX_BYTES_PER_ROW); + memcpy(t_str, row[i], fields[i].bytes); + l[i] = max(fields[i].bytes, strlen(fields[i].name)); + shellPrintNChar(t_str, l[i], printMode); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + if (args.is_raw_time) { +#ifdef WINDOWS + printf("%lld\n", *(int64_t *)row[i]); +#else + printf("%ld\n", *(int64_t *)row[i]); +#endif } else { - printf(" %s.%03d|", buf, (int)(*(int64_t *)row[i] % 1000)); + if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { + tt = *(int64_t *)row[i] / 1000000; + } else { + tt = *(int64_t *)row[i] / 1000; + } + + ptm = localtime(&tt); + strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); + + if (taos_result_precision(result) == TSDB_TIME_PRECISION_MICRO) { + printf("%s.%06d\n", buf, (int)(*(int64_t *)row[i] % 1000000)); + } else { + printf("%s.%03d\n", buf, (int)(*(int64_t *)row[i] % 1000)); + } } - } - break; - default: - break; + break; + default: + break; + } } } - printf("\n"); numOfRows++; } while ((row = taos_fetch_row(result))); @@ -546,9 +644,9 @@ void read_history() { memset(history.hist, 0, sizeof(char *) * MAX_HISTORY_SIZE); history.hstart = 0; history.hend = 0; - char *line = NULL; + char * line = NULL; size_t line_size = 0; - int read_size = 0; + int read_size = 0; char f_history[TSDB_FILENAME_LEN]; get_history_path(f_history); @@ -614,11 +712,11 @@ static int isCommentLine(char *line) { void source_file(TAOS *con, char *fptr) { wordexp_t full_path; - int read_len = 0; - char *cmd = malloc(MAX_COMMAND_SIZE); - size_t cmd_len = 0; - char *line = NULL; - size_t line_len = 0; + int read_len = 0; + char * cmd = malloc(MAX_COMMAND_SIZE); + size_t cmd_len = 0; + char * line = NULL; + size_t line_len = 0; if (wordexp(fptr, &full_path, 0) != 0) { fprintf(stderr, "ERROR: illegal file name\n"); diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index bdb233e367fef6f3a4a5d19235fec163354952e5..84437389efe5a95e5626e830940ef3ce07fe837e 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -305,7 +305,7 @@ void *shellLoopQuery(void *arg) { return NULL; } -void shellPrintNChar(char *str, int width) { +void shellPrintNChar(char *str, int width, bool printMode) { int col_left = width; wchar_t wc; while (col_left > 0) { @@ -323,7 +323,12 @@ void shellPrintNChar(char *str, int width) { printf(" "); col_left--; } - printf("|"); + + if (!printMode) { + printf("|"); + } else { + printf("\n"); + } } int get_old_terminal_mode(struct termios *tio) { diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index 325a81a91ec3e911d93f598defb3cd35871ac12d..bffee5390b1becc537242e49b4eb8e9f34da61c7 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -216,7 +216,7 @@ void *shellLoopQuery(void *arg) { return NULL; } -void shellPrintNChar(char *str, int width) { +void shellPrintNChar(char *str, int width, bool printMode) { int col_left = width; wchar_t wc; while (col_left > 0) { @@ -234,7 +234,12 @@ void shellPrintNChar(char *str, int width) { printf(" "); col_left--; } - printf("|"); + + if (!printMode) { + printf("|"); + } else { + printf("\n"); + } } void get_history_path(char *history) { sprintf(history, "%s/%s", ".", HISTORY_FILE); }