This file is indexed.

/usr/share/perl5/SQL/Translator/Producer/TT/Table.pm is in libsql-translator-perl 0.11024-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
package SQL::Translator::Producer::TT::Table;

=pod

=head1 NAME

SQL::Translator::Producer::TT::Table -
    Produces output using the Template Toolkit from a SQL schema, per table.

=head1 SYNOPSIS

  # Normal STDOUT version
  #
  my $translator     = SQL::Translator->new(
      from           => 'MySQL',
      filename       => 'foo_schema.sql',
      to             => 'TT::Table',
      producer_args  => {
          tt_table     => 'foo_table.tt',
      },
  );
  print $translator->translate;

  # To generate a file per table
  #
  my $translator     = SQL::Translator->new(
      from           => 'MySQL',
      filename       => 'foo_schema.sql',
      to             => 'TT::Table',
      producer_args  => {
          tt_table       => 'foo_table.tt.html',
          mk_files      => 1,
          mk_files_base => "./doc/tables",
          mk_file_ext   => ".html",
          on_exists     => "replace",
      },
  );
  #
  # ./doc/tables/ now contains the templated tables as $tablename.html
  #

=head1 DESCRIPTION

Produces schema output using a given Template Tookit template,
processing that template for each table in the schema. Optionally
allows you to write the result for each table to a separate file.

It needs one additional producer_arg of C<tt_table> which is the file
name of the template to use.  This template will be passed a template
var of C<table>, which is the current
L<SQL::Translator::Schema::Table> table we are producing,
which you can then use to walk the schema via the methods documented
in that module. You also get C<schema> as a shortcut to the
L<SQL::Translator::Schema> for the table and C<translator>,
the L<SQL::Translator> object for this parse in case you want to get
access to any of the options etc set here.

Here's a brief example of what the template could look like:

  [% table.name %]
  ================
  [% FOREACH field = table.get_fields %]
      [% field.name %]   [% field.data_type %]([% field.size %])
  [% END -%]

See F<t/data/template/table.tt> for a more complete example.

You can also set any of the options used to initialize the Template
object by adding them to your producer_args. See Template Toolkit docs
for details of the options.

  $translator          = SQL::Translator->new(
      to               => 'TT',
      producer_args    => {
          ttfile       => 'foo_template.tt',
          INCLUDE_PATH => '/foo/templates/tt',
          INTERPOLATE  => 1,
      },
  );

If you set C<mk_files> and its additional options the producer will
write a separate file for each table in the schema. This is useful for
producing things like HTML documentation where every table gets its
own page (you could also use TTSchema producer to add an index page).
It's also particularly good for code generation where you want to
produce a class file per table.

=head1 OPTIONS

=over 4

=item tt_table

File name of the template to run for each table.

=item mk_files

Set to true to output a file for each table in the schema (as well as
returning the whole lot back to the Translalor and hence STDOUT). The
file will be named after the table, with the optional C<mk_files_ext>
added and placed in the directory C<mk_files_base>.

=item mk_files_ext

Extension (without the dot) to add to the filename when using mk_files.

=item mk_files_base = DIR

Dir to build the table files into when using mk_files. Defaults to the
current directory.

=item mk_file_dir

Set true and if the file needs to written to a directory that doesn't
exist, it will be created first.

=item on_exists [Default:replace]

What to do if we are running with mk_files and a file already exists
where we want to write our output. One of "skip", "die", "replace",
"insert".  The default is die.

B<replace> - Over-write the existing file with the new one, clobbering
anything already there.

B<skip> - Leave the original file as it was and don't write the new
version anywhere.

B<die> - Die with an existing file error.

B<insert> - Insert the generated output into the file between a set of
special comments (defined by the following options.) Any code between
the comments will be overwritten (ie the results from a previous
produce) but the rest of the file is left alone (your custom code).
This is particularly useful for code generation as it allows you to
generate schema derived code and then add your own custom code
to the file.  Then when the schema changes you just re-produce to
insert the new code.

=item insert_comment_start

The comment to look for in the file when on_exists is C<insert>. Default
is C<SQLF INSERT START>. Must appear on it own line, with only
whitespace either side, to be recognised.

=item insert_comment_end

The end comment to look for in the file when on_exists is C<insert>.
Default is C<SQLF INSERT END>. Must appear on it own line, with only
whitespace either side, to be recognised.

=back

=cut

use strict;
use warnings;

