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