Commit e30e0b7c authored by Magne Mahre's avatar Magne Mahre

Bug#26780: automatic vertical output for wide results

  
Feature from Eric Bergen, CLA signed 2007-06-27.
  
Adds new mysql client option "--auto-vertical-output", which causes
the client to test whether a result table is too wide for the current
window (where available) and emit vertical results in that case.
Otherwise, it sends normal tabular results.
parent df6d4bf1
...@@ -78,6 +78,7 @@ enum options_client ...@@ -78,6 +78,7 @@ enum options_client
OPT_SLAP_DETACH, OPT_SLAP_DETACH,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID, OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT, OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
OPT_AUTO_VERTICAL_OUTPUT,
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE, OPT_WRITE_BINLOG, OPT_DUMP_DATE,
OPT_INIT_COMMAND, OPT_INIT_COMMAND,
......
...@@ -143,6 +143,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, ...@@ -143,6 +143,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1, tty_password= 0, opt_nobeep=0, opt_reconnect=1,
opt_secure_auth= 0, opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0, default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, interrupted_query= 0, show_warnings= 0, executing_query= 0, interrupted_query= 0,
ignore_spaces= 0; ignore_spaces= 0;
static my_bool debug_info_flag, debug_check_flag; static my_bool debug_info_flag, debug_check_flag;
...@@ -185,6 +186,7 @@ static MEM_ROOT hash_mem_root; ...@@ -185,6 +186,7 @@ static MEM_ROOT hash_mem_root;
static uint prompt_counter; static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER; static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1; static uint delimiter_length= 1;
unsigned short terminal_width= 80;
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
static char *shared_memory_base_name=0; static char *shared_memory_base_name=0;
...@@ -238,6 +240,8 @@ static const char* construct_prompt(); ...@@ -238,6 +240,8 @@ static const char* construct_prompt();
static char *get_arg(char *line, my_bool get_next_arg); static char *get_arg(char *line, my_bool get_next_arg);
static void init_username(); static void init_username();
static void add_int_to_prompt(int toadd); static void add_int_to_prompt(int toadd);
static int get_result_width(MYSQL_RES *res);
static int get_field_disp_length(MYSQL_FIELD * field);
/* A structure which contains information on the commands this program /* A structure which contains information on the commands this program
can understand. */ can understand. */
...@@ -1065,6 +1069,10 @@ static void mysql_end_timer(ulong start_time,char *buff); ...@@ -1065,6 +1069,10 @@ static void mysql_end_timer(ulong start_time,char *buff);
static void nice_time(double sec,char *buff,bool part_second); static void nice_time(double sec,char *buff,bool part_second);
extern "C" sig_handler mysql_end(int sig); extern "C" sig_handler mysql_end(int sig);
extern "C" sig_handler handle_sigint(int sig); extern "C" sig_handler handle_sigint(int sig);
#if defined(HAVE_TERMIOS_H)
static sig_handler window_resize(int sig);
#endif
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
...@@ -1144,8 +1152,8 @@ int main(int argc,char *argv[]) ...@@ -1144,8 +1152,8 @@ int main(int argc,char *argv[])
if (sql_connect(current_host,current_db,current_user,opt_password, if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent)) opt_silent))
{ {
quick=1; // Avoid history quick= 1; // Avoid history
status.exit_status=1; status.exit_status= 1;
mysql_end(-1); mysql_end(-1);
} }
if (!status.batch) if (!status.batch)
...@@ -1157,6 +1165,13 @@ int main(int argc,char *argv[]) ...@@ -1157,6 +1165,13 @@ int main(int argc,char *argv[])
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
#if defined(HAVE_TERMIOS_H)
/* Readline will call this if it installs a handler */
signal(SIGWINCH, window_resize);
/* call the SIGWINCH handler to get the default term width */
window_resize(0);
#endif
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.", put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
INFO_INFO); INFO_INFO);
sprintf((char*) glob_buffer.ptr(), sprintf((char*) glob_buffer.ptr(),
...@@ -1315,6 +1330,16 @@ sig_handler handle_sigint(int sig) ...@@ -1315,6 +1330,16 @@ sig_handler handle_sigint(int sig)
} }
#if defined(HAVE_TERMIOS_H)
sig_handler window_resize(int sig)
{
struct winsize window_size;
if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
terminal_width= window_size.ws_col;
}
#endif
static struct my_option my_long_options[] = static struct my_option my_long_options[] =
{ {
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
...@@ -1332,6 +1357,9 @@ static struct my_option my_long_options[] = ...@@ -1332,6 +1357,9 @@ static struct my_option my_long_options[] =
{"no-auto-rehash", 'A', {"no-auto-rehash", 'A',
"No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.", "No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
"Automatically switch to vertical output mode if the result is wider than the terminal width.",
(uchar**) &auto_vertical_output, (uchar**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"batch", 'B', {"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, "Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR, {"character-sets-dir", OPT_CHARSETS_DIR,
...@@ -3038,7 +3066,7 @@ com_go(String *buffer,char *line __attribute__((unused))) ...@@ -3038,7 +3066,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result); print_table_data_html(result);
else if (opt_xml) else if (opt_xml)
print_table_data_xml(result); print_table_data_xml(result);
else if (vertical) else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
print_table_data_vertically(result); print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables) else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result); print_tab_data(result);
...@@ -3369,6 +3397,65 @@ print_table_data(MYSQL_RES *result) ...@@ -3369,6 +3397,65 @@ print_table_data(MYSQL_RES *result)
my_afree((uchar*) num_flag); my_afree((uchar*) num_flag);
} }
/**
Return the length of a field after it would be rendered into text.
This doesn't know or care about multibyte characters. Assume we're
using such a charset. We can't know that all of the upcoming rows
for this column will have bytes that each render into some fraction
of a character. It's at least possible that a row has bytes that
all render into one character each, and so the maximum length is
still the number of bytes. (Assumption 1: This can't be better
because we can never know the number of characters that the DB is
going to send -- only the number of bytes. 2: Chars <= Bytes.)
@param field Pointer to a field to be inspected
@returns number of character positions to be used, at most
*/
static int get_field_disp_length(MYSQL_FIELD *field)
{
uint length= column_names ? field->name_length : 0;
if (quick)
length= max(length, field->length);
else
length= max(length, field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length= 4; /* Room for "NULL" */
return length;
}
/**
For a new result, return the max number of characters that any
upcoming row may return.
@param result Pointer to the result to judge
@returns The max number of characters in any row of this result
*/
static int get_result_width(MYSQL_RES *result)
{
unsigned int len= 0;
MYSQL_FIELD *field;
MYSQL_FIELD_OFFSET offset;
#ifndef DBUG_OFF
offset= mysql_field_tell(result);
DBUG_ASSERT(offset == 0);
#else
offset= 0;
#endif
while ((field= mysql_fetch_field(result)) != NULL)
len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
(void) mysql_field_seek(result, offset);
return len + 1; /* plus final bar. */
}
static void static void
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified) tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
......
...@@ -201,6 +201,202 @@ COUNT (*) ...@@ -201,6 +201,202 @@ COUNT (*)
ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno) ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno)
End of 5.0 tests End of 5.0 tests
WARNING: --server-arg option not supported in this configuration. WARNING: --server-arg option not supported in this configuration.
*************************** 1. row ***************************
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
0: 0
+---+
| 1 |
+---+
| 1 |
+---+
Warning (Code 1286): Unknown table engine 'nonexistent' Warning (Code 1286): Unknown table engine 'nonexistent'
Warning (Code 1266): Using storage engine MyISAM for table 't2' Warning (Code 1266): Using storage engine MyISAM for table 't2'
Warning (Code 1286): Unknown table engine 'nonexistent2' Warning (Code 1286): Unknown table engine 'nonexistent2'
......
...@@ -366,6 +366,14 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; ...@@ -366,6 +366,14 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql;
--exec $MYSQL --server-arg=no-defaults test -e "quit" --exec $MYSQL --server-arg=no-defaults test -e "quit"
--enable_query_log --enable_query_log
#
# Bug#26780: patch to add auto vertical output option to the cli.
#
# Make this wide enough that it will wrap almost everywhere.
--exec $MYSQL test --auto-vertical-output --table -e "SELECT 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0;"
# Too short to wrap.
--exec $MYSQL test --auto-vertical-output --table -e "SELECT 1;"
# #
# Bug #25146: Some warnings/errors not shown when using --show-warnings # Bug #25146: Some warnings/errors not shown when using --show-warnings
# #
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment