home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / mysql / scripts / mysql_tableinfo < prev    next >
Text File  |  2008-04-17  |  14KB  |  495 lines

  1. #!@PERL@ -w
  2.  
  3. use strict;
  4. use Getopt::Long;
  5. use DBI;
  6.  
  7. =head1 NAME
  8.  
  9. WARNING: MySQL versions 5.0 and above feature the INFORMATION_SCHEMA
  10. pseudo-database which contains always up-to-date metadata information
  11. about all tables. So instead of using this script one can now
  12. simply query the INFORMATION_SCHEMA.SCHEMATA, INFORMATION_SCHEMA.TABLES,
  13. INFORMATION_SCHEMA.COLUMNS, INFORMATION_SCHEMA.STATISTICS pseudo-tables.
  14. Please see the MySQL manual for more information about INFORMATION_SCHEMA.
  15. This script will be removed from the MySQL distribution in version 5.1.
  16.  
  17. mysql_tableinfo - creates and populates information tables with 
  18. the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS), 
  19. SHOW COLUMNS and SHOW INDEX.
  20.  
  21. This is version 1.1.
  22.  
  23. =head1 SYNOPSIS
  24.  
  25.   mysql_tableinfo [OPTIONS] database_to_write [database_like_wild] [table_like_wild]
  26.  
  27.   Do not backquote (``) database_to_write, 
  28.   and do not quote ('') database_like_wild or table_like_wild
  29.  
  30.   Examples:
  31.  
  32.   mysql_tableinfo info
  33.  
  34.   mysql_tableinfo info this_db
  35.  
  36.   mysql_tableinfo info %a% b%
  37.  
  38.   mysql_tableinfo info --clear-only
  39.  
  40.   mysql_tableinfo info --col --idx --table-status
  41.  
  42. =cut
  43.  
  44. # Documentation continued at end of file
  45.  
  46.  
  47. sub usage {
  48.     die @_,"\nExecute 'perldoc $0' for documentation\n";
  49. }
  50.  
  51. my %opt = (
  52.     'user'    => scalar getpwuid($>),
  53.     'host'      => "localhost",
  54.     'prefix'    => "", #to avoid 'use of uninitialized value...'
  55. );
  56. Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P
  57. GetOptions( \%opt,
  58.     "help",
  59.     "user|u=s",
  60.     "password|p=s",
  61.     "host|h=s",
  62.     "port|P=s",
  63.     "socket|S=s",
  64.     "tbl-status",
  65.     "col",
  66.     "idx",
  67.     "clear",
  68.     "clear-only",
  69.     "prefix=s",
  70.     "quiet|q",
  71. ) or usage("Invalid option");
  72.  
  73. if (!$opt{'quiet'})
  74.     {
  75.     print <<EOF
  76. WARNING: MySQL versions 5.0 and above feature the INFORMATION_SCHEMA
  77. pseudo-database which contains always up-to-date metadata information
  78. about all tables. So instead of using this script one can now
  79. simply query the INFORMATION_SCHEMA.SCHEMATA, INFORMATION_SCHEMA.TABLES,
  80. INFORMATION_SCHEMA.COLUMNS, INFORMATION_SCHEMA.STATISTICS pseudo-tables.
  81. Please see the MySQL manual for more information about INFORMATION_SCHEMA.
  82. This script will be removed from the MySQL distribution in version 5.1.
  83. EOF
  84.     }
  85.  
  86. if ($opt{'help'}) {usage();}
  87.  
  88. my ($db_to_write,$db_like_wild,$tbl_like_wild);
  89. if (@ARGV==0)
  90. {
  91.     usage("Not enough arguments");
  92. }
  93. $db_to_write="`$ARGV[0]`"; shift @ARGV;
  94. $db_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
  95. $tbl_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
  96. if (@ARGV>0) { usage("Too many arguments"); }
  97.  
  98. $0 = $1 if $0 =~ m:/([^/]+)$:;
  99.  
  100. my $info_db="`".$opt{'prefix'}."db`";
  101. my $info_tbl="`".$opt{'prefix'}."tbl".
  102.     (($opt{'tbl-status'})?"_status":"")."`";
  103. my $info_col="`".$opt{'prefix'}."col`";
  104. my $info_idx="`".$opt{'prefix'}."idx`";
  105.  
  106.  
  107. # --- connect to the database ---
  108.  
  109. my $dsn = ";host=$opt{'host'}";
  110. $dsn .= ";port=$opt{'port'}" if $opt{'port'};
  111. $dsn .= ";mysql_socket=$opt{'socket'}" if $opt{'socket'};
  112.  
  113. my $dbh = DBI->connect("dbi:mysql:$dsn;mysql_read_default_group=perl",
  114.                         $opt{'user'}, $opt{'password'},
  115. {
  116.     RaiseError => 1,
  117.     PrintError => 0,
  118.     AutoCommit => 1,
  119. });
  120.  
  121. $db_like_wild=$dbh->quote($db_like_wild);
  122. $tbl_like_wild=$dbh->quote($tbl_like_wild);
  123.  
  124. #Ask
  125.  
  126. if (!$opt{'quiet'})
  127. {
  128.     print "\n!! This program is going to do:\n\n";
  129.     print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'});
  130.     print "**DELETE** FROM ... WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild
  131. **INSERT** INTO ...
  132.  
  133. on the following tables :\n";
  134.  
  135.     foreach  (($info_db, $info_tbl),
  136.           (($opt{'col'})?$info_col:()), 
  137.           (($opt{'idx'})?$info_idx:()))
  138.     {
  139.     print("  $db_to_write.$_\n");
  140.     }
  141.     print "\nContinue (you can skip this confirmation step with --quiet) ? (y|n) [n]";
  142.     if (<STDIN> !~ /^\s*y\s*$/i) 
  143.     {
  144.     print "Nothing done!\n";exit;
  145.     }
  146. }
  147.  
  148. if ($opt{'clear'} or $opt{'clear-only'}) 
  149. {
  150. #do not drop the $db_to_write database !
  151.     foreach  (($info_db, $info_tbl),
  152.           (($opt{'col'})?$info_col:()), 
  153.           (($opt{'idx'})?$info_idx:()))
  154.     {
  155.     $dbh->do("DROP TABLE IF EXISTS $db_to_write.$_");
  156.     }
  157.     if ($opt{'clear-only'}) 
  158.     {
  159.     print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
  160.     exit; 
  161.     }
  162. }
  163.  
  164.  
  165. my %sth;
  166. my %extra_col_desc;
  167. my %row;
  168. my %done_create_table;
  169.  
  170. #create the $db_to_write database
  171. $dbh->do("CREATE DATABASE IF NOT EXISTS $db_to_write");
  172. $dbh->do("USE $db_to_write");
  173.  
  174. #get databases
  175. $sth{'db'}=$dbh->prepare("SHOW DATABASES LIKE $db_like_wild");
  176. $sth{'db'}->execute;
  177.  
  178. #create $info_db which will receive info about databases.
  179. #Ensure that the first column to be called "Database" (as SHOW DATABASES LIKE
  180. #returns a varying
  181. #column name (of the form "Database (%...)") which is not suitable)
  182. $extra_col_desc{'db'}=do_create_table("db",$info_db,undef,"`Database`");
  183. #we'll remember the type of the `Database` column (as returned by
  184. #SHOW DATABASES), which we will need when creating the next tables. 
  185.  
  186. #clear out-of-date info from this table 
  187. $dbh->do("DELETE FROM $info_db WHERE `Database` LIKE $db_like_wild"); 
  188.  
  189.  
  190. while ($row{'db'}=$sth{'db'}->fetchrow_arrayref) #go through all databases
  191. {
  192.  
  193. #insert the database name
  194.     $dbh->do("INSERT INTO $info_db VALUES("
  195.          .join(',' ,  ( map $dbh->quote($_), @{$row{'db'}} ) ).")" );
  196.  
  197. #for each database, get tables
  198.  
  199.     $sth{'tbl'}=$dbh->prepare("SHOW TABLE"
  200.                 .( ($opt{'tbl-status'}) ? 
  201.                    " STATUS"
  202.                    : "S" )
  203.                 ." from `$row{'db'}->[0]` LIKE $tbl_like_wild");
  204.     $sth{'tbl'}->execute;
  205.     unless ($done_create_table{$info_tbl})
  206.  
  207. #tables must be created only once, and out-of-date info must be
  208. #cleared once
  209.     {
  210.     $done_create_table{$info_tbl}=1;
  211.     $extra_col_desc{'tbl'}=
  212.         do_create_table("tbl",$info_tbl,
  213. #add an extra column (database name) at the left
  214. #and ensure that the table name will be called "Table"
  215. #(this is unncessesary with
  216. #SHOW TABLE STATUS, but necessary with SHOW TABLES (which returns a column
  217. #named "Tables_in_..."))
  218.                 "`Database` ".$extra_col_desc{'db'},"`Table`"); 
  219.     $dbh->do("DELETE FROM $info_tbl WHERE `Database` LIKE $db_like_wild                                 AND `Table` LIKE $tbl_like_wild");
  220.     }
  221.  
  222.     while ($row{'tbl'}=$sth{'tbl'}->fetchrow_arrayref)
  223.     {
  224.     $dbh->do("INSERT INTO $info_tbl VALUES("
  225.          .$dbh->quote($row{'db'}->[0]).","
  226.          .join(',' ,  ( map $dbh->quote($_), @{$row{'tbl'}} ) ).")");
  227.  
  228. #for each table, get columns...
  229.  
  230.     if ($opt{'col'})
  231.     {
  232.         $sth{'col'}=$dbh->prepare("SHOW COLUMNS FROM `$row{'tbl'}->[0]` FROM `$row{'db'}->[0]`"); 
  233.         $sth{'col'}->execute;
  234.         unless ($done_create_table{$info_col})
  235.         {
  236.         $done_create_table{$info_col}=1;
  237.         do_create_table("col",$info_col,
  238.                 "`Database` ".$extra_col_desc{'db'}.","
  239.                 ."`Table` ".$extra_col_desc{'tbl'}.","
  240.                 ."`Seq_in_table` BIGINT(3)"); 
  241. #We need to add a sequence number (1 for the first column of the table,
  242. #2 for the second etc) so that users are able to retrieve columns in order
  243. #if they want. This is not needed for INDEX 
  244. #(where there is already Seq_in_index)
  245.         $dbh->do("DELETE FROM $info_col WHERE `Database` 
  246.                             LIKE $db_like_wild
  247.                 AND `Table` LIKE $tbl_like_wild");
  248.         }
  249.         my $col_number=0;
  250.         while ($row{'col'}=$sth{'col'}->fetchrow_arrayref)
  251.         {
  252.         $dbh->do("INSERT INTO $info_col VALUES("
  253.              .$dbh->quote($row{'db'}->[0]).","
  254.              .$dbh->quote($row{'tbl'}->[0]).","
  255.              .++$col_number.","
  256.              .join(',' ,  ( map $dbh->quote($_), @{$row{'col'}} ) ).")");
  257.         }
  258.     }
  259.  
  260. #and get index.
  261.  
  262.     if ($opt{'idx'})
  263.     {
  264.         $sth{'idx'}=$dbh->prepare("SHOW INDEX FROM `$row{'tbl'}->[0]` FROM `$row{'db'}->[0]`"); 
  265.         $sth{'idx'}->execute;
  266.         unless ($done_create_table{$info_idx})
  267.         {
  268.         $done_create_table{$info_idx}=1;
  269.         do_create_table("idx",$info_idx,
  270.                 "`Database` ".$extra_col_desc{'db'});
  271.         $dbh->do("DELETE FROM $info_idx WHERE `Database`
  272.              LIKE $db_like_wild
  273.              AND `Table` LIKE $tbl_like_wild");
  274.         }
  275.         while ($row{'idx'}=$sth{'idx'}->fetchrow_arrayref)
  276.         {
  277.         $dbh->do("INSERT INTO $info_idx VALUES("
  278.              .$dbh->quote($row{'db'}->[0]).","
  279.              .join(',' ,  ( map $dbh->quote($_), @{$row{'idx'}} ) ).")");
  280.         }
  281.     }
  282.     }
  283. }
  284.  
  285. print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
  286. exit;
  287.  
  288.  
  289. sub do_create_table
  290. {
  291.     my ($sth_key,$target_tbl,$extra_col_desc,$first_col_name)=@_; 
  292.     my $create_table_query=$extra_col_desc;
  293.     my ($i,$first_col_desc,$col_desc);
  294.  
  295.     for ($i=0;$i<$sth{$sth_key}->{NUM_OF_FIELDS};$i++)
  296.     {
  297.     if ($create_table_query) { $create_table_query.=", "; }    
  298.     $col_desc=$sth{$sth_key}->{mysql_type_name}->[$i];
  299.     if ($col_desc =~ /char|int/i)
  300.     {
  301.         $col_desc.="($sth{$sth_key}->{PRECISION}->[$i])";
  302.     }
  303.     elsif ($col_desc =~ /decimal|numeric/i) #(never seen that)
  304.     {
  305.         $col_desc.=
  306.         "($sth{$sth_key}->{PRECISION}->[$i],$sth{$sth_key}->{SCALE}->[$i])";
  307.     }
  308.     elsif ($col_desc !~ /date/i) #date and datetime are OK,
  309.                              #no precision or scale for them
  310.     {
  311.         warn "unexpected column type '$col_desc' 
  312. (neither 'char','int','decimal|numeric')
  313. when creating $target_tbl, hope table creation will go OK\n";
  314.     }
  315.     if ($i==0) {$first_col_desc=$col_desc};
  316.     $create_table_query.=
  317.         ( ($i==0 and $first_col_name) ? 
  318.           "$first_col_name " :"`$sth{$sth_key}->{NAME}->[$i]` " )
  319.         .$col_desc;
  320.     }
  321. if ($create_table_query)
  322. {
  323.     $dbh->do("CREATE TABLE IF NOT EXISTS $target_tbl ($create_table_query)");
  324. }
  325. return $first_col_desc;
  326. }
  327.  
  328. __END__
  329.  
  330.  
  331. =head1 DESCRIPTION
  332.  
  333. mysql_tableinfo asks a MySQL server information about its
  334. databases, tables, table columns and index, and stores this
  335. in tables called `db`, `tbl` (or `tbl_status`), `col`, `idx` 
  336. (with an optional prefix specified with --prefix).
  337. After that, you can query these information tables, for example
  338. to build your admin scripts with SQL queries, like
  339.  
  340. SELECT CONCAT("CHECK TABLE ",`database`,".",`table`," EXTENDED;") 
  341. FROM info.tbl WHERE ... ;
  342.  
  343. as people usually do with some other RDBMS
  344. (note: to increase the speed of your queries on the info tables,
  345. you may add some index on them).
  346.  
  347. The database_like_wild and table_like_wild instructs the program
  348. to gather information only about databases and tables
  349. whose names match these patterns. If the info
  350. tables already exist, their rows matching the patterns are simply
  351. deleted and replaced by the new ones. That is,
  352. old rows not matching the patterns are not touched.
  353. If the database_like_wild and table_like_wild arguments
  354. are not specified on the command-line they default to "%".
  355.  
  356. The program :
  357.  
  358. - does CREATE DATABASE IF NOT EXISTS database_to_write
  359. where database_to_write is the database name specified on the command-line.
  360.  
  361. - does CREATE TABLE IF NOT EXISTS database_to_write.`db`
  362.  
  363. - fills database_to_write.`db` with the output of
  364. SHOW DATABASES LIKE database_like_wild
  365.  
  366. - does CREATE TABLE IF NOT EXISTS database_to_write.`tbl`
  367. (respectively database_to_write.`tbl_status`
  368. if the --tbl-status option is on)
  369.  
  370. - for every found database,
  371. fills database_to_write.`tbl` (respectively database_to_write.`tbl_status`)
  372. with the output of 
  373. SHOW TABLES FROM found_db LIKE table_like_wild
  374. (respectively SHOW TABLE STATUS FROM found_db LIKE table_like_wild)
  375.  
  376. - if the --col option is on,
  377.     * does CREATE TABLE IF NOT EXISTS database_to_write.`col`
  378.     * for every found table,
  379.       fills database_to_write.`col` with the output of 
  380.       SHOW COLUMNS FROM found_tbl FROM found_db
  381.  
  382. - if the --idx option is on,
  383.     * does CREATE TABLE IF NOT EXISTS database_to_write.`idx`
  384.     * for every found table,
  385.       fills database_to_write.`idx` with the output of 
  386.       SHOW INDEX FROM found_tbl FROM found_db
  387.  
  388. Some options may modify this general scheme (see below).
  389.  
  390. As mentioned, the contents of the info tables are the output of
  391. SHOW commands. In fact the contents are slightly more complete :
  392.  
  393. - the `tbl` (or `tbl_status`) info table 
  394.   has an extra column which contains the database name,
  395.  
  396. - the `col` info table
  397.   has an extra column which contains the table name,
  398.   and an extra column which contains, for each described column,
  399.   the number of this column in the table owning it (this extra column
  400.   is called `Seq_in_table`). `Seq_in_table` makes it possible for you
  401.   to retrieve your columns in sorted order, when you are querying
  402.   the `col` table. 
  403.  
  404. - the `index` info table
  405.   has an extra column which contains the database name.
  406.  
  407. Caution: info tables contain certain columns (e.g.
  408. Database, Table, Null...) whose names, as they are MySQL reserved words,
  409. need to be backquoted (`...`) when used in SQL statements.
  410.  
  411. Caution: as information fetching and info tables filling happen at the
  412. same time, info tables may contain inaccurate information about
  413. themselves.
  414.  
  415. =head1 OPTIONS
  416.  
  417. =over 4
  418.  
  419. =item --clear
  420.  
  421. Does DROP TABLE on the info tables (only those that the program is
  422. going to fill, for example if you do not use --col it won't drop
  423. the `col` table) and processes normally. Does not drop database_to_write.
  424.  
  425. =item --clear-only
  426.  
  427. Same as --clear but exits after the DROPs.
  428.  
  429. =item --col
  430.  
  431. Adds columns information (into table `col`).
  432.  
  433. =item --idx
  434.  
  435. Adds index information (into table `idx`).
  436.  
  437. =item --prefix prefix
  438.  
  439. The info tables are named from the concatenation of prefix and,
  440. respectively, db, tbl (or tbl_status), col, idx. Do not quote ('')
  441. or backquote (``) prefix.
  442.  
  443. =item -q, --quiet
  444.  
  445. Does not warn you about what the script is going to do (DROP TABLE etc)
  446. and does not ask for a confirmation before starting.
  447.  
  448. =item --tbl-status
  449.  
  450. Instead of using SHOW TABLES, uses SHOW TABLE STATUS
  451. (much more complete information, but slower). 
  452.  
  453. =item --help
  454.  
  455. Display helpscreen and exit
  456.  
  457. =item -u, --user=#         
  458.  
  459. user for database login if not current user. Give a user
  460. who has sufficient privileges (CREATE, ...).
  461.  
  462. =item -p, --password=#     
  463.  
  464. password to use when connecting to server
  465.  
  466. =item -h, --host=#     
  467.  
  468. host to connect to
  469.  
  470. =item -P, --port=#         
  471.  
  472. port to use when connecting to server
  473.  
  474. =item -S, --socket=#         
  475.  
  476. UNIX domain socket to use when connecting to server
  477.  
  478. =head1 WARRANTY
  479.  
  480. This software is free and comes without warranty of any kind.
  481.  
  482. Patches adding bug fixes, documentation and new features are welcome.
  483.  
  484. =head1 TO DO
  485.  
  486. Nothing: starting from MySQL 5.0, this program is replaced by the
  487. INFORMATION_SCHEMA pseudo-database.
  488.  
  489. =head1 AUTHOR
  490.  
  491. 2002-06-18 Guilhem Bichot (guilhem.bichot@mines-paris.org)
  492.  
  493. And all the authors of mysqlhotcopy, which served as a model for 
  494. the structure of the program.
  495.