Added support for producer_args and parser_args.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Validator.pm
CommitLineData
e2158c40 1package SQL::Translator::Validator;
2
3# ----------------------------------------------------------------------
4# $Id: Validator.pm,v 1.1 2002-03-26 12:46:54 dlc Exp $
5# ----------------------------------------------------------------------
6# Copyright (C) 2002 Ken Y. Clark <kycl4rk@users.sourceforge.net>,
7# darren chamberlain <darren@cpan.org>
8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License as
11# published by the Free Software Foundation; version 2.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21# 02111-1307 USA
22# ----------------------------------------------------------------------
23
24use strict;
25use vars qw($VERSION @EXPORT);
26$VERSION = sprintf "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/;
27
28use Exporter;
29use base qw(Exporter);
30@EXPORT = qw(validate);
31
32use Data::Dumper;
33
34sub by_context($$$) { ($_[0]) ? ($_[1], $_[2]) : $_[1]; }
35
36sub validate {
37 my $data = shift;
38 my $wa = wantarray;
39 my ($ok, $log);
40
41 unless (ref $data) {
42 return by_context $wa, 0, "Not a reference";
43 }
44
45 unless (UNIVERSAL::isa($data, "HASH")) {
46 return by_context $wa, 0, "Not a HASH reference";
47 } else {
48 my $num = scalar keys %{$data};
49 $log = sprintf "Contains %d table%s.", $num, ($num == 1 ? "" : "s");
50 }
51
52 my @tables = sort keys %{$data};
53 for (my $i = 0; $i < @tables; $i++) {
54 my $table = $tables[$i];
55 my $table_num = $i + 1;
56
57 $log .= "\nTable $table_num: $table";
58 my $table_data = $data->{$table};
59
60 # Table must be a hashref
61 unless (UNIVERSAL::isa($table_data, "HASH")) {
62 return by_context $wa, 0,
63 "Table `$table' is not a HASH reference";
64 }
65
66 # Table must contain three elements: type, indeces, and fields
67 # XXX If there are other keys, is this an error?
68 unless (exists $table_data->{"type"}) {
69 return by_context $wa, 0, "Missing type for table `$table'";
70 } else {
71 $log .= sprintf "\n\tType: %s", $table_data->{"type"} ||
72 "not defined";
73 }
74
75 # Indeces: array of hashes
76 unless (defined $table_data->{"indeces"} &&
77 UNIVERSAL::isa($table_data->{"indeces"}, "ARRAY")) {
78 return by_context $wa, 0, "Indeces is missing or is not an ARRAY";
79 } else {
80 my @indeces = @{$table_data->{"indeces"}};
81 $log .= "\n\tIndeces:";
82 if (@indeces) {
83 for my $index (@indeces) {
84 $log .= "\n\t\t" . ($index->{"name"} || "(unnamed)")
85 . " on "
86 . join ", ", @{$index->{"fields"}};
87 }
88 } else {
89 $log .= " none defined";
90 }
91 }
92
93 # Fields
94 unless (defined $table_data->{"fields"} &&
95 UNIVERSAL::isa($table_data->{"fields"}, "HASH")) {
96 return by_context $wa, 0, "Fields is missing or is not a HASH";
97 } else {
98 $log .= "\n\tFields:";
99 my @fields = sort { $table_data->{$a}->{"order"} <=>
100 $table_data->{$b}->{"order"}
101 } keys %{$table_data->{"fields"}};
102 for my $field (@fields) {
103 my $field_data = $table_data->{"fields"}->{$field};
104 $log .= qq|\n\t\t$field_data->{"name"}|
105 . qq| $field_data->{"data_type"} ($field_data->{"size"})|;
106 $log .= qq|\n\t\t\tDefault: $field_data->{"default"}|
107 if length $field_data->{"default"};
108 $log .= sprintf qq|\n\t\t\tNull: %s|,
109 $field_data->{"null"} ? "yes" : "no";
110 }
111 }
112 }
113
114 $log .= "\n";
115
116 return by_context $wa, 1, $log;
117}
118
119
1201;
121__END__
122
123=head1 NAME
124
125SQL::Translator::Validate - Validate that a data structure is correct
126
127=head1 SYNOPSIS
128
129 print "1..1\n";
130
131 use SQL::Translator;
132 use SQL::Translator::Validator;
133
134 my $tr = SQL::Translator->new(parser => "My::Swell::Parser");
135
136 # Default producer passes the data structure through unchanged
137 my $parsed = $tr->translate($datafile);
138
139 print "not " unless validate($parsed);
140 print "ok 1 # data structure looks OK\n";
141
142=head1 DESCRIPTION
143
144When writing a parser module for SQL::Translator, it is helpful to
145have a tool to automatically check the return of your module, to make
146sure that it is returning the Right Thing. While only a full Producer
147and the associated database can determine if you are producing valud
148output, SQL::Translator::Validator can tell you if the basic format of
149the data structure is correct. While this will not catch many errors,
150it will catch the basic ones.
151
152SQL::Translator::Validator can be used as a development tool, a
153testing tool (every SQL::Translator install will have this module),
154or, potentially, even as a runtime assertion for producers you don't
155trust:
156
157 $tr->producer(\&paranoid_producer);
158 sub paranoid_producer {
159 my ($tr, $data) = @_;
160 return unless validate($data);
161
162 # continue...
163
164=head1 EXPORTED FUNCTIONS
165
166SQL::Translator::Validator exports a single function, called
167B<validate>, which expects a data structure as its only argument.
168When called in scalar context, it returns a 1 (valid data structure)
169or 0 (not a valid data structure). In list context, B<validate>
170returns a 2 element list: the first element is a 1 or 0, as in scalar
171context, and the second value is a reason (for a malformed data
172structure) or a summary of the data (for a well-formed data
173structure).
174
175=head1 TODO
176
177=over 4
178
179=item *
180
181color, either via Term::ANSI, or something along those lines, or just
182plain $RED = "\033[31m" type stuff.
183
184=back
185
186=head1 AUTHOR
187
188darren chamberlain E<lt>darren@cpan.orgE<gt>