File Coverage

script/sqlt-diff-old
Criterion Covered Total %
statement 204 248 82.2
branch 117 218 53.6
condition 21 41 51.2
subroutine 8 8 100.0
pod n/a
total 350 515 67.9


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             # vim: set ft=perl:
3              
4             # -------------------------------------------------------------------
5             # Copyright (C) 2002-2009 The SQLFairy Authors
6             #
7             # This program is free software; you can redistribute it and/or
8             # modify it under the terms of the GNU General Public License as
9             # published by the Free Software Foundation; version 2.
10             #
11             # This program is distributed in the hope that it will be useful, but
12             # WITHOUT ANY WARRANTY; without even the implied warranty of
13             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14             # General Public License for more details.
15             #
16             # You should have received a copy of the GNU General Public License
17             # along with this program; if not, write to the Free Software
18             # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19             # 02110-1301 USA.
20             # -------------------------------------------------------------------
21              
22             =head1 NAME
23              
24             sqlt-diff - find the differences b/w two schemas
25              
26             =head1 SYNOPSIS
27              
28             For help:
29              
30             sqlt-diff -h|--help
31              
32             For a list of all valid parsers:
33              
34             sqlt -l|--list
35              
36             To diff two schemas:
37              
38             sqlt-diff [options] file_name1=parser file_name2=parser
39              
40             Options:
41              
42             -d|--debug Show debugging info
43              
44             =head1 DESCRIPTION
45              
46             sqlt-diff is a utility for creating a file of SQL commands necessary to
47             transform the first schema provided to the second. While not yet
48             exhaustive in its ability to mutate the entire schema, it will report the
49             following
50              
51             =over
52              
53             =item * New tables
54              
55             Using the Producer class of the target (second) schema, any tables missing
56             in the first schema will be generated in their entirety (fields, constraints,
57             indices).
58              
59             =item * Missing/altered fields
60              
61             Any fields missing or altered between the two schemas will be reported
62             as:
63              
64             ALTER TABLE
65             [DROP ]
66             [CHANGE ()] ;
67              
68             =item * Missing/altered indices
69              
70             Any indices missing or of a different type or on different fields will be
71             indicated. Indices that should be dropped will be reported as such:
72              
73             DROP INDEX ON ;
74              
75             An index of a different type or on different fields will be reported as a
76             new index as such:
77              
78             CREATE [] INDEX [] ON
79             ( [,] ) ;
80              
81             =back
82              
83             "ALTER/DROP TABLE" and "CREATE INDEX" statements B generated by
84             the Producer, unfortunately, and may require massaging before being passed to
85             your target database.
86              
87             =cut
88              
89             # -------------------------------------------------------------------
90              
91 5     5   54 use strict;
  5         36  
  5         157  
92 5     5   26 use warnings;
  5         8  
  5         127  
93 5     5   2677 use Pod::Usage;
  5         266120  
  5         772  
94 5     5   3366 use Data::Dumper;
  5         31238  
  5         325  
95 5     5   2761 use SQL::Translator;
  5         21  
  5         187  
96 5     5   43 use SQL::Translator::Schema::Constants;
  5         11  
  5         361  
97              
98 5     5   35 use vars qw( $VERSION );
  5         10  
  5         27587  
99 5         26 $VERSION = '1.62';
100              
101 5         17 my ( @input, $list, $help, $debug );
102 5         17 for my $arg ( @ARGV ) {
103 10 50       146 if ( $arg =~ m/^-?-l(ist)?$/ ) {
    50          
    50          
    50          
104 0         0 $list = 1;
105             }
106             elsif ( $arg =~ m/^-?-h(elp)?$/ ) {
107 0         0 $help = 1;
108             }
109             elsif ( $arg =~ m/^-?-d(ebug)?$/ ) {
110 0         0 $debug = 1;
111             }
112             elsif ( $arg =~ m/^([^=]+)=(.+)$/ ) {
113 10         67 push @input, { file => $1, parser => $2 };
114             }
115             else {
116 0         0 pod2usage( msg => "Unknown argument '$arg'" );
117             }
118             }
119              
120 5 50       24 pod2usage(1) if $help;
121 5 50       30 pod2usage('Please specify only two schemas to diff') if scalar @input > 2;
122 5 50       21 pod2usage('No input') if !@input;
123              
124 5 50 33     62 if ( my $interactive = -t STDIN && -t STDOUT ) {
125 0         0 print STDERR join("\n",
126             "sqlt-diff-old is deprecated. Please sqlt-diff, and tell us ",
127             "about any problems or patch SQL::Translator::Diff",
128             '',
129             );
130             }
131              
132 5         178 my $tr = SQL::Translator->new;
133 5         155 my @parsers = $tr->list_parsers;
134 5         22 my %valid_parsers = map { $_, 1 } @parsers;
  120         194  
