mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
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.
This commit is contained in:
@ -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,
|
|||||||
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;
|
|||||||
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();
|
|||||||
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);
|
|||||||
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[])
|
|||||||
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[])
|
|||||||
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 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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[] =
|
|||||||
{"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)))
|
|||||||
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)
|
|||||||
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 (*)
|
|||||||
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;
|
|||||||
--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
|
||||||
#
|
#
|
||||||
|
Reference in New Issue
Block a user