SQL-Translator

 view release on metacpan or  search on metacpan

lib/SQL/Translator/Parser/PostgreSQL.pm  view on Meta::CPAN

    | DOLLARSTRING
    | /null/i
    { 'NULL' }

END_OF_GRAMMAR

sub parse {
  my ($translator, $data) = @_;

  # Enable warnings within the Parse::RecDescent module.
  local $::RD_ERRORS = 1
      unless defined $::RD_ERRORS;    # Make sure the parser dies when it encounters an error
  local $::RD_WARN = 1
      unless defined $::RD_WARN;      # Enable warnings. This will warn on unused rules &c.
  local $::RD_HINT = 1
      unless defined $::RD_HINT;      # Give out hints to help fix problems.

  local $::RD_TRACE = $translator->trace ? 1 : undef;
  local $DEBUG      = $translator->debug;

  my $parser = ddl_parser_instance('PostgreSQL');

  my $result = $parser->startrule($data);
  die "Parse failed.\n" unless defined $result;
  warn Dumper($result) if $DEBUG;

  my $schema = $translator->schema;
  my @tables = sort { ($result->{tables}{$a}{'order'} || 0) <=> ($result->{tables}{$b}{'order'} || 0) }
      keys %{ $result->{tables} };

  for my $table_name (@tables) {
    my $tdata = $result->{tables}{$table_name};
    my $table = $schema->add_table(

      #schema => $tdata->{'schema_name'},
      name => $tdata->{'table_name'},
    ) or die "Couldn't create table '$table_name': " . $schema->error;

    $table->extra(temporary => 1) if $tdata->{'temporary'};

    $table->comments($tdata->{'comments'});

    my @fields
        = sort { $tdata->{'fields'}{$a}{'order'} <=> $tdata->{'fields'}{$b}{'order'} } keys %{ $tdata->{'fields'} };

    for my $fname (@fields) {
      my $fdata = $tdata->{'fields'}{$fname};
      next if $fdata->{'drop'};
      my $field = $table->add_field(
        name              => $fdata->{'name'},
        data_type         => $fdata->{'data_type'},
        size              => $fdata->{'size'},
        default_value     => $fdata->{'default'},
        is_auto_increment => $fdata->{'is_auto_increment'},
        is_nullable       => $fdata->{'is_nullable'},
        comments          => $fdata->{'comments'},
      ) or die $table->error;

      $table->primary_key($field->name) if $fdata->{'is_primary_key'};

      for my $cdata (@{ $fdata->{'constraints'} }) {
        next unless $cdata->{'type'} eq 'foreign_key';
        $cdata->{'fields'} ||= [ $field->name ];
        push @{ $tdata->{'constraints'} }, $cdata;
      }
    }

    for my $idata (@{ $tdata->{'indices'} || [] }) {
      my @options = ();
      push @options, { using   => $idata->{'method'} } if $idata->{method};
      push @options, { where   => $idata->{'where'} }  if $idata->{where};
      push @options, { include => $idata->{'include'} }
          if $idata->{include};
      my $index = $table->add_index(
        name    => $idata->{'name'},
        type    => uc $idata->{'type'},
        fields  => $idata->{'fields'},
        options => \@options
      ) or die $table->error . ' ' . $table->name;
    }

    for my $cdata (@{ $tdata->{'constraints'} || [] }) {
      my $options = [

        # load this up with the extras
        map +{ %$cdata{$_} }, grep $cdata->{$_},
        qw/include using where/
      ];
      my $constraint = $table->add_constraint(
        name             => $cdata->{'name'},
        type             => $cdata->{'type'},
        fields           => $cdata->{'fields'},
        reference_table  => $cdata->{'reference_table'},
        reference_fields => $cdata->{'reference_fields'},
        match_type       => $cdata->{'match_type'} || '',
        on_delete        => $cdata->{'on_delete'}  || $cdata->{'on_delete_do'},
        on_update        => $cdata->{'on_update'}  || $cdata->{'on_update_do'},
        expression       => $cdata->{'expression'},
        options          => $options
          )
          or die "Can't add constraint of type '"
          . $cdata->{'type'}
          . "' to table '"
          . $table->name . "': "
          . $table->error;
    }
  }

  for my $vinfo (@{ $result->{views} }) {
    my $sql = $vinfo->{sql};
    $sql =~ s/\A\s+|\s+\z//g;
    my $view = $schema->add_view(
      name   => $vinfo->{view_name},
      sql    => $sql,
      fields => $vinfo->{fields},
    );

    $view->extra(temporary => 1) if $vinfo->{is_temporary};
  }

  for my $trigger (@{ $result->{triggers} }) {
    $schema->add_trigger(%$trigger);
  }

  return 1;
}

1;

# -------------------------------------------------------------------
# Rescue the drowning and tie your shoestrings.
# Henry David Thoreau
# -------------------------------------------------------------------

=pod

=head1 AUTHORS

Ken Y. Clark E<lt>kclark@cpan.orgE<gt>,
Allen Day E<lt>allenday@ucla.eduE<gt>.

=head1 SEE ALSO

perl(1), Parse::RecDescent.

=cut



( run in 0.705 second using v1.01-cache-2.11-cpan-5a3173703d6 )