135              
136 5 50       34 if ( $list ) {
137 0         0 print "\nParsers:\n", map { "\t$_\n" } sort @parsers;
  0         0  
138 0         0 print "\n";
139 0         0 exit(0);
140             }
141              
142 5 50       23 pod2usage( msg => 'Too many file args' ) if @input > 2;
143              
144 5         18 my ( $source_schema, $source_db, $target_schema, $target_db );
145              
146 5         14 my $i = 2;
147 5         18 for my $in ( @input ) {
148 10         39 my $file = $in->{'file'};
149 10         30 my $parser = $in->{'parser'};
150              
151 10 50       446 die "Unable to read file '$file'\n" unless -r $file;
152 10 50       52 die "'$parser' is an invalid parser\n" unless $valid_parsers{ $parser };
153              
154 10         328 my $t = SQL::Translator->new;
155 10         223 $t->debug( $debug );
156 10 50       227 $t->parser( $parser ) or die $tr->error;
157 10 50       48 my $out = $t->translate( $file ) or die $tr->error;
158 10         190 my $schema = $t->schema;
159 10 50       113 unless ( $schema->name ) {
160 10         46 $schema->name( $file );
161             }
162              
163 10 100       38 if ( $i == 1 ) {
164 5         14 $source_schema = $schema;
165 5         17 $source_db = $parser;
166             }
167             else {
168 5         13 $target_schema = $schema;
169 5         13 $target_db = $parser;
170             }
171 10         155 $i--;
172             }
173 5         18 my $case_insensitive = $target_db =~ /SQLServer/;
174              
175 5         42 my $s1_name = $source_schema->name;
176 5         54 my $s2_name = $target_schema->name;
177 5         30 my ( @new_tables, @diffs , @diffs_at_end);
178 5         45 for my $t1 ( $source_schema->get_tables ) {
179 11         218 my $t1_name = $t1->name;
180 11         278 my $t2 = $target_schema->get_table( $t1_name, $case_insensitive );
181              
182 11 50       41 warn "TABLE '$s1_name.$t1_name'\n" if $debug;
183 11 100       266 unless ( $t2 ) {
184 1 50       5 warn "Couldn't find table '$s1_name.$t1_name' in '$s2_name'\n"
185             if $debug;
186 1 50       6 if ( $target_db =~ /(SQLServer|Oracle)/ ) {
187 0         0 for my $constraint ( $t1->get_constraints ) {
188 0 0       0 next if $constraint->type ne FOREIGN_KEY;
189 0         0 push @diffs_at_end, "ALTER TABLE $t1_name ADD ".
190             constraint_to_string($constraint, $source_schema).";";
191 0         0 $t1->drop_constraint($constraint);
192             }
193             }
194 1         3 push @new_tables, $t1;
195 1         3 next;
196             }
197              
198             # Go through our options
199 10         188 my $options_different = 0;
200 10         23 my %checkedOptions;
201             OPTION:
202 10         214 for my $t1_option_ref ( $t1->options ) {
203 4         7 my($key1, $value1) = %{$t1_option_ref};
  4         20  
204 4         69 for my $t2_option_ref ( $t2->options ) {
205 4         10 my($key2, $value2) = %{$t2_option_ref};
  4         14  
206 4 50       15 if ( $key1 eq $key2 ) {
207 4 50       15 if ( defined $value1 != defined $value2 ) {
208 0         0 $options_different = 1;
209 0         0 last OPTION;
210             }
211 4 100 66     25 if ( defined $value1 && $value1 ne $value2 ) {
212 1         4 $options_different = 1;
213 1         5 last OPTION;
214             }
215 3         13 $checkedOptions{$key1} = 1;
216 3         12 next OPTION;
217             }
218             }
219 0         0 $options_different = 1;
220 0         0 last OPTION;
221             }
222             # Go through the other table's options
223 10 100       38 unless ( $options_different ) {
224 9         164 for my $t2_option_ref ( $t2->options ) {
225 3         6 my($key, $value) = %{$t2_option_ref};
  3         11  
226 3 50       14 next if $checkedOptions{$key};
227 0         0 $options_different = 1;
228 0         0 last;
229             }
230             }
231             # If there's a difference, just re-set all the options
232 10         24 my @diffs_table_options;
233 10 100       51 if ( $options_different ) {
234 1         3 my @options = ();
235 1         21 foreach my $option_ref ( $t1->options ) {
236 1         4 my($key, $value) = %{$option_ref};
  1         6  
237 1 50       8 push(@options, defined $value ? "$key=$value" : $key);
238             }
239 1         4 my $options = join(' ', @options);
240 1         6 @diffs_table_options = ("ALTER TABLE $t1_name $options;");
241             }
242              
243 10         352 my $t2_name = $t2->name;
244 10         237 my(@diffs_table_adds, @diffs_table_changes);
245 10         45 for my $t1_field ( $t1->get_fields ) {
246 42         160 my $f1_type = $t1_field->data_type;
247 42         888 my $f1_size = $t1_field->size;
248 42         1074 my $f1_name = $t1_field->name;
249 42         1528 my $f1_nullable = $t1_field->is_nullable;
250 42         2519 my $f1_default = $t1_field->default_value;
251 42         654 my $f1_auto_inc = $t1_field->is_auto_increment;
252 42         538 my $t2_field = $t2->get_field( $f1_name, $case_insensitive );
253 42         357 my $f1_full_name = "$s1_name.$t1_name.$t1_name";
254 42 50       113 warn "FIELD '$f1_full_name'\n" if $debug;
255              
256 42         113 my $f2_full_name = "$s2_name.$t2_name.$f1_name";
257              
258 42 100       347 unless ( $t2_field ) {
259 3 50       13 warn "Couldn't find field '$f2_full_name' in '$t2_name'\n"
260             if $debug;
261 3         8 my $temp_default_value = 0;
262 3 0 33     14 if ( $target_db =~ /SQLServer/ && !$f1_nullable && !defined $f1_default ) {
      33        
263             # SQL Server doesn't allow adding non-nullable, non-default columns
264             # so we add it with a default value, then remove the default value
265 0         0 $temp_default_value = 1;
266 0         0 my(@numeric_types) = qw(decimal numeric float real int bigint smallint tinyint);
267 0 0       0 $f1_default = grep($_ eq $f1_type, @numeric_types) ? 0 : '';
268             }
269 3 50 100     68 push @diffs_table_adds, sprintf( "ALTER TABLE %s ADD %s%s %s%s%s%s%s%s;",
    100          
    50          
    50          
    100          
    50          
    50          
    50          
270             $t1_name, $target_db =~ /Oracle/ ? '(' : '',
271             $f1_name, $f1_type,
272             ($f1_size && $f1_type !~ /(blob|text)$/) ? "($f1_size)" : '',
273             !defined $f1_default ? ''
274             : uc $f1_default eq 'NULL' ? ' DEFAULT NULL'
275             : uc $f1_default eq 'CURRENT_TIMESTAMP' ? ' DEFAULT CURRENT_TIMESTAMP'
276             : " DEFAULT '$f1_default'",
277             $f1_nullable ? '' : ' NOT NULL',
278             $f1_auto_inc ? ' AUTO_INCREMENT' : '',
279             $target_db =~ /Oracle/ ? ')' : '',
280             );
281 3 50       15 if ( $temp_default_value ) {
282 0         0 undef $f1_default;
283 0         0 push @diffs_table_adds, sprintf( <
284             DECLARE \@defname VARCHAR(100), \@cmd VARCHAR(1000)
285             SET \@defname =
286             (SELECT name
287             FROM sysobjects so JOIN sysconstraints sc
288             ON so.id = sc.constid
289             WHERE object_name(so.parent_obj) = '%s'
290             AND so.xtype = 'D'
291             AND sc.colid =
292             (SELECT colid FROM syscolumns
293             WHERE id = object_id('%s') AND
294             name = '%s'))
295             SET \@cmd = 'ALTER TABLE %s DROP CONSTRAINT '
296             + \@defname
297             EXEC(\@cmd)
298             END
299             , $t1_name, $t1_name, $f1_name, $t1_name,
300             );
301             }
302 3         9 next;
303             }
304              
305 39         800 my $f2_type = $t2_field->data_type;
306 39   100     712 my $f2_size = $t2_field->size || '';
307 39         1080 my $f2_nullable = $t2_field->is_nullable;
308 39         2135 my $f2_default = $t2_field->default_value;
309 39         587 my $f2_auto_inc = $t2_field->is_auto_increment;
310 39 100       1053 if ( !$t1_field->equals($t2_field, $case_insensitive) ) {
311             # SQLServer timestamp fields can't be altered, so we drop and add instead
312 6 50 33     101 if ( $target_db =~ /SQLServer/ && $f2_type eq "timestamp" ) {
313 0         0 push @diffs_table_changes, "ALTER TABLE $t1_name DROP COLUMN $f1_name;";
314 0 0 0     0 push @diffs_table_changes, sprintf( "ALTER TABLE %s ADD %s%s %s%s%s%s%s%s;",
    0          
    0          
    0          
    0          
    0          
    0          
    0          
315             $t1_name, $target_db =~ /Oracle/ ? '(' : '',
316             $f1_name, $f1_type,
317             ($f1_size && $f1_type !~ /(blob|text)$/) ? "($f1_size)" : '',
318             !defined $f1_default ? ''
319             : uc $f1_default eq 'NULL' ? ' DEFAULT NULL'
320             : uc $f1_default eq 'CURRENT_TIMESTAMP' ? ' DEFAULT CURRENT_TIMESTAMP'
321             : " DEFAULT '$f1_default'",
322             $f1_nullable ? '' : ' NOT NULL',
323             $f1_auto_inc ? ' AUTO_INCREMENT' : '',
324             $target_db =~ /Oracle/ ? ')' : '',
325             );
326 0         0 next;
327             }
328              
329 6 50       26 my $changeText = $target_db =~ /SQLServer/ ? 'ALTER COLUMN' :
    50          
330             $target_db =~ /Oracle/ ? 'MODIFY (' : 'CHANGE';
331 6 100       16 my $nullText = $f1_nullable ? '' : ' NOT NULL';
332 6 50 33     21 $nullText = '' if $target_db =~ /Oracle/ && $f1_nullable == $f2_nullable;
333 6 100 66     125 push @diffs_table_changes, sprintf( "ALTER TABLE %s %s %s%s %s%s%s%s%s%s;",
    100 66        
    50          
    50          
    100          
    100          
    50          
334             $t1_name, $changeText,
335             $f1_name, $target_db =~ /MySQL/ ? " $f1_name" : '',
336             $f1_type, ($f1_size && $f1_type !~ /(blob|text)$/) ? "($f1_size)" : '',
337             $nullText,
338             !defined $f1_default || $target_db =~ /SQLServer/ ? ''
339             : uc $f1_default eq 'NULL' ? ' DEFAULT NULL'
340             : uc $f1_default eq 'CURRENT_TIMESTAMP' ? ' DEFAULT CURRENT_TIMESTAMP'
341             : " DEFAULT '$f1_default'",
342             $f1_auto_inc ? ' AUTO_INCREMENT' : '',
343             $target_db =~ /Oracle/ ? ')' : '',
344             );
345 6 50 66     39 if ( defined $f1_default && $target_db =~ /SQLServer/ ) {
346             # Adding a column with a default value for SQL Server means adding a
347             # constraint and setting existing NULLs to the default value
348 0 0       0 push @diffs_table_changes, sprintf( "ALTER TABLE %s ADD CONSTRAINT DF_%s_%s %s FOR %s;",
    0          
349             $t1_name, $t1_name, $f1_name, uc $f1_default eq 'NULL' ? 'DEFAULT NULL'
350             : uc $f1_default eq 'CURRENT_TIMESTAMP' ? 'DEFAULT CURRENT_TIMESTAMP'
351             : "DEFAULT '$f1_default'", $f1_name,
352             );
353 0 0       0 push @diffs_table_changes, sprintf( "UPDATE %s SET %s = %s WHERE %s IS NULL;",
    0          
354             $t1_name, $f1_name, uc $f1_default eq 'NULL' ? 'NULL'
355             : uc $f1_default eq 'CURRENT_TIMESTAMP' ? 'CURRENT_TIMESTAMP'
356             : "'$f1_default'", $f1_name,
357             );
358             }
359             }
360             }
361              
362 10         48 my(%checked_indices, @diffs_index_creates, @diffs_index_drops);
363             INDEX:
364 10         52 for my $i1 ( $t1->get_indices ) {
365 2         26 for my $i2 ( $t2->get_indices ) {
366 2 100       53 if ( $i1->equals($i2, $case_insensitive) ) {
367 1         5 $checked_indices{$i2} = 1;
368 1         5 next INDEX;
369             }
370             }
371 1 50       37 push @diffs_index_creates, sprintf(
    50          
372             "CREATE %sINDEX%s ON %s (%s);",
373             $i1->type eq NORMAL ? '' : $i1->type." ",
374             $i1->name ? " ".$i1->name : '',
375             $t1_name,
376             join(",", $i1->fields),
377             );
378             }
379             INDEX2:
380 10         44 for my $i2 ( $t2->get_indices ) {
381 2 100       23 next if $checked_indices{$i2};
382 1         6 for my $i1 ( $t1->get_indices ) {
383 1 50       27 next INDEX2 if $i2->equals($i1, $case_insensitive);
384             }
385 1 50       37 $target_db =~ /SQLServer/
386             ? push @diffs_index_drops, "DROP INDEX $t1_name.".$i2->name.";"
387             : push @diffs_index_drops, "DROP INDEX ".$i2->name." on $t1_name;";
388             }
389              
390 10         34 my(%checked_constraints, @diffs_constraint_drops);
391             CONSTRAINT:
392 10         37 for my $c1 ( $t1->get_constraints ) {
393 22 50 66     205 next if $source_db =~ /Oracle/ && $c1->type eq UNIQUE && $c1->name =~ /^SYS_/i;
      33        
394 22         117 for my $c2 ( $t2->get_constraints ) {
395 42 100       1247 if ( $c1->equals($c2, $case_insensitive) ) {
396 17         63 $checked_constraints{$c2} = 1;
397 17         67 next CONSTRAINT;
398             }
399             }
400 5         85 push @diffs_at_end, "ALTER TABLE $t1_name ADD ".
401             constraint_to_string($c1, $source_schema).";";
402             }
403             CONSTRAINT2:
404 10         56 for my $c2 ( $t2->get_constraints ) {
405 22 100       172 next if $checked_constraints{$c2};
406 5         22 for my $c1 ( $t1->get_constraints ) {
407 13 50       361 next CONSTRAINT2 if $c2->equals($c1, $case_insensitive);
408             }
409 5 100       178 if ( $c2->type eq UNIQUE ) {
    50          
410 1         47 push @diffs_constraint_drops, "ALTER TABLE $t1_name DROP INDEX ".
411             $c2->name.";";
412             } elsif ( $target_db =~ /SQLServer/ ) {
413 0         0 push @diffs_constraint_drops, "ALTER TABLE $t1_name DROP ".$c2->name.";";
414             } else {
415 4 100       167 push @diffs_constraint_drops, "ALTER TABLE $t1_name DROP ".$c2->type.
416             ($c2->type eq FOREIGN_KEY ? " ".$c2->name : '').";";
417             }
418             }
419              
420 10         72 push @diffs, @diffs_index_drops, @diffs_constraint_drops,
421             @diffs_table_options, @diffs_table_adds,
422             @diffs_table_changes, @diffs_index_creates;
423             }
424              
425 5         35 for my $t2 ( $target_schema->get_tables ) {
426 11         281 my $t2_name = $t2->name;
427 11         236 my $t1 = $source_schema->get_table( $t2_name, $target_db =~ /SQLServer/ );
428              
429 11 100       39 unless ( $t1 ) {
430 1 50       5 if ( $target_db =~ /SQLServer/ ) {
431 0         0 for my $constraint ( $t2->get_constraints ) {
432 0 0       0 next if $constraint->type eq PRIMARY_KEY;
433 0         0 push @diffs, "ALTER TABLE $t2_name DROP ".$constraint->name.";";
434             }
435             }
436 1         6 push @diffs_at_end, "DROP TABLE $t2_name;";
437 1         4 next;
438             }
439              
440 10         213 for my $t2_field ( $t2->get_fields ) {
441 41         1280 my $f2_name = $t2_field->name;
442 41         789 my $t1_field = $t1->get_field( $f2_name );
443 41 100       333 unless ( $t1_field ) {
444 2 50       8 my $modifier = $target_db =~ /SQLServer/ ? "COLUMN " : '';
445 2         34 push @diffs, "ALTER TABLE $t2_name DROP $modifier$f2_name;";
446             }
447             }
448             }
449              
450 5 100       89 if ( @new_tables ) {
451 1         29 my $dummy_tr = SQL::Translator->new;
452 1         44 $dummy_tr->schema->add_table( $_ ) for @new_tables;
453 1         24 my $producer = $dummy_tr->producer( $target_db );
454 1         7 unshift @diffs, $producer->( $dummy_tr );
455             }
456 5         22 push(@diffs, @diffs_at_end);
457              
458 5 100       23 if ( @diffs ) {
459 3 100       292 if ( $source_db !~ /^(MySQL|SQLServer|Oracle)$/ ) {
460 1         13 unshift(@diffs, "-- Target database $target_db is untested/unsupported!!!");
461             }
462             }
463              
464 5 100       19 if ( @diffs ) {
465 3         52 print join( "\n",
466             "-- Convert schema '$s2_name' to '$s1_name':\n", @diffs, "\n"
467             );
468 3         877 exit(1);
469             }
470             else {
471 2         1018 print "There were no differences.\n";
472             }
473              
474             sub constraint_to_string {
475 5     5   11 my $c = shift;
476 5 50       16 my $schema = shift or die "No schema given";
477 5 100       98 my @fields = $c->field_names or return '';
478              
479 4 50       73 if ( $c->type eq PRIMARY_KEY ) {
    100          
    50          
480 0 0       0 if ( $target_db =~ /Oracle/ ) {
481 0 0       0 return (defined $c->name ? 'CONSTRAINT '.$c->name.' ' : '') .
482             'PRIMARY KEY (' . join(', ', @fields). ')';
483             } else {
484 0         0 return 'PRIMARY KEY (' . join(', ', @fields). ')';
485             }
486             }
487             elsif ( $c->type eq UNIQUE ) {
488 2 50       40 if ( $target_db =~ /Oracle/ ) {
489 0 0       0 return (defined $c->name ? 'CONSTRAINT '.$c->name.' ' : '') .
490             'UNIQUE (' . join(', ', @fields). ')';
491             } else {
492 2 50       41 return 'UNIQUE '.
493             (defined $c->name ? $c->name.' ' : '').
494             '(' . join(', ', @fields). ')';
495             }
496             }
497             elsif ( $c->type eq FOREIGN_KEY ) {
498             my $def = join(' ',
499 2 50       87 map { $_ || () } 'CONSTRAINT', $c->name, 'FOREIGN KEY'
  6         33  
500             );
501              
502 2         10 $def .= ' (' . join( ', ', @fields ) . ')';
503              
504 2         10 $def .= ' REFERENCES ' . $c->reference_table;
505              
506 2 50       40 my @rfields = map { $_ || () } $c->reference_fields;
  2         10  
507 2 50       8 unless ( @rfields ) {
508 0         0 my $rtable_name = $c->reference_table;
509 0 0       0 if ( my $ref_table = $schema->get_table( $rtable_name ) ) {
510 0         0 push @rfields, $ref_table->primary_key;
511             }
512             else {
513 0         0 warn "Can't find reference table '$rtable_name' " .
514             "in schema\n";
515             }
516             }
517              
518 2 50       6 if ( @rfields ) {
519 2         13 $def .= ' (' . join( ', ', @rfields ) . ')';
520             }
521             else {
522 0         0 warn "FK constraint on " . 'some table' . '.' .
523             join('', @fields) . " has no reference fields\n";
524             }
525              
526 2 50       42 if ( $c->match_type ) {
527 0 0       0 $def .= ' MATCH ' .
528             ( $c->match_type =~ /full/i ) ? 'FULL' : 'PARTIAL';
529             }
530              
531 2 100       72 if ( $c->on_delete ) {
532 1         16 $def .= ' ON DELETE '.join( ' ', $c->on_delete );
533             }
534              
535 2 50       38 if ( $c->on_update ) {
536 0         0 $def .= ' ON UPDATE '.join( ' ', $c->on_update );
537             }
538              
539 2         13 return $def;
540             }
541             }
542              
543             # -------------------------------------------------------------------
544             # Bring out number weight & measure in a year of dearth.
545             # William Blake
546             # -------------------------------------------------------------------
547              
548             =pod
549              
550             =head1 AUTHOR
551              
552             Ken Youens-Clark Ekclark@cpan.orgE.
553              
554             =head1 SEE ALSO
555              
556             SQL::Translator, L.
557              
558             =cut