Added refactored comment producing using header_comment.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Producer / MySQL.pm
CommitLineData
9398955f 1package SQL::Translator::Producer::MySQL;
2
49e1eb70 3# -------------------------------------------------------------------
5ee19df8 4# $Id: MySQL.pm,v 1.17 2003-04-25 11:47:25 dlc Exp $
49e1eb70 5# -------------------------------------------------------------------
abfa405a 6# Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>,
7# darren chamberlain <darren@cpan.org>,
8# Chris Mungall <cjm@fruitfly.org>
9398955f 9#
10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License as
12# published by the Free Software Foundation; version 2.
13#
14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22# 02111-1307 USA
23# -------------------------------------------------------------------
24
25use strict;
d529894e 26use vars qw[ $VERSION $DEBUG ];
5ee19df8 27$VERSION = sprintf "%d.%02d", q$Revision: 1.17 $ =~ /(\d+)\.(\d+)/;
5636ed00 28$DEBUG = 0 unless defined $DEBUG;
9398955f 29
30use Data::Dumper;
5ee19df8 31use SQL::Translator::Utils qw(debug header_comment);
9398955f 32
2620fc1c 33my %translate = (
34 #
35 # Oracle types
36 #
37 varchar2 => 'varchar',
38 long => 'text',
39 CLOB => 'longtext',
40
41 #
42 # Sybase types
43 #
44 int => 'integer',
45 money => 'float',
46 real => 'double',
47 comment => 'text',
48 bit => 'tinyint',
49);
50
9398955f 51sub produce {
52 my ($translator, $data) = @_;
5636ed00 53 local $DEBUG = $translator->debug;
d529894e 54 my $no_comments = $translator->no_comments;
758ab1cd 55 my $add_drop_table = $translator->add_drop_table;
d529894e 56
1a24938d 57 debug("PKG: Beginning production\n");
d529894e 58
59 my $create;
5ee19df8 60 $create .= header_comment unless ($no_comments);
9398955f 61
758ab1cd 62 for my $table ( keys %{ $data } ) {
56120730 63
64
1a24938d 65 debug("PKG: Looking at table '$table'\n");
9398955f 66 my $table_data = $data->{$table};
56120730 67#warn Dumper($table_data);
d529894e 68 my @fields = sort {
69 $table_data->{'fields'}->{$a}->{'order'}
70 <=>
71 $table_data->{'fields'}->{$b}->{'order'}
72 } keys %{$table_data->{'fields'}};
9398955f 73
d529894e 74 #
9398955f 75 # Header. Should this look like what mysqldump produces?
d529894e 76 #
77 $create .= "--\n-- Table: $table\n--\n" unless $no_comments;
2620fc1c 78 $create .= qq[DROP TABLE IF EXISTS $table;\n] if $add_drop_table;
c45c546e 79 $create .= "CREATE TABLE $table (";
9398955f 80
d529894e 81 #
9398955f 82 # Fields
d529894e 83 #
9398955f 84 for (my $i = 0; $i <= $#fields; $i++) {
85 my $field = $fields[$i];
1a24938d 86 debug("PKG: Looking at field '$field'\n");
9398955f 87 my $field_data = $table_data->{'fields'}->{$field};
88 my @fdata = ("", $field);
c45c546e 89 $create .= "\n";
9398955f 90
91 # data type and size
2620fc1c 92 my $attr = uc $field_data->{'data_type'} eq 'SET'
93 ? 'list' : 'size';
94 my @values = @{ $field_data->{ $attr } || [] };
95 my $data_type = $field_data->{'data_type'};
96
97 if ( $data_type eq 'number' ) {
98 # not an integer
99 if ( scalar @values > 1 ) {
100 $data_type = 'double';
101 }
102 elsif ( $values[0] >= 12 ) {
103 $data_type = 'bigint';
104 }
105 elsif ( $values[0] <= 1 ) {
106 $data_type = 'tinyint';
107 }
108 else {
109 $data_type = 'int';
110 }
111 }
112 elsif ( exists $translate{ $data_type } ) {
113 $data_type = $translate{ $data_type };
114 }
115
0a7fc605 116 push @fdata, sprintf "%s%s",
2620fc1c 117 $data_type,
0a7fc605 118 defined( $values[0] )
2620fc1c 119 ? '(' . join( ', ', @values ) . ')'
d529894e 120 : '';
121
122 # MySQL qualifiers
123 for my $qual ( qw[ binary unsigned zerofill ] ) {
124 push @fdata, $qual
125 if $field_data->{ $qual } ||
126 $field_data->{ uc $qual };
127 }
9398955f 128
129 # Null?
130 push @fdata, "NOT NULL" unless $field_data->{'null'};
131
132 # Default? XXX Need better quoting!
d529894e 133 my $default = $field_data->{'default'};
134 if ( defined $default ) {
135 if ( uc $default eq 'NULL') {
136 push @fdata, "DEFAULT NULL";
9398955f 137 } else {
138 push @fdata, "DEFAULT '$default'";
139 }
140 }
141
142 # auto_increment?
143 push @fdata, "auto_increment" if $field_data->{'is_auto_inc'};
144
145 # primary key?
d529894e 146 # This is taken care of in the indices, could be duplicated here
147 # push @fdata, "PRIMARY KEY" if $field_data->{'is_primary_key'};
9398955f 148
149
d529894e 150 $create .= (join " ", '', @fdata);
9398955f 151 $create .= "," unless ($i == $#fields);
56120730 152 }
9398955f 153
d529894e 154 #
155 # Indices
156 #
157 my @index_creates;
2620fc1c 158 my @indices = @{ $table_data->{'indices'} || [] };
159 my @constraints = @{ $table_data->{'constraints'} || [] };
56120730 160
2620fc1c 161 for my $key ( @indices, @constraints ) {
d529894e 162 my ($name, $type, $fields) = @{ $key }{ qw[ name type fields ] };
163 $name ||= '';
164 my $index_type =
165 $type eq 'primary_key' ? 'PRIMARY KEY' :
2620fc1c 166 $type eq 'unique' ? 'UNIQUE KEY' :
56120730 167 $type eq 'key' ? 'KEY' :
168 $type eq 'normal' ? 'KEY' : '';
169
2620fc1c 170 next unless $index_type;
56120730 171 push @index_creates,
d529894e 172 " $index_type $name (" . join( ', ', @$fields ) . ')';
c45c546e 173 }
9398955f 174
d529894e 175 if ( @index_creates ) {
176 $create .= join(",\n", '', @index_creates);
177 }
178
179 #
5e56da9a 180 # Constraints -- need to handle more than just FK. -ky
181 #
2620fc1c 182 my @constraint_defs;
183 for my $constraint ( @constraints ) {
5e56da9a 184 my $name = $constraint->{'name'} || '';
185 my $type = $constraint->{'type'};
186 my $fields = $constraint->{'fields'};
187 my $ref_table = $constraint->{'reference_table'};
188 my $ref_fields = $constraint->{'reference_fields'};
189 my $match_type = $constraint->{'match_type'} || '';
190 my $on_delete = $constraint->{'on_delete_do'};
191 my $on_update = $constraint->{'on_update_do'};
192
193 if ( $type eq 'foreign_key' ) {
194 my $def = join(' ', map { $_ || () } ' FOREIGN KEY', $name );
195 if ( @$fields ) {
196 $def .= ' (' . join( ', ', @$fields ) . ')';
197 }
198 $def .= " REFERENCES $ref_table";
199
023c4026 200 if ( @{ $ref_fields || [] } ) {
5e56da9a 201 $def .= ' (' . join( ', ', @$ref_fields ) . ')';
202 }
203
204 if ( $match_type ) {
205 $def .= ' MATCH ' .
206 ( $match_type =~ /full/i ) ? 'FULL' : 'PARTIAL';
207 }
208
586809da 209 if ( @{ $on_delete || [] } ) {
210 $def .= ' ON DELETE '.join(' ', @$on_delete);
211 }
212
213 if ( @{ $on_update || [] } ) {
214 $def .= ' ON UPDATE '.join(' ', @$on_update);
215 }
5e56da9a 216
2620fc1c 217 push @constraint_defs, $def;
5e56da9a 218 }
219 }
220
2620fc1c 221 $create .= join(",\n", '', @constraint_defs) if @constraint_defs;
5e56da9a 222
223 #
9398955f 224 # Footer
d529894e 225 #
c45c546e 226 $create .= "\n)";
95f99bd3 227 while (
228 my ( $key, $val ) = each %{ $table_data->{'table_options'} ||= {} }
229 ) {
d529894e 230 $create .= " $key=$val"
231 }
9398955f 232 $create .= ";\n\n";
233 }
234
9398955f 235 return $create;
236}
237
9398955f 2381;
239__END__
240
241=head1 NAME
242
758ab1cd 243SQL::Translator::Producer::MySQL - MySQL-specific producer for SQL::Translator
9398955f 244
9398955f 245=head1 AUTHOR
246
758ab1cd 247darren chamberlain E<lt>darren@cpan.orgE<gt>,
248Ken Y. Clark E<lt>kclark@cpan.orgE<gt>