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