our ( $DEBUG, @EXPORT_OK );
our $VERSION = '1.59';
$DEBUG   = 0 unless defined $DEBUG;

use File::Path;
use Template;
use Data::Dumper;
use Exporter;
use base qw(Exporter);
@EXPORT_OK = qw(produce);

use SQL::Translator::Utils 'debug';

my $Translator;

sub produce {
    $Translator = shift;
    local $DEBUG   = $Translator->debug;
    my $scma       = $Translator->schema;
    my $pargs      = $Translator->producer_args;
    my $file       = $pargs->{'tt_table'} or die "No template file given!";
    $pargs->{on_exists} ||= "die";

    debug "Processing template $file\n";
    my $out;
    my $tt       = Template->new(
        DEBUG    => $DEBUG,
        ABSOLUTE => 1, # Set so we can use from the command line sensibly
        RELATIVE => 1, # Maybe the cmd line code should set it! Security!
        %$pargs,        # Allow any TT opts to be passed in the producer_args
    ) || die "Failed to initialize Template object: ".Template->error;

   for my $tbl ( sort {$a->order <=> $b->order} $scma->get_tables ) {
      my $outtmp;
        $tt->process( $file, {
            translator => $Translator,
            schema     => $scma,
            table      => $tbl,
        }, \$outtmp )
      or die "Error processing template '$file' for table '".$tbl->name
             ."': ".$tt->error;
        $out .= $outtmp;

        # Write out the file...
      write_file(  table_file($tbl), $outtmp ) if $pargs->{mk_files};
    }

    return $out;
};

# Work out the filename for a given table.
sub table_file {
    my ($tbl) = shift;
    my $pargs = $Translator->producer_args;
    my $root  = $pargs->{mk_files_base};
    my $ext   = $pargs->{mk_file_ext};
    return "$root/$tbl.$ext";
}

# Write the src given to the file given, handling the on_exists arg.
sub write_file {
   my ($file, $src) = @_;
    my $pargs = $Translator->producer_args;
    my $root = $pargs->{mk_files_base};

    if ( -e $file ) {
        if ( $pargs->{on_exists} eq "skip" ) {
            warn "Skipping existing $file\n";
            return 1;
        }
        elsif ( $pargs->{on_exists} eq "die" ) {
            die "File $file already exists.\n";
        }
        elsif ( $pargs->{on_exists} eq "replace" ) {
            warn "Replacing $file.\n";
        }
        elsif ( $pargs->{on_exists} eq "insert" ) {
            warn "Inserting into $file.\n";
            $src = insert_code($file, $src);
        }
        else {
            die "Unknown on_exists action: $pargs->{on_exists}\n";
        }
    }
    else {
        if ( my $interactive = -t STDIN && -t STDOUT ) {
            warn "Creating $file.\n";
        }
    }

    my ($dir) = $file =~ m!^(.*)/!; # Want greedy, everything before the last /
   if ( $dir and not -d $dir and $pargs->{mk_file_dir} ) { mkpath($dir); }

    debug "Writing to $file\n";
   open( FILE, ">$file") or die "Error opening file $file : $!\n";
   print FILE $src;
   close(FILE);
}

# Reads file and inserts code between the insert comments and returns the new
# source.
sub insert_code {
    my ($file, $src) = @_;
    my $pargs = $Translator->producer_args;
    my $cstart = $pargs->{insert_comment_start} || "SQLF_INSERT_START";
    my $cend   = $pargs->{insert_comment_end}   || "SQLF_INSERT_END";

    # Slurp in the original file
    open ( FILE, "<", "$file") or die "Error opening file $file : $!\n";
    local $/ = undef;
    my $orig = <FILE>;
    close(FILE);

    # Insert the new code between the insert comments
    unless (
        $orig =~ s/^\s*?$cstart\s*?\n.*?^\s*?$cend\s*?\n/\n$cstart\n$src\n$cend\n/ms
    ) {
        warn "No insert done\n";
    }

    return $orig;
}

1;

=pod

=head1 AUTHOR

Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.

=head1 TODO

- Some tests for the various on exists options (they have been tested
implicitly through use in a project but need some proper tests).

- More docs on code generation strategies.

- Better hooks for filename generation.

- Integrate with L<TT::Base|SQL::Translator::Producer::TT::Base> and
  L<TTSchema|SQL::Translator::Producer::TTSchema>.

=head1 SEE ALSO

SQL::Translator.

=cut