1 package SQL::Translator::Producer::TT::Table;
3 # -------------------------------------------------------------------
4 # Copyright (C) 2002-2009 SQLFairy Authors
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 # -------------------------------------------------------------------
25 SQL::Translator::Producer::TT::Table -
26 Produces output using the Template Toolkit from a SQL schema, per table.
30 # Normal STDOUT version
32 my $translator = SQL::Translator->new(
34 filename => 'foo_schema.sql',
37 tt_table => 'foo_table.tt',
40 print $translator->translate;
42 # To generate a file per table
44 my $translator = SQL::Translator->new(
46 filename => 'foo_schema.sql',
49 tt_table => 'foo_table.tt.html',
51 mk_files_base => "./doc/tables",
52 mk_file_ext => ".html",
53 on_exists => "replace",
57 # ./doc/tables/ now contains the templated tables as $tablename.html
62 Produces schema output using a given Template Tookit template,
63 processing that template for each table in the schema. Optionally
64 allows you to write the result for each table to a separate file.
66 It needs one additional producer_arg of C<tt_table> which is the file
67 name of the template to use. This template will be passed a template
68 var of C<table>, which is the current
69 L<SQL::Translator::Producer::Table> table we are producing, which you
70 can then use to walk the schema via the methods documented in that
71 module. You also get L<schema> as a shortcut to the
72 L<SQL::Translator::Producer::Schema> for the table and C<translator>,
73 the L<SQL::Translator> object for this parse in case you want to get
74 access to any of the options etc set here.
76 Here's a brief example of what the template could look like:
80 [% FOREACH field = table.get_fields %]
81 [% field.name %] [% field.data_type %]([% field.size %])
84 See F<t/data/template/table.tt> for a more complete example.
86 You can also set any of the options used to initiallize the Template
87 object by adding them to your producer_args. See Template Toolkit docs
88 for details of the options.
90 $translator = SQL::Translator->new(
93 ttfile => 'foo_template.tt',
94 INCLUDE_PATH => '/foo/templates/tt',
99 If you set C<mk_files> and its additional options the producer will
100 write a separate file for each table in the schema. This is useful for
101 producing things like HTML documentation where every table gets its
102 own page (you could also use TTSchema producer to add an index page).
103 Its also particulary good for code generation where you want to
104 produce a class file per table.
112 File name of the template to run for each table.
116 Set to true to output a file for each table in the schema (as well as
117 returning the whole lot back to the Translalor and hence STDOUT). The
118 file will be named after the table, with the optional C<mk_files_ext>
119 added and placed in the directory C<mk_files_base>.
123 Extension (without the dot) to add to the filename when using mk_files.
125 =item mk_files_base = DIR
127 Dir to build the table files into when using mk_files. Defaults to the
132 Set true and if the file needs to written to a directory that doesn't
133 exist, it will be created first.
135 =item on_exists [Default:replace]
137 What to do if we are running with mk_files and a file already exists
138 where we want to write our output. One of "skip", "die", "replace",
139 "insert". The default is die.
141 B<replace> - Over-write the existing file with the new one, clobbering
142 anything already there.
144 B<skip> - Leave the origional file as it was and don't write the new
147 B<die> - Die with an existing file error.
149 B<insert> - Insert the generated output into the file bewteen a set of
150 special comments (defined by the following options.) Any code between
151 the comments will be overwritten (ie the results from a previous
152 produce) but the rest of the file is left alone (your custom code).
153 This is particularly useful for code generation as it allows you to
154 generate schema derived code and then add your own custom code
155 to the file. Then when the schema changes you just re-produce to
158 =item insert_comment_start
160 The comment to look for in the file when on_exists is C<insert>. Default
161 is C<SQLF INSERT START>. Must appear on it own line, with only
162 whitespace either side, to be recognised.
164 =item insert_comment_end
166 The end comment to look for in the file when on_exists is C<insert>.
167 Default is C<SQLF INSERT END>. Must appear on it own line, with only
168 whitespace either side, to be recognised.
174 # -------------------------------------------------------------------
178 use vars qw[ $DEBUG $VERSION @EXPORT_OK ];
180 $DEBUG = 0 unless defined $DEBUG;
186 use base qw(Exporter);
187 @EXPORT_OK = qw(produce);
189 use SQL::Translator::Utils 'debug';
195 local $DEBUG = $Translator->debug;
196 my $scma = $Translator->schema;
197 my $pargs = $Translator->producer_args;
198 my $file = $pargs->{'tt_table'} or die "No template file given!";
199 $pargs->{on_exists} ||= "die";
201 debug "Processing template $file\n";
203 my $tt = Template->new(
205 ABSOLUTE => 1, # Set so we can use from the command line sensibly
206 RELATIVE => 1, # Maybe the cmd line code should set it! Security!
207 %$pargs, # Allow any TT opts to be passed in the producer_args
208 ) || die "Failed to initialize Template object: ".Template->error;
210 for my $tbl ( sort {$a->order <=> $b->order} $scma->get_tables ) {
212 $tt->process( $file, {
213 translator => $Translator,
217 or die "Error processing template '$file' for table '".$tbl->name
221 # Write out the file...
222 write_file( table_file($tbl), $outtmp ) if $pargs->{mk_files};
228 # Work out the filename for a given table.
231 my $pargs = $Translator->producer_args;
232 my $root = $pargs->{mk_files_base};
233 my $ext = $pargs->{mk_file_ext};
234 return "$root/$tbl.$ext";
237 # Write the src given to the file given, handling the on_exists arg.
239 my ($file, $src) = @_;
240 my $pargs = $Translator->producer_args;
241 my $root = $pargs->{mk_files_base};
244 if ( $pargs->{on_exists} eq "skip" ) {
245 warn "Skipping existing $file\n";
248 elsif ( $pargs->{on_exists} eq "die" ) {
249 die "File $file already exists.\n";
251 elsif ( $pargs->{on_exists} eq "replace" ) {
252 warn "Replacing $file.\n";
254 elsif ( $pargs->{on_exists} eq "insert" ) {
255 warn "Inserting into $file.\n";
256 $src = insert_code($file, $src);
259 die "Unknown on_exists action: $pargs->{on_exists}\n";
263 warn "Creating $file.\n";
266 my ($dir) = $file =~ m!^(.*)/!; # Want greedy, eveything before the last /
267 if ( $dir and not -d $dir and $pargs->{mk_file_dir} ) { mkpath($dir); }
269 debug "Writing to $file\n";
270 open( FILE, ">$file") or die "Error opening file $file : $!\n";
275 # Reads file and inserts code between the insert comments and returns the new
278 my ($file, $src) = @_;
279 my $pargs = $Translator->producer_args;
280 my $cstart = $pargs->{insert_comment_start} || "SQLF_INSERT_START";
281 my $cend = $pargs->{insert_comment_end} || "SQLF_INSERT_END";
283 # Slurp in the origional file
284 open ( FILE, "<", "$file") or die "Error opening file $file : $!\n";
289 # Insert the new code between the insert comments
291 $orig =~ s/^\s*?$cstart\s*?\n.*?^\s*?$cend\s*?\n/\n$cstart\n$src\n$cend\n/ms
293 warn "No insert done\n";
301 # -------------------------------------------------------------------
307 Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.
311 - Some tests for the various on exists options (they have been tested
312 implicitley through use in a project but need some proper tests).
314 - More docs on code generation strategies.
316 - Better hooks for filename generation.
318 - Integrate with L<TT::Base> and L<TTSchema>.