fix for primary key adding/checking
[dbsrgits/SQL-Translator-2.0-ish.git] / lib / SQL / Translator / Object / Table.pm
1 use MooseX::Declare;
2 class SQL::Translator::Object::Table extends SQL::Translator::Object is dirty {
3     use MooseX::Types::Moose qw(Any Bool HashRef Str);
4     use MooseX::MultiMethods;
5     use SQL::Translator::Types qw(Column Constraint Index Schema Sequence);
6     use SQL::Translator::Object::Constraint;
7     clean;
8
9     use overload
10         '""'     => sub { shift->name },
11         'bool'   => sub { $_[0]->name || $_[0] },
12         fallback => 1,
13     ;
14
15     has 'name' => (
16         is => 'rw',
17         isa => Str,
18         required => 1
19     );
20     
21     has 'columns' => (
22         traits => ['Hash'],
23         is => 'rw',
24         isa => HashRef[Column],
25         handles => {
26             exists_column => 'exists',
27             column_ids    => 'keys',
28             get_columns   => 'values',
29             get_column    => 'get',
30             add_column    => 'set',
31             remove_column => 'delete',
32             clear_columns => 'clear',
33         },
34         default => sub { my %hash = (); tie %hash, 'Tie::IxHash'; return \%hash },
35     );
36     
37     has 'indexes' => (
38         traits => ['Hash'],
39         is => 'rw',
40         isa => HashRef[Index],
41         handles => {
42             exists_index => 'exists',
43             index_ids    => 'keys',
44             get_indices  => 'values',
45             get_index    => 'get',
46             add_index    => 'set',
47             remove_index => 'delete',
48         },
49         default => sub { my %hash = (); tie %hash, 'Tie::IxHash'; return \%hash },
50     );
51     
52     has 'constraints' => (
53         traits => ['Hash'],
54         is => 'rw',
55         isa => HashRef[Constraint],
56         handles => {
57             exists_constraint => 'exists',
58             constraint_ids    => 'keys',
59             get_constraints   => 'values',
60             get_constraint    => 'get',
61             add_constraint    => 'set',
62             remove_constraint => 'delete',
63         },
64         default => sub { my %hash = (); tie %hash, 'Tie::IxHash'; return \%hash },
65     );
66     
67     has 'sequences' => (
68         traits => ['Hash'],
69         is => 'rw',
70         isa => HashRef[Sequence],
71         handles => {
72             exists_sequence => 'exists',
73             sequence_ids    => 'keys',
74             get_sequences   => 'values',
75             get_sequence    => 'get',
76             add_sequence    => 'set',
77             remove_sequence => 'delete',
78         },
79         default => sub { my %hash = (); tie %hash, 'Tie::IxHash'; return \%hash },
80     );
81
82     has 'schema' => (
83         is => 'rw',
84         isa => Schema,
85         weak_ref => 1,
86     );
87
88     has 'temporary' => (
89         is => 'rw',
90         isa => Bool,
91         default => 0
92     );
93
94     around add_column(Column $column does coerce) {
95         die "Can't use column name " . $column->name if $self->exists_column($column->name) || $column->name eq '';
96         $column->table($self);
97         return $self->$orig($column->name, $column);
98     }
99
100     around add_constraint(Constraint $constraint does coerce) {
101         my $name = $constraint->name;
102         if ($name eq '') {
103             my $idx = 0;
104             while ($self->exists_constraint('ANON' . $idx)) { $idx++ }
105             $name = 'ANON' . $idx;
106         }
107         $constraint->table($self);
108         if ($constraint->has_type && $constraint->type eq 'PRIMARY KEY') {
109             $self->get_column($_)->is_primary_key(1) for $constraint->column_ids;
110         }
111         $self->$orig($name, $constraint)
112     }
113
114     around add_index(Index $index does coerce) {
115         my $name = $index->name;
116         if ($name eq '') {
117             my $idx = 0;
118             while ($self->exists_index('ANON' . $idx)) { $idx++ }
119             $name = 'ANON' . $idx;
120         }
121         $index->table($self);
122         $self->$orig($name, $index)
123     }
124
125     around add_sequence(Sequence $sequence does coerce) { $self->$orig($sequence->name, $sequence) }
126
127     multi method primary_key {
128         my $constraints = $self->constraints;
129         for my $key (keys %$constraints) {
130             return $constraints->{$key} if $constraints->{$key}{type} eq 'PRIMARY KEY';
131         }
132         return undef;
133     }
134
135     multi method primary_key(Str $column) {
136         die "Column $column does not exist!" unless $self->exists_column($column);
137         $self->get_column($column)->is_primary_key(1);
138
139         my $primary_key = $self->primary_key;
140         unless (defined $primary_key) {
141             $primary_key = SQL::Translator::Object::Constraint->new({ type => 'PRIMARY KEY' });
142             $self->add_constraint($primary_key);
143         }
144         $primary_key->add_column(SQL::Translator::Object::Column->new({ name => $column })) unless $primary_key->exists_column($column);
145         return $primary_key;
146     }
147
148     method is_valid { return $self->get_columns ? 1 : undef }
149     method order { }
150
151     before name($name?) { die "Can't use table name $name, table already exists" if $name && $self->schema->exists_table($name) && $name ne $self->name }
152
153     around remove_column(Column|Str $column, Int :$cascade = 0) {
154         my $name = is_Column($column) ? $column->name : $column;
155         die "Can't drop non-existant column " . $name unless $self->exists_column($name);
156         $self->$orig($name);
157     }
158
159     around remove_index(Index|Str $index) {
160         my $name = is_Index($index) ? $index->name : $index;
161         die "Can't drop non-existant index " . $name unless $self->exists_index($name);
162         $self->$orig($name);
163     }
164
165     around remove_constraint(Constraint|Str $constraint) {
166         my $name = is_Constraint($constraint) ? $constraint->name : $constraint;
167         die "Can't drop non-existant constraint " . $name unless $self->exists_constraint($name);
168         $self->$orig($name);
169     }
170 }