mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
478
scripts/mysql_tableinfo.sh
Normal file
478
scripts/mysql_tableinfo.sh
Normal file
@ -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.
|
Reference in New Issue
Block a user