Commit | Line | Data |
4f4fd192 |
1 | use MooseX::Declare; |
2 | role SQL::Translator::Parser::DDL::PostgreSQL { |
faff8d0e |
3 | use MooseX::Types::Moose qw(Str); |
4 | use MooseX::MultiMethods; |
5 | use SQL::Translator::Constants qw(:sqlt_types :sqlt_constants); |
6 | use SQL::Translator::Types qw(Schema); |
7 | use aliased 'SQL::Translator::Object::Column'; |
8 | use aliased 'SQL::Translator::Object::Constraint'; |
9 | use aliased 'SQL::Translator::Object::ForeignKey'; |
10 | use aliased 'SQL::Translator::Object::Index'; |
11 | use aliased 'SQL::Translator::Object::PrimaryKey'; |
12 | use aliased 'SQL::Translator::Object::Table'; |
13 | use aliased 'SQL::Translator::Object::View'; |
14 | |
15 | multi method parse(Schema $data) { $data } |
16 | |
17 | multi method parse(Str $data) { |
18 | my $translator = $self->translator; |
19 | my $parser = Parse::RecDescent->new($self->grammar); |
20 | |
faff8d0e |
21 | unless (defined $parser) { |
22 | return $translator->error("Error instantiating Parse::RecDescent ". |
23 | "instance: Bad grammer"); |
24 | } |
25 | |
26 | my $result = $parser->startrule($data); |
27 | die "Parse failed.\n" unless defined $result; |
d5f4c45f |
28 | |
faff8d0e |
29 | my $schema = $translator->schema; |
30 | my @tables = |
d5f4c45f |
31 | sort { ( $result->{tables}{ $a }{'order'} || 0 ) <=> ( $result->{tables}{ $b }{'order'} || 0 ) } |
faff8d0e |
32 | keys %{ $result->{tables} }; |
33 | |
34 | for my $table_name ( @tables ) { |
35 | my $tdata = $result->{tables}{ $table_name }; |
0621a167 |
36 | my $table = Table->new({ name => $tdata->{table_name}, schema => $schema }); |
faff8d0e |
37 | $schema->add_table($table); |
38 | |
39 | $table->extra(temporary => 1) if $tdata->{'temporary'}; |
40 | $table->comments( $tdata->{'comments'} ); |
41 | |
0621a167 |
42 | my @fields = sort { $tdata->{'fields'}{ $a }{'order'} <=> $tdata->{'fields'}{ $b }{'order'} } keys %{ $tdata->{'fields'} }; |
faff8d0e |
43 | |
44 | for my $fname ( @fields ) { |
45 | my $fdata = $tdata->{'fields'}{ $fname }; |
46 | next if $fdata->{'drop'}; |
47 | my $field = Column->new({ |
48 | name => $fdata->{'name'}, |
49 | data_type => $fdata->{'data_type'}, |
50 | sql_data_type => $self->data_type_mapping->{$fdata->{data_type}} || -999999, |
51 | size => $fdata->{'size'}, |
52 | default_value => $fdata->{'default'}, |
53 | is_auto_increment => $fdata->{'is_auto_increment'}, |
54 | is_nullable => $fdata->{'is_nullable'}, |
55 | comments => $fdata->{'comments'}, |
56 | table => $table, |
57 | }); |
d5f4c45f |
58 | |
faff8d0e |
59 | $table->add_column($field); |
d5f4c45f |
60 | $table->primary_key($field->name) if $fdata->{is_primary_key}; |
faff8d0e |
61 | |
62 | for my $cdata ( @{ $fdata->{constraints} } ) { |
63 | next unless $cdata->{type} eq 'foreign_key'; |
64 | $cdata->{fields} ||= [ $field->name ]; |
65 | push @{ $tdata->{constraints} }, $cdata; |
66 | } |
67 | } |
68 | |
69 | for my $idata ( @{ $tdata->{indices} || [] } ) { |
70 | my $index = Index->new({ |
71 | name => $idata->{name}, |
72 | type => uc $idata->{type}, |
f350b918 |
73 | table => $table, |
faff8d0e |
74 | }); |
f350b918 |
75 | $index->add_column($table->get_column($_)) for @{$idata->{fields}}; |
76 | $table->add_index($index); |
faff8d0e |
77 | } |
78 | |
79 | for my $cdata ( @{ $tdata->{'constraints'} || [] } ) { |
d5f4c45f |
80 | my $constraint; |
81 | if (uc $cdata->{type} eq 'PRIMARY_KEY') { |
82 | $constraint = PrimaryKey->new({ name => $cdata->{name} || '', table => $table }); |
83 | $table->get_column($_)->is_primary_key(1) for @{$cdata->{fields}}; |
84 | } elsif (uc $cdata->{type} eq 'FOREIGN_KEY') { |
85 | $constraint = ForeignKey->new({ name => $cdata->{name} || '', |
86 | table => $table, |
87 | reference_table => $cdata->{reference_table}, |
88 | reference_columns => $cdata->{reference_fields}, |
89 | on_delete => $cdata->{on_delete} || $cdata->{on_delete_do}, |
90 | on_update => $cdata->{on_update} || $cdata->{on_update_do} }); |
91 | $table->get_column($_)->is_foreign_key(1) for @{$cdata->{fields}}; |
92 | $table->get_column($_)->foreign_key_reference($constraint) for @{$cdata->{fields}}; |
93 | } else { |
94 | $constraint = Constraint->new({ name => $cdata->{name} || '', type => uc $cdata->{type}, table => $table }); |
95 | } |
96 | $constraint->add_column($table->get_column($_)) for @{$cdata->{fields}}; |
faff8d0e |
97 | $table->add_constraint($constraint); |
98 | } |
99 | } |
100 | |
101 | for my $vinfo (@{$result->{views}}) { |
102 | my $sql = $vinfo->{sql}; |
103 | $sql =~ s/\A\s+|\s+\z//g; |
104 | my $view = View->new({ |
105 | name => $vinfo->{view_name}, |
106 | sql => $sql, |
faff8d0e |
107 | }); |
108 | |
109 | $schema->add_view($view); |
110 | |
111 | $view->extra ( temporary => 1 ) if $vinfo->{is_temporary}; |
112 | } |
113 | |
77bdd3a8 |
114 | return 1; |
faff8d0e |
115 | } |
4f4fd192 |
116 | } |