File Coverage

blib/lib/SQL/Translator/Parser/DB2.pm
Criterion Covered Total %
statement 24 59 40.6
branch 5 32 15.6
condition 0 10 0.0
subroutine 6 6 100.0
pod 0 1 0.0
total 35 108 32.4


line stmt bran cond sub pod time code
1             package SQL::Translator::Parser::DB2;
2              
3             =head1 NAME
4              
5             SQL::Translator::Parser::DB2 - parser for DB2
6              
7             =head1 SYNOPSIS
8              
9             use SQL::Translator;
10             use SQL::Translator::Parser::DB2;
11              
12             my $translator = SQL::Translator->new;
13             $translator->parser("SQL::Translator::Parser::DB2");
14              
15             =head1 DESCRIPTION
16              
17             This is a grammar for parsing CREATE statements for DB2
18              
19             =cut
20              
21 1     1   1572 use warnings;
  1         2  
  1         39  
22 1     1   4 use strict;
  1         3  
  1         27  
23              
24 1     1   5 use base qw(Exporter);
  1         3  
  1         139  
25             our @EXPORT_OK = qw(parse);
26              
27             our $DEBUG;
28              
29 1     1   6 use Data::Dumper;
  1         2  
  1         58  
30 1     1   6 use SQL::Translator::Utils qw/ddl_parser_instance/;
  1         3  
  1         703  
