diff options
author | unknown <monty@hundin.mysql.fi> | 2002-06-27 11:27:04 +0300 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2002-06-27 11:27:04 +0300 |
commit | 835a75c97bbc31e35e25171db9c046ec1dae5b87 (patch) | |
tree | 857f8b9d553911f4937bee644ea5d2c3606e8e58 /scripts | |
parent | d471ad0c236d2d2ff23e75dc02e3095e5edb7f17 (diff) | |
download | mariadb-git-835a75c97bbc31e35e25171db9c046ec1dae5b87.tar.gz |
Removed mysql_ssl_clear()
Added statistics information for alarms (for bug tracking)
Don't store "incomplete" in the xxx.cfg file if we are not using --restart. (Crash-me)
Enlarged STACK_BUF_ALLOC becasue of failed crash-me test
Aded new script mysql_tableinfo to make a system directory.
Docs/manual.texi:
Changelog and TODO
include/mysql.h:
Removed mysql_ssl_clear() (One should use mysql_close() instead)
include/thr_alarm.h:
Added info for alarms
libmysql/libmysql.c:
Made mysql_ssl_clear() static
libmysql/libmysql.def:
cleanup
libmysqld/libmysqld.def:
cleanup
myisam/myisamchk.c:
describe -> description
myisam/myisampack.c:
Fixed copyright.
mysys/thr_alarm.c:
Added statistics information for alarms (for bug tracking)
scripts/Makefile.am:
Added mysql_table_info
sql-bench/crash-me.sh:
Don't store "incomplete" in the xxx.cfg file if we are not using --restart.
This was done becasue "incomplete" made it harder to quickly repeat a test that
failed.
sql-bench/limits/mysql.cfg:
Update to 1.58
sql/hostname.cc:
Remved compiler warning
sql/item_func.cc:
cleanup
sql/item_func.h:
Cleanup
sql/mysql_priv.h:
Enlarged STACK_BUF_ALLOC becasue of failed crash-me test
sql/opt_range.cc:
Removed purify warning
sql/sql_parse.cc:
cleanup
sql/sql_test.cc:
Added ala
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile.am | 2 | ||||
-rw-r--r-- | scripts/mysql_tableinfo.sh | 478 |
2 files changed, 480 insertions, 0 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 913e62050fa..1469f3f2f2d 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -31,6 +31,7 @@ bin_SCRIPTS = @server_scripts@ \ mysqlhotcopy \ mysqldumpslow \ mysql_explain_log \ + mysql_tableinfo \ mysqld_multi EXTRA_SCRIPTS = make_binary_distribution.sh \ @@ -50,6 +51,7 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ mysqldumpslow.sh \ mysql_explain_log.sh \ mysqld_multi.sh \ + mysql_tableinfo.sh \ mysqld_safe.sh EXTRA_DIST = $(EXTRA_SCRIPTS) \ diff --git a/scripts/mysql_tableinfo.sh b/scripts/mysql_tableinfo.sh new file mode 100644 index 00000000000..bfe9be377c7 --- /dev/null +++ b/scripts/mysql_tableinfo.sh @@ -0,0 +1,478 @@ +#!@PERL@ -w + +use strict; +use Getopt::Long; +use DBI; + +=head1 NAME + +mysql_tableinfo - creates and populates information tables with +the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS), +SHOW COLUMNS and SHOW INDEX. + +This is version 1.0. + +=head1 SYNOPSIS + + mysql_tableinfo [OPTIONS] database_to_write [database_like_wild] [table_like_wild] + + Do not backquote (``) database_to_write, + and do not quote ('') database_like_wild or table_like_wild + + Examples: + + mysql_tableinfo info + + mysql_tableinfo info this_db + + mysql_tableinfo info %a% b% + + mysql_tableinfo info --clear-only + + mysql_tableinfo info --col --idx --table-status + +=cut + +# Documentation continued at end of file + + +sub usage { + die @_,"\nExecute 'perldoc $0' for documentation\n"; +} + +my %opt = ( + 'user' => scalar getpwuid($>), + 'host' => "localhost", + 'prefix' => "", #to avoid 'use of uninitialized value...' +); +Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P +GetOptions( \%opt, + "help", + "user|u=s", + "password|p=s", + "host|h=s", + "port|P=s", + "socket|S=s", + "tbl-status", + "col", + "idx", + "clear", + "clear-only", + "prefix=s", + "quiet|q", +) or usage("Invalid option"); + +if ($opt{help}) {usage();} + +my ($db_to_write,$db_like_wild,$tbl_like_wild); +if (@ARGV==0) +{ + usage("Not enough arguments"); +} +$db_to_write="`$ARGV[0]`"; shift @ARGV; +$db_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV; +$tbl_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV; +if (@ARGV>0) { usage("Too many arguments"); } + +my $info_db="`".$opt{'prefix'}."db`"; +my $info_tbl="`".$opt{'prefix'}."tbl". + (($opt{'tbl-status'})?"_status":"")."`"; +my $info_col="`".$opt{'prefix'}."col`"; +my $info_idx="`".$opt{'prefix'}."idx`"; + + +# --- connect to the database --- + +my $dsn = ";host=$opt{'host'}"; +$dsn .= ";port=$opt{port}" if $opt{port}; +$dsn .= ";mysql_socket=$opt{socket}" if $opt{socket}; + +my $dbh = DBI->connect("dbi:mysql:$dsn;mysql_read_default_group=perl", + $opt{user}, $opt{password}, +{ + RaiseError => 1, + PrintError => 0, + AutoCommit => 1, +}); + +$db_like_wild=$dbh->quote($db_like_wild); +$tbl_like_wild=$dbh->quote($tbl_like_wild); + +#Ask + +if (!$opt{'quiet'}) +{ + print "\n!! This program is doing to do:\n\n"; + print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'}); + print "**DELETE** FROM ... WHERE `Database LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild +**INSERT** INTO ... + +on the following tables :\n"; + my $i; + foreach $i (($info_db, $info_tbl), + (($opt{'col'})?$info_col:()), + (($opt{'idx'})?$info_idx:())) + { + print(" $db_to_write.$i\n"); + } + print "\nContinue (you can skip this confirmation step with --quiet) ? (y|n) [n]"; + my $answer=<STDIN>; + unless ($answer =~ /^\s*y\s*$/i) + { + print "Nothing done!\n";exit; + } +} + +if ($opt{'clear'} or $opt{'clear-only'}) +{ +#do not drop the $db_to_write database ! + my $i; + foreach $i (($info_db, $info_tbl), + (($opt{'col'})?$info_col:()), + (($opt{'idx'})?$info_idx:())) + { + $dbh->do("DROP TABLE IF EXISTS $db_to_write.$i"); + } + if ($opt{'clear-only'}) + { + print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'}); + exit(); + } +} + + +my %sth; +my %extra_col_desc; +my %row; +my %done_create_table; + +#create the $db_to_write database +$dbh->do("CREATE DATABASE IF NOT EXISTS $db_to_write"); +$dbh->do("USE $db_to_write"); + +#get databases +$sth{db}=$dbh->prepare("SHOW DATABASES LIKE $db_like_wild"); +$sth{db}->execute; + +#create $info_db which will receive info about databases. +#Ensure that the first column to be called "Database" (as SHOW DATABASES LIKE +#returns a varying +#column name (of the form "Database (%...)") which is not suitable) +$extra_col_desc{db}=do_create_table("db",$info_db,undef,"`Database`"); +#we'll remember the type of the `Database` column (as returned by +#SHOW DATABASES), which we will need when creating the next tables. + +#clear out-of-date info from this table +$dbh->do("DELETE FROM $info_db WHERE `Database` LIKE $db_like_wild"); + + +while (@{$row{db}}=$sth{db}->fetchrow_array) #go through all databases +{ + +#insert the database name + $dbh->do("INSERT INTO $info_db VALUES(" + .join_quote(@{$row{db}}).")"); + +#for each database, get tables + + $sth{tbl}=$dbh->prepare("SHOW TABLE" + .( ($opt{'tbl-status'}) ? + " STATUS" + : "S" ) + ." from `${$row{db}}[0]` LIKE $tbl_like_wild"); + $sth{tbl}->execute; + unless ($done_create_table{$info_tbl}) + +#tables must be created only once, and out-of-date info must be +#cleared once + { + $done_create_table{$info_tbl}=1; + $extra_col_desc{table}= + do_create_table("tbl",$info_tbl, +#add an extra column (database name) at the left +#and ensure that the table name will be called "Table" +#(this is unncessesary with +#SHOW TABLE STATUS, but necessary with SHOW TABLES (which returns a column +#named "Tables_in_...")) + "`Database` ".$extra_col_desc{db},"`Table`"); + $dbh->do("DELETE FROM $info_tbl WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild"); + } + + while (@{$row{tbl}}=$sth{tbl}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_tbl VALUES(" + .$dbh->quote(${$row{db}}[0]).",".join_quote(@{$row{tbl}}).")"); + +#for each table, get columns... + + if ($opt{'col'}) + { + $sth{col}=$dbh->prepare("SHOW COLUMNS FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`"); + $sth{col}->execute; + unless ($done_create_table{$info_col}) + { + $done_create_table{$info_col}=1; + do_create_table("col",$info_col, + "`Database` ".$extra_col_desc{db}."," + ."`Table` ".$extra_col_desc{table}."," + ."`Seq_in_table` BIGINT(3)"); +#We need to add a sequence number (1 for the first column of the table, +#2 for the second etc) so that users are able to retrieve columns in order +#if they want. This is not needed for INDEX +#(where there is already Seq_in_index) + $dbh->do("DELETE FROM $info_col WHERE `Database` + LIKE $db_like_wild + AND `Table` LIKE $tbl_like_wild"); + } + my $col_number=0; + while (@{$row{col}}=$sth{col}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_col VALUES(" + .$dbh->quote(${$row{db}}[0])."," + .$dbh->quote(${$row{tbl}}[0])."," + .++$col_number."," + .join_quote(@{$row{col}}).")"); + } + } + +#and get index. + + if ($opt{'idx'}) + { + $sth{idx}=$dbh->prepare("SHOW INDEX FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`"); + $sth{idx}->execute; + unless ($done_create_table{$info_idx}) + { + $done_create_table{$info_idx}=1; + do_create_table("idx",$info_idx, + "`Database` ".$extra_col_desc{db}); + $dbh->do("DELETE FROM $info_idx WHERE `Database` + LIKE $db_like_wild + AND `Table` LIKE $tbl_like_wild"); + } + while (@{$row{idx}}=$sth{idx}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_idx VALUES(" + .$dbh->quote(${$row{db}}[0])."," + .join_quote(@{$row{idx}}).")"); + } + } + } +} + +print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'}); +exit; + +sub join_quote +{ + my (@list)=@_; my $i; + foreach $i (@list) { $i=$dbh->quote($i); } + return (join ',',@list); +} + +sub do_create_table +{ + my ($sth_key,$target_tbl,$extra_col_desc,$first_col_name)=@_; + my $create_table_query=$extra_col_desc; + my ($i,$type,$first_col_desc,$col_desc); + + for ($i=0;$i<$sth{$sth_key}->{NUM_OF_FIELDS};$i++) + { + if ($create_table_query) { $create_table_query.=", "; } + $type=$sth{$sth_key}->{mysql_type_name}->[$i]; + $col_desc=$type; + if ($type =~ /char|int/i) + { + $col_desc.="($sth{$sth_key}->{PRECISION}->[$i])"; + } + elsif ($type =~ /decimal|numeric/i) #(never seen that) + { + $col_desc.= + "($sth{$sth_key}->{PRECISION}->[$i],$sth{$sth_key}->{SCALE}->[$i])"; + } + elsif ($type !~ /date/i) #date and datetime are OK, + #no precision or scale for them + { + warn "unexpected column type '$type' +(neither 'char','int','decimal|numeric') +when creating $target_tbl, hope table creation will go OK\n"; + } + if ($i==0) {$first_col_desc=$col_desc}; + $create_table_query.= + ( ($i==0 and $first_col_name) ? + "$first_col_name " :"`$sth{$sth_key}->{NAME}->[$i]` " ) + .$col_desc; + } +if ($create_table_query) +{ + $dbh->do("CREATE TABLE IF NOT EXISTS $target_tbl ($create_table_query)"); +} +return $first_col_desc; +} + +__END__ + + +=head1 DESCRIPTION + +mysql_tableinfo asks a MySQL server information about its +databases, tables, table columns and index, and stores this +in tables called `db`, `tbl` (or `tbl_status`), `col`, `idx` +(with an optional prefix specified with --prefix). +After that, you can query these information tables, for example +to build your admin scripts with SQL queries, like + +SELECT CONCAT("CHECK TABLE ",`database`,".",`table`," EXTENDED;") +FROM info.tbl WHERE ... ; + +as people usually do with some other RDBMS +(note: to increase the speed of your queries on the info tables, +you may add some index on them). + +The database_like_wild and table_like_wild instructs the program +to gather information only about databases and tables +whose names match these patterns. If the info +tables already exist, their rows matching the patterns are simply +deleted and replaced by the new ones. That is, +old rows not matching the patterns are not touched. +If the database_like_wild and table_like_wild arguments +are not specified on the command-line they default to "%". + +The program : + +- does CREATE DATABASE IF NOT EXISTS database_to_write +where database_to_write is the database name specified on the command-line. + +- does CREATE TABLE IF NOT EXISTS database_to_write.`db` + +- fills database_to_write.`db` with the output of +SHOW DATABASES LIKE database_like_wild + +- does CREATE TABLE IF NOT EXISTS database_to_write.`tbl` +(respectively database_to_write.`tbl_status` +if the --tbl-status option is on) + +- for every found database, +fills database_to_write.`tbl` (respectively database_to_write.`tbl_status`) +with the output of +SHOW TABLES FROM found_db LIKE table_like_wild +(respectively SHOW TABLE STATUS FROM found_db LIKE table_like_wild) + +- if the --col option is on, + * does CREATE TABLE IF NOT EXISTS database_to_write.`col` + * for every found table, + fills database_to_write.`col` with the output of + SHOW COLUMNS FROM found_tbl FROM found_db + +- if the --idx option is on, + * does CREATE TABLE IF NOT EXISTS database_to_write.`idx` + * for every found table, + fills database_to_write.`idx` with the output of + SHOW INDEX FROM found_tbl FROM found_db + +Some options may modify this general scheme (see below). + +As mentioned, the contents of the info tables are the output of +SHOW commands. In fact the contents are slightly more complete : + +- the `tbl` (or `tbl_status`) info table + has an extra column which contains the database name, + +- the `col` info table + has an extra column which contains the table name, + and an extra column which contains, for each described column, + the number of this column in the table owning it (this extra column + is called `Seq_in_table`). `Seq_in_table` makes it possible for you + to retrieve your columns in sorted order, when you are querying + the `col` table. + +- the `index` info table + has an extra column which contains the database name. + +Caution: info tables contain certain columns (e.g. +Database, Table, Null...) whose names, as they are MySQL reserved words, +need to be backquoted (`...`) when used in SQL statements. + +=head1 OPTIONS + +=over 4 + +=item --clear + +Does DROP TABLE on the info tables (only those that the program is +going to fill, for example if you do not use --col it won't drop +the `col` table) and processes normally. Does not drop database_to_write. + +=item --clear-only + +Same as --clear but exits after the DROPs. + +=item --col + +Adds columns information (into table `col`). + +=item --idx + +Adds index information (into table `idx`). + +=item --prefix prefix + +The info tables are named from the concatenation of prefix and, +respectively, db, tbl (or tbl_status), col, idx. Do not quote ('') +or backquote (``) prefix. + +=item -q, --quiet + +Does not warn you about what the script is going to do (DROP TABLE etc) +and does not ask for a confirmation before starting. + +=item --tbl-status + +Instead of using SHOW TABLES, uses SHOW TABLE STATUS +(much more complete information, but slower). + +=item --help + +Display helpscreen and exit + +=item -u, --user=# + +user for database login if not current user. Give a user +who has sufficient privileges (CREATE, ...). + +=item -p, --password=# + +password to use when connecting to server + +=item -h, --host=# + +host to connect to + +=item -P, --port=# + +port to use when connecting to server + +=item -S, --socket=# + +UNIX domain socket to use when connecting to server + +=head1 WARRANTY + +This software is free and comes without warranty of any kind. You +should never trust backup software without studying the code yourself. +Study the code inside this script and only rely on it if I<you> believe +that it does the right thing for you. + +Patches adding bug fixes, documentation and new features are welcome. + +=head1 TO DO + +Use extended inserts to be faster (for servers with many databases +or tables). But to do that, must care about net-buffer-length. + +=head1 AUTHOR + +2002-06-18 Guilhem Bichot (guilhem.bichot@mines-paris.org) + +And all the authors of mysqlhotcopy, which served as a model for +the structure of the program. |