Add support for parsing PostgreSQL dollar-quoted strings
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Producer / TT / Base.pm
CommitLineData
f5f03b78 1package SQL::Translator::Producer::TT::Base;
2
11a8c77a 3=pod
f5f03b78 4
5=head1 NAME
6
11a8c77a 7SQL::Translator::Producer::TT::Base - TT (Template Toolkit) based Producer base
8class.
f5f03b78 9
10=cut
11
f5f03b78 12use strict;
f27f9229 13use warnings;
f5f03b78 14
0c04c5a2 15our @EXPORT_OK;
16our $VERSION = '1.59';
f5f03b78 17
18use Template;
19use Data::Dumper;
bfd86e76 20use IO::Handle;
f5f03b78 21use Exporter;
22use base qw(Exporter);
23@EXPORT_OK = qw(produce);
24
25use SQL::Translator::Utils 'debug';
26
27# Hack to convert the produce call into an object. ALL sub-classes need todo
28# this so that the correct class gets created.
29sub produce {
30 return __PACKAGE__->new( translator => shift )->run;
31};
32
33sub new {
34 my $proto = shift;
35 my $class = ref $proto || $proto;
36 my %args = @_;
37
38 my $me = bless {}, $class;
39 $me->{translator} = delete $args{translator} || die "Need a translator.";
40
41 return $me;
42}
43
44sub translator { shift->{translator}; }
45sub schema { shift->{translator}->schema(@_); }
46
7f3fc883 47# Util args access method.
f5f03b78 48# No args - Return hashref (the actual hash in Translator) or hash of args.
49# 1 arg - Return that named args value.
50# Args - List of names. Return values of the given arg names in list context
51# or return as hashref in scalar context. Any names given that don't
7f3fc883 52# exist in the args are returned as undef.
f5f03b78 53sub args {
54 my $me = shift;
55
56 # No args
57 unless (@_) {
7f3fc883 58 return wantarray
f5f03b78 59 ? %{ $me->{translator}->producer_args }
60 : $me->{translator}->producer_args
61 ;
62 }
63
64 # 1 arg. Return the value whatever the context.
65 return $me->{translator}->producer_args->{$_[0]} if @_ == 1;
66
67 # More args so return values list or hash ref
68 my %args = %{ $me->{translator}->producer_args };
69 return wantarray ? @args{@_} : { map { ($_=>$args{$_}) } @_ };
70}
71
72# Run the produce and return the result.
73sub run {
74 my $me = shift;
75 my $scma = $me->schema;
76 my %args = %{$me->args};
77 my $tmpl = $me->tt_schema or die "No template!";
78
79 debug "Processing template $tmpl\n";
80 my $out;
7f3fc883 81 my $tt = Template->new(
f5f03b78 82 #DEBUG => $me->translator->debug,
7f3fc883 83 ABSOLUTE => 1, # Set so we can use from the command line sensibly
84 RELATIVE => 1, # Maybe the cmd line code should set it! Security!
85 $me->tt_config, # Hook for sub-classes to add config
86 %args, # Allow any TT opts to be passed in the producer_args
f5f03b78 87 ) || die "Failed to initialize Template object: ".Template->error;
88
7f3fc883 89 $tt->process( $tmpl, {
90 $me->tt_default_vars,
91 $me->tt_vars, # Sub-class hook for adding vars
92 }, \$out )
f5f03b78 93 or die "Error processing template '$tmpl': ".$tt->error;
94
95 return $out;
96}
97
11a8c77a 98
99# Sub class hooks
100#-----------------------------------------------------------------------------
101
102sub tt_config { () };
103
bfd86e76 104sub tt_schema {
105 my $me = shift;
106 my $class = ref $me;
107
108 my $file = $me->args("ttfile");
109 return $file if $file;
110
111 no strict 'refs';
112 my $ref = *{"$class\:\:DATA"}{IO};
113 if ( $ref->opened ) {
114 local $/ = undef; # Slurp mode
115 return \<$ref>;
116 }
117
118 undef;
119};
f5f03b78 120
f5f03b78 121sub tt_default_vars {
122 my $me = shift;
123 return (
124 translator => $me->translator,
bfd86e76 125 schema => $me->pre_process_schema($me->translator->schema),
f5f03b78 126 );
127}
128
bfd86e76 129sub pre_process_schema { $_[1] }
130
7f3fc883 131sub tt_vars { () };
132
f5f03b78 1331;
134
f5f03b78 135=pod
136
11a8c77a 137=head1 SYNOPSIS
138
466c88de 139 # Create a producer using a template in the __DATA__ section.
11a8c77a 140 package SQL::Translator::Producer::Foo;
141
142 use base qw/SQL::Translator::Producer::TT::Base/;
143
f33f9d70 144 # Convert produce call into a method call on our new class
11a8c77a 145 sub produce { return __PACKAGE__->new( translator => shift )->run; };
146
11a8c77a 147 # Configure the Template object.
148 sub tt_config { ( INTERPOLATE => 1 ); }
149
150 # Extra vars to add to the template
151 sub tt_vars { ( foo => "bar" ); }
152
bfd86e76 153 # Put template in DATA section (or use file with ttfile producer arg)
154 __DATA__
155 Schema
f33f9d70 156
bfd86e76 157 Database: [% schema.database %]
158 Foo: $foo
159 ...
160
11a8c77a 161=head1 DESCRIPTION
162
11a8c77a 163A base class producer designed to be sub-classed to create new TT based
164producers cheaply - by simply giving the template to use and sprinkling in some
165extra template variables and config.
166
466c88de 167You can find an introduction to this module in L<SQL::Translator::Manual>.
168
11a8c77a 169The 1st thing the module does is convert the produce sub routine call we get
f33f9d70 170from SQL::Translator into a method call on an object, which we can then
171sub-class. This is done with the following code which needs to appear in B<all>
172sub classes.
11a8c77a 173
174 # Convert produce call into an object method call
175 sub produce { return __PACKAGE__->new( translator => shift )->run; };
176
ac7adbab 177See L</PRODUCER OBJECT> below for details.
11a8c77a 178
f33f9d70 179The upshot of this is we can make new template producers by sub classing this
180base class, adding the above snippet and a template.
181The module also provides a number of hooks into the templating process,
ac7adbab 182see L</SUB CLASS HOOKS> for details.
11a8c77a 183
ac7adbab 184See the L</SYNOPSIS> above for an example of creating a simple producer using
11a8c77a 185a single template stored in the producers DATA section.
186
187=head1 SUB CLASS HOOKS
188
f33f9d70 189Sub-classes can override these methods to control the templating by giving
11a8c77a 190the template source, adding variables and giving config to the Tempate object.
191
192=head2 tt_config
193
194 sub tt_config { ( INTERPOLATE => 1 ); }
195
f33f9d70 196Return hash of Template config to add to that given to the L<Template> C<new>
197method.
11a8c77a 198
199=head2 tt_schema
200
201 sub tt_schema { "foo.tt"; }
202 sub tt_schema { local $/ = undef; \<DATA>; }
203
f33f9d70 204The template to use, return a file name or a scalar ref of TT
205source, or an L<IO::Handle>. See L<Template> for details, as the return from
206this is passed on to it's C<produce> method.
11a8c77a 207
7ce70c58 208The default implementation uses the producer arg C<ttfile> as a filename to read
f33f9d70 209the template from. If the arg isn't there it will look for a C<__DATA__> section
bfd86e76 210in the class, reading it as template source if found. Returns undef if both
211these fail, causing the produce call to fail with a 'no template!' error.
11a8c77a 212
213=head2 tt_vars
214
215 sub tt_vars { ( foo => "bar" ); }
216
f33f9d70 217Return hash of template vars to use in the template. Nothing added here
ac7adbab 218by default, but see L</tt_default_vars> for the variables you get for free.
11a8c77a 219
220=head2 tt_default_vars
221
222Return a hash-ref of the default vars given to the template.
7ce70c58 223You wouldn't normally over-ride this, just inherit the default implementation,
ac7adbab 224to get the C<translator> & C<schema> variables, then over-ride L</tt_vars> to add
11a8c77a 225your own.
226
227The current default variables are:
228
229=over 4
230
231=item schema
232
233The schema to template.
234
235=item translator
236
237The L<SQL::Translator> object.
238
239=back
240
bfd86e76 241=head2 pre_process_schema
242
243WARNING: This method is Experimental so may change!
244
f33f9d70 245Called with the L<SQL::Translator::Schema> object and should return one (it
7ce70c58 246doesn't have to be the same one) that will become the C<schema> variable used
f33f9d70 247in the template.
bfd86e76 248
249Gets called from tt_default_vars.
250
11a8c77a 251=head1 PRODUCER OBJECT
252
253The rest of the methods in the class set up a sub-classable producer object.
254You normally just inherit them.
255
256=head2 new
257
258 my $tt_producer = TT::Base->new( translator => $translator );
259
260Construct a new TT Producer object. Takes a single, named arg of the
261L<SQL::Translator> object running the translation. Dies if this is not given.
262
263=head2 translator
264
265Return the L<SQL::Translator> object.
266
267=head2 schema
268
7ce70c58 269Return the L<SQL::Translator::Schema> we are translating. This is equivalent
11a8c77a 270to C<< $tt_producer->translator->schema >>.
271
f33f9d70 272=head2 run
273
274Called to actually produce the output, calling the sub class hooks. Returns the
275produced text.
276
11a8c77a 277=head2 args
278
279Util wrapper method around C<< TT::Base->translator->producer_args >> for
7ce70c58 280(mostly) readonly access to the producer args. How it works depends on the
11a8c77a 281number of arguments you give it and the context.
282
283 No args - Return hashref (the actual hash in Translator) or hash of args.
284 1 arg - Return value of the arg with the passed name.
f33f9d70 285 2+ args - List of names. In list context returns values of the given arg
286 names, returns as a hashref in scalar context. Any names given
287 that don't exist in the args are returned as undef.
11a8c77a 288
f33f9d70 289This is still a bit messy but is a handy way to access the producer args when
290you use your own to drive the templating.
11a8c77a 291
f33f9d70 292=head1 SEE ALSO
f5f03b78 293
f33f9d70 294L<perl>,
295L<SQL::Translator>,
296L<Template>.
f5f03b78 297
298=head1 TODO
299
11a8c77a 300- Add support for a sqlf template repository, set as an INCLUDE_PATH,
301so that sub-classes can easily include file based templates using relative
302paths.
f5f03b78 303
f33f9d70 304- Pass in template vars from the producer args and command line.
305
ac7adbab 306- Merge in L<TT::Table|SQL::Translator::Producer::TT::Table>.
f5f03b78 307
11a8c77a 308- Hooks to pre-process the schema and post-process the output.
309
f33f9d70 310=head1 AUTHOR
f5f03b78 311
f33f9d70 312Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.
f5f03b78 313
314=cut