31              
32             # !!!!!!
33             # THIS GRAMMAR IS INCOMPLETE!!!
34             # Khisanth is slowly working on a replacement
35             # !!!!!!
36             our $GRAMMAR = <<'END_OF_GRAMMAR';
37              
38             {
39             my ( %tables, $table_order, @table_comments, @views, @triggers );
40             }
41              
42             #
43             # The "eofile" rule makes the parser fail if any "statement" rule
44             # fails. Otherwise, the first successful match by a "statement"
45             # won't cause the failure needed to know that the parse, as a whole,
46             # failed. -ky
47             #
48             startrule : statement(s) eofile {
49             $return = {
50             tables => \%tables,
51             views => \@views,
52             triggers => \@triggers,
53             }
54             }
55              
56             eofile : /^\Z/
57              
58             statement :
59             comment
60             | create
61             |
62              
63             comment : /^\s*-{2}.*\n/
64             {
65             my $comment = $item[1];
66             $comment =~ s/^\s*(-{2})\s*//;
67             $comment =~ s/\s*$//;
68             $return = $comment;
69             }
70              
71              
72             create: CREATE TRIGGER trigger_name before type /ON/i table_name reference_b(?) /FOR EACH ROW/i 'MODE DB2SQL' triggered_action
73             {
74             my $table_name = $item{'table_name'}{'name'};
75             $return = {
76             table => $table_name,
77             schema => $item{'trigger_name'}{'schema'},
78             name => $item{'trigger_name'}{'name'},
79             when => 'before',
80             db_event => $item{'type'}->{'event'},
81             fields => $item{'type'}{'fields'},
82             condition => $item{'triggered_action'}{'condition'},
83             reference => $item{'reference_b'},
84             granularity => $item[9],
85             action => $item{'triggered_action'}{'statement'}
86             };
87              
88             push @triggers, $return;
89             }
90              
91             create: CREATE TRIGGER trigger_name after type /ON/i table_name reference_a(?) /FOR EACH ROW|FOR EACH STATEMENT/i 'MODE DB2SQL' triggered_action
92             {
93             my $table_name = $item{'table_name'}{'name'};
94             $return = {
95             table => $table_name,
96             schema => $item{'trigger_name'}{'schema'},
97             name => $item{'trigger_name'}{'name'},
98             when => 'after',
99             db_event => $item{'type'}{'event'},
100             fields => $item{'type'}{'fields'},
101             condition => $item{'triggered_action'}{'condition'},
102             reference => $item{'reference_a'},
103             granularity => $item[9],
104             action => $item{'triggered_action'}{'statement'}
105             };
106              
107             push @triggers, $return;
108             }
109              
110             create: CREATE /FEDERATED|/i VIEW view_name column_list(?) /AS/i with_expression(?) SQL_procedure_statement
111             {
112             $return = {
113             name => $item{view_name}{name},
114             sql => $item{SQL_procedure_statement},
115             with => $item{'with_expression(?)'},
116             fields => $item{'column_list(?)'}
117             };
118             push @views, $return;
119             }
120              
121             # create: CREATE /FEDERATED/i VIEW view_name col_list_or_of(?) /AS/i with_expression(?) fullselect options(?)
122              
123             # col_list_or_of: column_list | /OF/i ( root_view_definition | subview_definition )
124              
125             with_expression: /WITH/i common_table_expression(s /,/)
126             {
127             $return = $item{'common_table_expression'};
128             }
129              
130             SQL_procedure_statement: /[^;]*/ /(;|\z)/ { $return = $item[1] . $item[2] }
131              
132             column_list: '(' column_name(s /,/) ')'
133             {
134             $return = join(' ', '(', @{$item[2]}, ')');
135             }
136              
137             CREATE: /create/i
138              
139             TRIGGER: /trigger/i
140              
141             VIEW: /view/i
142              
143             INNER: /inner/i
144              
145             LEFT: /left/i
146              
147             RIGHT: /right/i
148              
149             FULL: /full/i
150              
151             OUTER: /outer/i
152              
153             WHERE: /where/i
154              
155             trigger_name: SCHEMA '.' NAME
156             { $return = { schema => $item[1], name => $item[3] } }
157             | NAME
158             { $return = { name => $item[1] } }
159              
160             table_name: SCHEMA '.' NAME
161             { $return = { schema => $item[1], name => $item[3] } }
162             | NAME
163             { $return = { name => $item[1] } }
164              
165             view_name: SCHEMA '.' NAME
166             { $return = { schema => $item[1], name => $item[3] } }
167             | NAME
168             { $return = { name => $item[1] } }
169              
170             column_name: NAME
171              
172             identifier: NAME
173              
174             correlation_name: NAME
175              
176             numeric_constant: /\d+/
177              
178             SCHEMA: /\w+/
179              
180             SCHEMA: /\w{1,128}/
181              
182             NAME: /\w+/
183              
184             NAME: /\w{1,18}/
185              
186             options: /WITH/i ( /CASCADED/i | /LOCAL/i ) /CHECK\s+OPTION/i
187              
188             # root_view_definition: /MODE\s+DB2SQL/i '(' oid_column ( /,/ with_options )(?) ')'
189              
190             # subview_definition: /MODE\s+DB2SQL/i under_clause ( '(' with_options ')' )(?) /EXTEND/i(?)
191              
192             # oid_column: /REF\s+IS/i oid_column_name /USER\s+GENERATED\s+UNCHECKED/i(?)
193              
194             # with_options: ( column_name /WITH\s+OPTIONS/i ( /SCOPE/i ( typed_table_name | typed_view_name ) | /READ\s+ONLY/i )(s /,/) )(s /,/)
195              
196             # under_clause: /UNDER/i superview_name /INHERIT\s+SELECT\s+PRIVILEGES/i
197              
198             common_table_expression: table_name column_list /AS/i get_bracketed
199             {
200             $return = { name => $item{table_name}{name},
201             query => $item[4]
202             };
203             }
204              
205             get_bracketed:
206             {
207             extract_bracketed($text, '(');
208             }
209              
210             common_table_expression: table_name column_list /AS/i '(' fullselect ')'
211              
212             # fullselect: ( subselect | '(' fullselect ')' | values_clause ) ( ( /UNION/i | /UNION/i /ALL/i | /EXCEPT/i | /EXCEPT/i /ALL/i | /INTERSECT/i | /INTERSECT/i /ALL/i ) ( subselect | '(' fullselect ')' | values_clause ) )(s)
213              
214             # values_clause: /VALUES/i values_row(s /,/)
215              
216             # values_row: ( expression | /NULL/i ) | '(' ( expression | /NULL/i )(s /,/) ')'
217              
218             # subselect: select_clause from_clause where_clause(?) group_by_clause(?) having_clause(?)
219              
220             # select_clause: SELECT ( /ALL/i | /DISTINCT )(?) ( '*' | ( expression ( /AS|/i new_column_name )(?) | exposed_name '.*' )(s /,/) )
221              
222             # from_clause: /FROM/i table_name(s /,/)
223              
224             # from_clause: /FROM/i table_reference(s /,/)
225              
226             # table_reference:
227             # (
228             # ( nickname
229             # | table_name
230             # | view_name
231             # )
232             # | ( /ONLY/i
233             # | /OUTER/i
234             # ) '('
235             # ( table_name
236             # | view_name
237             # ) ')'
238             # ) correlation_clause(?)
239             # | TABLE '(' function_name '(' expression(s? /,/) ')' ')' correlation_clause
240             # | TABLE(?) '(' fullselect ')' correlation_clause
241             # | joined_table
242              
243              
244             # correlation_clause: /AS/i(?) correlation_name column_list(?)
245              
246             # joined_table:
247             # table_reference ( INNER
248             # | outer
249             # )(?) JOIN table_reference ON join_condition
250             # | '(' joined_table ')'
251              
252             # outer: ( LEFT | RIGHT | FULL ) OUTER(?)
253              
254             where_clause: WHERE search_condition
255              
256             # group_by_clause: /GROUP\s+BY/i ( grouping_expression
257             # | grouping_sets
258             # | super_groups
259             # )(s /,/)
260              
261             # grouping_expression: expression
262              
263             # orderby_clause: /ORDER\s+BY/i ( sort_key ( /ASC/i | /DESC/i)(?) )(s /,/)
264              
265             # sort_key: simple_column_name | simple_integer | sort_key_expression
266              
267             # # Name of one of the selected columns!
268             # simple_column_name: NAME
269              
270             # simple_integer: /\d+/
271             # { $item[1] <= $numberofcolumns && $item[1] > 1 }
272              
273             # sort_key_expression: expression
274             # { expression from select columns list, grouping_expression, column function.. }
275              
276             # grouping_sets: /GROUPING\s+SETS/i '(' (
277             # ( grouping_expression
278             # | super_groups
279             # )
280             # | '(' ( grouping_expression
281             # | super_groups
282             # )(s /,/) ')'
283             # )(s /,/) ')'
284              
285             # super_groups: /ROLLUP/i '(' grouping_expression_list ')'
286             # | /CUBE/i '(' grouping_expression_list ')'
287             # | grand_total
288              
289             # grouping_expression_list: ( grouping_expression
290             # | '(' grouping_expression(s /,/) ')'
291             # )(s /,/)
292              
293             # grand_total: '(' ')'
294              
295             # having_clause: /HAVING/i search_condition
296              
297             when_clause: /WHEN/i '(' search_condition ')' {$return = $item[3]}
298              
299             triggered_action: when_clause(?) SQL_procedure_statement
300             { $return = { 'condition' => $item[1][0],
301             'statement' => $item{'SQL_procedure_statement'} };
302             }
303              
304             before: /NO CASCADE BEFORE/i
305              
306             after: /AFTER/i
307              
308             type: /UPDATE/i /OF/i column_name(s /,/)
309             { $return = { event => 'update_on',
310             fields => $item[3] }
311             }
312              
313             type: ( /INSERT/i | /DELETE/i | /UPDATE/i )
314             { $return = { event => $item[1] } }
315              
316             reference_b: /REFERENCING/i old_new_corr(0..2)
317             { $return = join(' ', $item[1], join(' ', @{$item[2]}) ) }
318              
319             reference_a: /REFERENCING/i old_new_corr(0..2) old_new_table(0..2)
320             { $return = join(' ', $item[1], join(' ', @{$item[2]}), join(' ', @{$item[3]}) ) }
321              
322             old_new_corr: /OLD/i /(AS)?/i correlation_name
323             { $return = join(' ', @item[1..3] ) }
324             | /NEW/i /(AS)?/i correlation_name
325             { $return = join(' ', @item[1..3] ) }
326              
327             old_new_table: /OLD_TABLE/i /(AS)?/i identifier
328             { $return = join(' ', @item[1..3] ) }
329             | /NEW_TABLE/i /(AS)?/i identifier
330             { $return = join(' ', @item[1..3] ) }
331              
332             # Just parsing simple search conditions for now.
333             search_condition: /[^)]+/
334              
335             expression: (
336             ( '+'
337             | '-'
338             )(?)
339             ( function
340             | '(' expression ')'
341             | constant
342             | column_name
343             | host_variable
344             | special_register
345             | '(' scalar_fullselect ')'
346             | labeled_duration
347             | case_expression
348             | cast_specification
349             # | dereference_operation
350             | OLAP_function
351             | method_invocation
352             | subtype_treatment
353             | sequence_reference
354             )
355             )(s /operator/)
356              
357             operator: ( /CONCAT/i | '||' ) | '/' | '*' | '+' | '-'
358              
359             function: ( /SYSIBM\.|/i sysibm_function
360             | /SYSFUN\.|/i sysfun_function
361             | userdefined_function
362             ) '(' func_args(s /,/) ')'
363              
364             constant: int_const | float_const | dec_const | char_const | hex_const | grastr_const
365              
366             func_args: expression
367              
368             sysibm_function: ( /ABS/i | /ABSVAL/i )
369             | /AVG/i
370             | /BIGINT/i
371             | /BLOB/i
372             | /CHAR/i
373             | /CLOB/i
374             | /COALESCE/i
375             | ( /CONCAT/ | '||' )
376             | ( /CORRELATION/i | /CORR/ )
377             | /COUNT/i
378             | /COUNT_BIG/i
379             | (/COVARIANCE/i | /COVAR/i )
380             | /DATE/i
381             | /DAY/i
382             | /DAYS/i
383             | /DBCLOB/i
384             | ( /DECIMAL/i | /DEC/i )
385             | /DECRYPT_BIN/i
386             | /DECRYPT_CHAR/i
387             | /DEREF/i
388             | /DIGITS/i
389             | /DLCOMMENT/i
390             | /DLLINKTYPE/i
391             | /DLURLCOMPLETE/i
392             | /DLURLPATH/i
393             | /DLURLPATHONLY/i
394             | /DLURLSCHEME/i
395             | /DLURLSERVER/i
396             | /DLVALUE/i
397             | ( /DOUBLE/i | /DOUBLE_PRECISION/i )
398             | /ENCRYPT/i
399             | /EVENT_MON_STATE/i
400             | /FLOAT/i
401             | /GETHINT/i
402             | /GENERATE_UNIQUE/i
403             | /GRAPHIC/i
404             | /GROUPING/i
405             | /HEX/i
406             | /HOUR/i
407             | /IDENTITY_VAL_LOCAL/i
408             | ( /INTEGER/i | /INT/ )
409             | ( /LCASE/i | /LOWER/ )
410             | /LENGTH/i
411             | /LONG_VARCHAR/i
412             | /LONG_VARGRAPHIC/i
413             | /LTRIM/i
414             | /MAX/i
415             | /MICROSECOND/i
416             | /MIN/i
417             | /MINUTE/i
418             | /MONTH/i
419             | /MULTIPLY_ACT/i
420             | /NODENUMBER/i
421             | /NULLIF/i
422             | /PARTITON/i
423             | /POSSTR/i
424             | /RAISE_ERROR/i
425             | /REAL/i
426             | /REC2XML/i
427             | /REGR_AVGX/i
428             | /REGR_AVGY/i
429             | /REGR_COUNT/i
430             | ( /REGR_INTERCEPT/i | /REGR_ICPT/i )
431             | /REGR_R2/i
432             | /REGR_SLOPE/i
433             | /REGR_SXX/i
434             | /REGR_SXY/i
435             | /REGR_SYY/i
436             | /RTRIM/i
437             | /SECOND/i
438             | /SMALLINT/i
439             | /STDDEV/i
440             | /SUBSTR/i
441             | /SUM/i
442             | /TABLE_NAME/i
443             | /TABLE_SCHEMA/i
444             | /TIME/i
445             | /TIMESTAMP/i
446             | /TRANSLATE/i
447             | /TYPE_ID/i
448             | /TYPE_NAME/i
449             | /TYPE_SCHEMA/i
450             | ( /UCASE/i | /UPPER/i )
451             | /VALUE/i
452             | /VARCHAR/i
453             | /VARGRAPHIC/i
454             | ( /VARIANCE/i | /VAR/i )
455             | /YEAR/i
456              
457             sysfun: ( /ABS/i | /ABSVAL/i )
458             | /ACOS/i
459             | /ASCII/i
460             | /ASIN/i
461             | /ATAN/i
462             | /ATAN2/i
463             | ( /CEIL/i | /CEILING/i )
464             | /CHAR/i
465             | /CHR/i
466             | /COS/i
467             | /COT/i
468             | /DAYNAME/i
469             | /DAYOFWEEK/i
470             | /DAYOFWEEK_ISO/i
471             | /DAYOFYEAR/i
472             | /DEGREES/i
473             | /DIFFERENCE/i
474             | /DOUBLE/i
475             | /EXP/i
476             | /FLOOR/i
477             | /GET_ROUTINE_SAR/i
478             | /INSERT/i
479             | /JULIAN_DAY/i
480             | /LCASE/i
481             | /LEFT/i
482             | /LN/i
483             | /LOCATE/i
484             | /LOG/i
485             | /LOG10/i
486             | /LTRIM/i
487             | /MIDNIGHT_SECONDS/i
488             | /MOD/i
489             | /MONTHNAME/i
490             | /POWER/i
491             | /PUT_ROUTINE_SAR/i
492             | /QUARTER/i
493             | /RADIANS/i
494             | /RAND/i
495             | /REPEAT/i
496             | /REPLACE/i
497             | /RIGHT/i
498             | /ROUND/i
499             | /RTRIM/I
500             | /SIGN/i
501             | /SIN/i
502             | /SOUNDEX/i
503             | /SPACE/i
504             | /SQLCACHE_SNAPSHOT/i
505             | /SQRT/i
506             | /TAN/i
507             | /TIMESTAMP_ISO/i
508             | /TIMESTAMPDIFF/i
509             | ( /TRUNCATE/i | /TRUNC/i )
510             | /UCASE/i
511             | /WEEK/i
512             | /WEEK_ISO/i
513              
514             scalar_fullselect: '(' fullselect ')'
515              
516             labeled_duration: ld_type ld_duration
517              
518             ld_type: function
519             | '(' expression ')'
520             | constant
521             | column_name
522             | host_variable
523              
524             ld_duration: /YEARS?/i
525             | /MONTHS?/i
526             | /DAYS?/i
527             | /HOURS?/i
528             | /MINUTES?/i
529             | /SECONDS?/i
530             | /MICROSECONDS?/i
531              
532             case_expression: /CASE/i ( searched_when_clause
533             | simple_when_clause
534             )
535             ( /ELSE\s+NULL/i
536             | /ELSE/i result_expression
537             )(?) /END/i
538              
539             searched_when_clause: ( /WHEN/i search_condition /THEN/i
540             ( result_expression
541             | /NULL/i
542             )
543             )(s)
544              
545             simple_when_clause: expression ( /WHEN/i search_condition /THEN/i
546             ( result_expression
547             | /NULL/i
548             )
549             )(s)
550              
551             result_expression: expression
552              
553             cast_specification: /CAST/i '(' ( expression
554             | /NULL/i
555             | parameter_marker
556             ) /AS/i data_type
557             ( /SCOPE/ ( typed_table_name
558             | typed_view_name
559             )
560             )(?) ')'
561              
562             dereference_operation: scoped_reference_expression '->' name1
563             ( '(' expression(s) ')' )(?)
564             # ( '(' expression(s /,/) ')' )(?)
565              
566              
567              
568             scoped_reference_expression: expression
569             { # scoped, reference
570             }
571              
572             name1: NAME
573              
574             OLAP_function: ranking_function
575             | numbering_function
576             | aggregation_function
577              
578             ranking_function: ( /RANK/ '()'
579             | /DENSE_RANK|DENSERANK/i '()'
580             ) /OVER/i '(' window_partition_clause(?) window_order_clause ')'
581              
582             numbering_function: /ROW_NUMBER|ROWNUMBER/i '()' /OVER/i '(' window_partition_clause(?)
583             ( window_order_clause window_aggregation_group_clause(?)
584             )(?)
585             ( /RANGE\s+BETWEEN\s+UNBOUNDED\s+PRECEDING\s+AND\s+UNBBOUNDED\s+FOLLOWING/i
586             | window_aggregation_group_clause
587             )(?) ')'
588              
589             window_partition_clause: /PARTITION\s+BY/i partitioning_expression(s /,/)
590              
591             window_order_clause: /ORDER\s+BY/i
592             ( sort_key_expression
593             ( asc_option
594             | desc_option
595             )(?)
596             )(s /,/)
597              
598             asc_option: /ASC/i ( /NULLS\s+FIRST/i | /NULLS\s+LAST/i )(?)
599              
600             desc_option: /DESC/i ( /NULLS\s+FIRST/i | /NULLS\s+LAST/i )(?)
601              
602             window_aggregation_group_clause: ( /ROWS/i
603             | /RANGE/i
604             )
605             ( group_start
606             | group_between
607             | group_end
608             )
609              
610             group_start: /UNBOUNDED\s+PRECEDING/i
611             | unsigned_constant /PRECEDING/i
612             | /CURRENT\s+ROW/i
613              
614             group_between: /BETWEEN/i group_bound1 /AND/i group_bound2
615              
616             group_bound1: /UNBOUNDED\s+PRECEDING/i
617             | unsigned_constant /PRECEDING/i
618             | unsigned_constant /FOLLOWING/i
619             | /CURRENT\s+ROW/i
620              
621             group_bound2: /UNBOUNDED\s+PRECEDING/i
622             | unsigned_constant /PRECEDING/i
623             | unsigned_constant /FOLLOWING/i
624             | /CURRENT\s+ROW/i
625              
626             group_end: /UNBOUNDED\s+PRECEDING/i
627             | unsigned_constant /FOLLOWING/i
628              
629             method_invocation: subject_expression '..' method_name
630             ( '(' expression(s) ')'
631             # ( '(' expression(s /,/) ')'
632             )(?)
633              
634             subject_expression: expression
635             { # with static result type that is a used-defined struct type
636             }
637              
638             method_name: NAME
639             { # must be a method of subject_expression
640             }
641              
642             subtype_treatment: /TREAT/i '(' expression /AS/i data_type ')'
643              
644             sequence_reference: nextval_expression
645             | prevval_expression
646              
647             nextval_expression: /NEXTVAL\s+FOR/i sequence_name
648              
649             prevval_expression: /PREVVAL\s+FOR/i sequence_name
650              
651             sequence_name: NAME
652              
653              
654             search_condition: /NOT|/i ( predicate ( /SELECTIVITY/i numeric_constant )(?) | '(' search_condition ')' ) cond(s?)
655              
656             cond: ( /AND/i | /OR/i ) /NOT|/i ( predicate ( /SELECTIVITY/i numeric_constant )(?) | '(' search_condition ')' )
657              
658             predicate: basic_p | quantified_p | between_p | exists_p | in_p | like_p | null_p | type_p
659              
660             basic_p: expression /(=|<>|<|>|<=|=>|\^=|\^<|\^>|\!=)/ expression
661              
662             quantified_p: expression1 /(=|<>|<|>|<=|=>|\^=|\^<|\^>|\!=)/ /SOME|ANY|ALL/i '(' fullselect ')'
663              
664             END_OF_GRAMMAR
665              
666             sub parse {
667 1     1 0 5 my ( $translator, $data ) = @_;
668              
669             # Enable warnings within the Parse::RecDescent module.
670 1 50       5 local $::RD_ERRORS = 1 unless defined $::RD_ERRORS; # Make sure the parser dies when it encounters an error
671 1 50       4 local $::RD_WARN = 1 unless defined $::RD_WARN; # Enable warnings. This will warn on unused rules &c.
672 1 50       4 local $::RD_HINT = 1 unless defined $::RD_HINT; # Give out hints to help fix problems.
673              
674 1 50       17 local $::RD_TRACE = $translator->trace ? 1 : undef;
675 1         12 local $DEBUG = $translator->debug;
676              
677 1         11 my $parser = ddl_parser_instance('DB2');
678              
679 1         74 my $result = $parser->startrule($data);
680 1 50       68 return $translator->error( "Parse failed." ) unless defined $result;
681 0 0         warn Dumper( $result ) if $DEBUG;
682              
683 0           my $schema = $translator->schema;
684             my @tables =
685 0           map { $_->[1] }
686 0           sort { $a->[0] <=> $b->[0] }
687 0           map { [ $result->{'tables'}{ $_ }->{'order'}, $_ ] }
688 0           keys %{ $result->{'tables'} };
  0            
689              
690 0           for my $table_name ( @tables ) {
691 0           my $tdata = $result->{'tables'}{ $table_name };
692             my $table = $schema->add_table(
693 0 0         name => $tdata->{'name'},
694             ) or die $schema->error;
695              
696 0           $table->comments( $tdata->{'comments'} );
697              
698 0           for my $fdata ( @{ $tdata->{'fields'} } ) {
  0            
699             my $field = $table->add_field(
700             name => $fdata->{'name'},
701             data_type => $fdata->{'data_type'},
702             size => $fdata->{'size'},
703             default_value => $fdata->{'default'},
704             is_auto_increment => $fdata->{'is_auto_inc'},
705             is_nullable => $fdata->{'is_nullable'},
706 0 0         comments => $fdata->{'comments'},
707             ) or die $table->error;
708              
709 0 0         $table->primary_key( $field->name ) if $fdata->{'is_primary_key'};
710              
711 0           for my $cdata ( @{ $fdata->{'constraints'} } ) {
  0            
712 0 0         next unless $cdata->{'type'} eq 'foreign_key';
713 0   0       $cdata->{'fields'} ||= [ $field->name ];
714 0           push @{ $tdata->{'constraints'} }, $cdata;
  0            
715             }
716             }
717              
718 0 0         for my $idata ( @{ $tdata->{'indices'} || [] } ) {
  0            
719             my $index = $table->add_index(
720             name => $idata->{'name'},
721             type => uc $idata->{'type'},
722 0 0         fields => $idata->{'fields'},
723             ) or die $table->error;
724             }
725              
726 0 0         for my $cdata ( @{ $tdata->{'constraints'} || [] } ) {
  0            
727             my $constraint = $table->add_constraint(
728             name => $cdata->{'name'},
729             type => $cdata->{'type'},
730             fields => $cdata->{'fields'},
731             reference_table => $cdata->{'reference_table'},
732             reference_fields => $cdata->{'reference_fields'},
733             match_type => $cdata->{'match_type'} || '',
734             on_delete => $cdata->{'on_delete'} || $cdata->{'on_delete_do'},
735 0 0 0       on_update => $cdata->{'on_update'} || $cdata->{'on_update_do'},
      0        
      0        
736             ) or die $table->error;
737             }
738             }
739              
740 0 0         for my $def ( @{ $result->{'views'} || [] } ) {
  0            
741             my $view = $schema->add_view(
742             name => $def->{'name'},
743 0           sql => $def->{'sql'},
744             );
745             }
746              
747 0 0         for my $def ( @{ $result->{'triggers'} || [] } ) {
  0            
748             my $trig = $schema->add_trigger(
749             name => $def->{'name'},
750             perform_action_when => $def->{'when'},
751             database_event => $def->{'db_event'},
752             action => $def->{'action'},
753             fields => $def->{'fields'},
754 0           on_table => $def->{'table'}
755             );
756             $trig->extra( reference => $def->{'reference'},
757             condition => $def->{'condition'},
758 0           granularity => $def->{'granularity'} );
759             }
760              
761 0           return 1;
762             }
763              
764             1;
765              
766             =pod
767              
768             =head1 AUTHOR
769              
770             Jess Robinson
771              
772             =head1 SEE ALSO
773              
774             perl(1), Parse::RecDescent, SQL::Translator::Schema.
775              
776             =cut