a payload per se.
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut
|
150
|
|
|
|
|
|
|
sub build_payload {
|
151
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
152
|
0
|
|
|
|
|
|
$self->{dictionary} = $self->find_context('data-dictionary');
|
153
|
0
|
|
|
|
|
|
foreach ($self->nodes) {
|
154
|
0
|
0
|
|
|
|
|
$_->build if $_->can('build');
|
155
|
|
|
|
|
|
|
}
|
156
|
|
|
|
|
|
|
|
157
|
0
|
0
|
|
|
|
|
return $self->build_table(@_) if $self->is('table');
|
158
|
0
|
|
|
|
|
|
$self->build_ddict(@_);
|
159
|
|
|
|
|
|
|
}
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub build_table {
|
162
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
163
|
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
$self->{tables} = [];
|
165
|
0
|
|
|
|
|
|
$self->{table_data} = {};
|
166
|
0
|
|
|
|
|
|
push @{$self->{tables}}, $self->name;
|
|
0
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
foreach my $l ($self->nodes()) {
|
168
|
0
|
0
|
|
|
|
|
if ($l->is('query')) {
|
169
|
|
|
|
|
|
|
# Not handling at the moment
|
170
|
|
|
|
|
|
|
} else {
|
171
|
|
|
|
|
|
|
# Anything else is either a list/link or a field.
|
172
|
0
|
|
|
|
|
|
my ($fname, $def) = $self->sql_single_field($self->name, $l);
|
173
|
0
|
0
|
0
|
|
|
|
$self->{key} = $fname if ($def->{key}) and not $self->{key};
|
174
|
|
|
|
|
|
|
}
|
175
|
0
|
0
|
|
|
|
|
if (not $self->{key}) {
|
176
|
0
|
|
|
|
|
|
$self->{key} = $self->default_key($self->name);
|
177
|
|
|
|
|
|
|
}
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
|
180
|
0
|
|
|
|
|
|
my $database = $self->find_context('database');
|
181
|
0
|
|
|
|
|
|
my $dbtype = '';
|
182
|
0
|
0
|
|
|
|
|
$dbtype = $database->{database_type} if defined $database;
|
183
|
0
|
|
|
|
|
|
my $db = undef;
|
184
|
0
|
0
|
0
|
|
|
|
$db = $database if defined $database and $database->parameter('tables') eq 'active';
|
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
$self->{sql} = join ("\n", map { $self->sql_single_table($_, $dbtype, $db) } @{$self->{tables}});
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head2 Helper functions sql_single_table() and sql_single_field
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
These functions just spin out some SQL based on our data structures.
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=cut
|
197
|
|
|
|
|
|
|
sub sql_single_table {
|
198
|
0
|
|
|
0
|
1
|
|
my ($self, $table, $dbtype, $db) = @_;
|
199
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
|
my $table_info;
|
201
|
|
|
|
|
|
|
|
202
|
0
|
0
|
|
|
|
|
if (defined $db) {
|
203
|
0
|
|
|
|
|
|
$table_info = $db->table_info($table);
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
my @fields = map {
|
207
|
0
|
|
|
|
|
|
my $fd = $self->{table_data}->{$table}->{fielddata}->{$_};
|
208
|
0
|
0
|
|
|
|
|
"$_ " . $fd->{type} . ($fd->{size} eq '' ? '' : ' (' . $fd->{size} . ")")
|
209
|
0
|
|
|
|
|
|
} @{$self->{table_data}->{$table}->{fields}};
|
210
|
|
|
|
|
|
|
|
211
|
0
|
|
|
|
|
|
my $sql = "create table $table (\n " .
|
212
|
|
|
|
|
|
|
join (",\n ", @fields) .
|
213
|
|
|
|
|
|
|
"\n);\n";
|
214
|
|
|
|
|
|
|
|
215
|
0
|
0
|
0
|
|
|
|
if (defined $db and not defined $table_info) {
|
216
|
0
|
|
|
|
|
|
print "Creating table $table\n";
|
217
|
0
|
|
|
|
|
|
$db->dbh->do($sql);
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
|
return $sql;
|
221
|
|
|
|
|
|
|
}
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub sql_single_field {
|
224
|
0
|
|
|
0
|
1
|
|
my ($self, $table, $field) = @_;
|
225
|
0
|
0
|
|
|
|
|
if ($field->is('list')) {
|
226
|
0
|
0
|
|
|
|
|
if ($field->nodes) {
|
227
|
|
|
|
|
|
|
# Subtable.
|
228
|
0
|
|
0
|
|
|
|
my $tname = $field->name || 'list';
|
229
|
0
|
|
|
|
|
|
my $subtable = $table . '_' . $tname;
|
230
|
0
|
|
|
|
|
|
push @{$self->{tables}}, $subtable;
|
|
0
|
|
|
|
|
|
|
231
|
0
|
|
|
|
|
|
my $key = $self->get_table_key($table);
|
232
|
0
|
|
|
|
|
|
my $keydef = $self->get_table_field($table, $key);
|
233
|
0
|
|
|
|
|
|
my $def = {
|
234
|
|
|
|
|
|
|
type => $keydef->{type},
|
235
|
|
|
|
|
|
|
size => $keydef->{size},
|
236
|
|
|
|
|
|
|
key => 0,
|
237
|
|
|
|
|
|
|
};
|
238
|
0
|
|
|
|
|
|
my $parent_key = 'ref_' . $key;
|
239
|
0
|
|
|
|
|
|
$self->add_field($subtable, $parent_key, $def);
|
240
|
0
|
|
|
|
|
|
$self->{tabledata}->{$subtable}->{parent_key} = $parent_key;
|
241
|
0
|
|
|
|
|
|
foreach ($field->nodes) {
|
242
|
0
|
|
|
|
|
|
$self->sql_single_field($subtable, $_);
|
243
|
|
|
|
|
|
|
}
|
244
|
|
|
|
|
|
|
} else {
|
245
|
0
|
|
|
|
|
|
my @names = $field->names;
|
246
|
0
|
|
|
|
|
|
my $tname;
|
247
|
0
|
0
|
|
|
|
|
if (@names == 0) {
|
|
|
0
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# error
|
249
|
0
|
|
|
|
|
|
next;
|
250
|
|
|
|
|
|
|
} elsif (@names == 1) {
|
251
|
0
|
|
|
|
|
|
$tname = $names[0];
|
252
|
|
|
|
|
|
|
} else {
|
253
|
0
|
|
|
|
|
|
$tname = $names[1];
|
254
|
|
|
|
|
|
|
}
|
255
|
0
|
|
|
|
|
|
push @{$self->{tables}}, $table . '_link_' . $tname;
|
|
0
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
}
|
257
|
|
|
|
|
|
|
} else {
|
258
|
0
|
|
0
|
|
|
|
my $fname = $field->name || $field->tag;
|
259
|
0
|
|
|
|
|
|
my $type = $field->tag;
|
260
|
0
|
|
0
|
|
|
|
my $size = $field->parameter_n(0) || '';
|
261
|
0
|
|
0
|
|
|
|
my $key = $field->is('key') || $field->parameter('key') || 0;
|
262
|
0
|
0
|
|
|
|
|
if ($size eq 'key') {
|
263
|
0
|
|
0
|
|
|
|
$size = $field->parameter_n(1) || '';
|
264
|
0
|
|
|
|
|
|
$key = 1;
|
265
|
|
|
|
|
|
|
}
|
266
|
0
|
0
|
|
|
|
|
if (defined $self->{dictionary}) {
|
267
|
0
|
|
|
|
|
|
my $dict = $self->{dictionary}->dictionary_lookup($type);
|
268
|
0
|
0
|
|
|
|
|
if (defined $dict) {
|
269
|
0
|
|
|
|
|
|
$type = $dict->{type};
|
270
|
0
|
0
|
|
|
|
|
$size = $dict->{size} unless $size;
|
271
|
0
|
0
|
|
|
|
|
$key = $dict->{key} unless $key;
|
272
|
|
|
|
|
|
|
}
|
273
|
|
|
|
|
|
|
}
|
274
|
0
|
|
|
|
|
|
my $def = {
|
275
|
|
|
|
|
|
|
type => $type,
|
276
|
|
|
|
|
|
|
size => $size,
|
277
|
|
|
|
|
|
|
key => $key,
|
278
|
|
|
|
|
|
|
};
|
279
|
0
|
|
|
|
|
|
$self->add_field($table, $fname, $def);
|
280
|
0
|
|
|
|
|
|
return ($fname, $def);
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
}
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub build_ddict {
|
285
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
286
|
0
|
|
|
|
|
|
$self->{tables} = ['dictionary'];
|
287
|
0
|
|
|
|
|
|
$self->{table_data}->{dictionary}->{fields} = [];
|
288
|
0
|
|
|
|
|
|
$self->{table_data}->{dictionary}->{fielddata} = {};
|
289
|
0
|
|
|
|
|
|
foreach my $l ($self->nodes()) {
|
290
|
0
|
|
|
|
|
|
$self->sql_single_field('dictionary', $l);
|
291
|
|
|
|
|
|
|
}
|
292
|
|
|
|
|
|
|
}
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=head2 dictionary_lookup
|
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
This is called by a table on its dictionary to see if the dictionary knows about a given field. If the dictionary doesn't know, and if there
|
297
|
|
|
|
|
|
|
is a higher-level data dictionary, then it gets called, and so on.
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=cut
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub dictionary_lookup {
|
302
|
0
|
|
|
0
|
1
|
|
my ($self, $field) = @_;
|
303
|
0
|
|
|
|
|
|
my $possible = $self->{table_data}->{dictionary}->{fielddata}->{$field};
|
304
|
0
|
0
|
|
|
|
|
return $possible if defined $possible;
|
305
|
0
|
0
|
|
|
|
|
if (defined $self->{dictionary}) {
|
306
|
0
|
|
|
|
|
|
return $self->{dictionary}->dictionary_lookup($field);
|
307
|
|
|
|
|
|
|
}
|
308
|
0
|
|
|
|
|
|
return;
|
309
|
|
|
|
|
|
|
}
|
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head2 default_key, add_default_key, get_table_key, get_table_field, add_field
|
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Table access functions.
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=cut
|
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub default_key {
|
318
|
0
|
|
|
0
|
1
|
|
my ($self, $table) = @_;
|
319
|
0
|
|
|
|
|
|
$table . '_id';
|
320
|
|
|
|
|
|
|
}
|
321
|
|
|
|
|
|
|
sub add_default_key {
|
322
|
0
|
|
|
0
|
1
|
|
my ($self, $table) = @_;
|
323
|
0
|
|
|
|
|
|
my $key = $self->default_key($table);
|
324
|
0
|
|
|
|
|
|
unshift @{$self->{table_data}->{$table}->{fields}}, $key;
|
|
0
|
|
|
|
|
|
|
325
|
0
|
|
|
|
|
|
$self->{table_data}->{$table}->{fielddata}->{$key} = {
|
326
|
|
|
|
|
|
|
type => 'int',
|
327
|
|
|
|
|
|
|
size => 'size',
|
328
|
|
|
|
|
|
|
key => 1
|
329
|
|
|
|
|
|
|
};
|
330
|
0
|
|
|
|
|
|
return $key;
|
331
|
|
|
|
|
|
|
}
|
332
|
|
|
|
|
|
|
sub get_table_key {
|
333
|
0
|
|
|
0
|
1
|
|
my ($self, $table) = @_;
|
334
|
0
|
|
|
|
|
|
foreach (@{$self->{table_data}->{$table}->{fields}}) {
|
|
0
|
|
|
|
|
|
|
335
|
0
|
0
|
|
|
|
|
return $_ if $self->{table_data}->{$table}->{fielddata}->{$_}->{key};
|
336
|
|
|
|
|
|
|
}
|
337
|
0
|
|
|
|
|
|
$self->add_default_key($table);
|
338
|
|
|
|
|
|
|
}
|
339
|
|
|
|
|
|
|
sub get_table_field {
|
340
|
0
|
|
|
0
|
1
|
|
my ($self, $table, $field) = @_;
|
341
|
0
|
|
|
|
|
|
$self->{table_data}->{$table}->{fielddata}->{$field};
|
342
|
|
|
|
|
|
|
}
|
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub add_field {
|
345
|
0
|
|
|
0
|
1
|
|
my ($self, $table, $field, $def) = @_;
|
346
|
0
|
|
|
|
|
|
push @{$self->{table_data}->{$table}->{fields}}, $field;
|
|
0
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
$self->{table_data}->{$table}->{fielddata}->{$field} = $def;
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 AUTHOR
|
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Michael Roberts, C<< >>
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=head1 BUGS
|
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through
|
358
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll
|
359
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes.
|
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
Copyright 2010 Michael Roberts.
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
366
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published
|
367
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License.
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information.
|
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=cut
|
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
1; # End of Decl::Semantics::Table
|