1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
package MySQL::Table;
use strict;
use Carp qw(:DEFAULT cluck);
use Class::MakeMethods::Template::Hash
'new --and_then_init' => 'new',
'scalar' => 'name def source primary_key options',
'array --get_set_ref' => 'lines',
'hash' => 'fields indices unique_index fulltext',
;
use MySQL::Utils qw(debug);
sub init {
my $self = shift;
debug(4, " constructing new MySQL::Table\n");
croak "MySQL::Table::new called without def params" unless $self->def;
$self->parse;
}
sub parse {
my $self = shift;
(my $def = $self->def) =~ s/\n+/\n/;
$self->def($def);
$self->lines([ grep ! /^\s*$/, split /(?=^)/m, $def ]);
my @lines = $self->lines;
debug(5, " parsing table def\n");
my $name;
if ($lines[0] =~ /^\s*create\s+table\s+(\S+)\s+\(\s*$/i) {
$self->name($name = $1);
debug(5, " got table name `$name'\n");
shift @lines;
}
else {
croak "couldn't figure out table name";
}
while (@lines) {
$_ = shift @lines;
s/^\s*(.*?),?\s*$/$1/; # trim whitespace and trailing commas
debug(7, " line: [$_]\n");
if (/^PRIMARY\s+KEY\s+(.+)$/) {
my $primary = $1;
croak "two primary keys in table `$name': `$primary', `",
$self->primary_key, "'\n"
if $self->primary_key;
$self->primary_key($primary);
debug(6, " got primary key $primary\n");
next;
}
if (/^(KEY|UNIQUE(?: KEY)?)\s+(\S+?)\s*\((.*)\)$/) {
my ($type, $key, $val) = ($1, $2, $3);
croak "index `$key' duplicated in table `$name'\n"
if $self->indices($key);
$self->indices_push($key, $val);
my $unique = $type =~ /unique/i;
$self->unique_index($key, $unique);
debug(6, " got ",
$unique ? 'unique ' : '',
"index key `$key': ($val)\n");
next;
}
if (/^(FULLTEXT(?: KEY|INDEX)?)\s+(\S+?)\s*\((.*)\)$/) {
my ($type, $key, $val) = ($1, $2, $3);
croak "FULLTEXT index `$key' duplicated in table `$name'\n"
if $self->fulltext($key);
$self->fulltext_push($key, $val);
debug(6, " got FULLTEXT index `$key': ($val)\n");
next;
}
if (/^\)\s*(.*?);$/) { # end of table definition
my $options = $self->options($1);
debug(6, " got table options `$options'\n");
last;
}
if (/^(\S+)\s*(.*)/) {
my ($field, $def) = ($1, $2);
croak "definition for field `$field' duplicated in table `$name'\n"
if $self->fields($field);
$self->fields_push($field, $def);
debug(6, " got field def `$field': $def\n");
next;
}
croak "unparsable line in definition for table `$name':\n$_";
}
warn "table `$name' didn't have terminator\n"
unless defined $self->options;
map {
s/\/\*.*\*\///;
s/^;*$//;
s/DROP TABLE IF EXISTS.*//;
s/SET character_set_client.*//;
s/SET \@saved_cs_client.*//;
s/^\n*$//;
shift @lines if /^\s$/;
} @lines;
warn "table `$name' had trailing garbage:\n", join '', @lines
if @lines && join('', @lines) !~ /^\s*$/;
}
1;
|