提交 aded75a8 编写于 作者: H huili

[supporting column output per row by row in shell]

上级 1ddd7336
......@@ -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 ****************/
......
......@@ -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(&regex, 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");
......
......@@ -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) {
......
......@@ -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); }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册