]> git.donarmstrong.com Git - debbugs.git/commitdiff
Merge branch 'master' into database
authorDon Armstrong <don@donarmstrong.com>
Wed, 2 Oct 2013 01:06:53 +0000 (18:06 -0700)
committerDon Armstrong <don@donarmstrong.com>
Wed, 2 Oct 2013 01:06:53 +0000 (18:06 -0700)
37 files changed:
Debbugs/DB.pm [new file with mode: 0644]
Debbugs/DB/Load.pm [new file with mode: 0644]
Debbugs/DB/Result/.gitignore [new file with mode: 0644]
Debbugs/DB/Result/Arch.pm [new file with mode: 0644]
Debbugs/DB/Result/BinAssociation.pm [new file with mode: 0644]
Debbugs/DB/Result/BinPkg.pm [new file with mode: 0644]
Debbugs/DB/Result/BinVer.pm [new file with mode: 0644]
Debbugs/DB/Result/BinaryVersion.pm [new file with mode: 0644]
Debbugs/DB/Result/Bug.pm [new file with mode: 0644]
Debbugs/DB/Result/BugBinpackage.pm [new file with mode: 0644]
Debbugs/DB/Result/BugBlock.pm [new file with mode: 0644]
Debbugs/DB/Result/BugMerged.pm [new file with mode: 0644]
Debbugs/DB/Result/BugMessage.pm [new file with mode: 0644]
Debbugs/DB/Result/BugPackage.pm [new file with mode: 0644]
Debbugs/DB/Result/BugSrcpackage.pm [new file with mode: 0644]
Debbugs/DB/Result/BugTag.pm [new file with mode: 0644]
Debbugs/DB/Result/BugVer.pm [new file with mode: 0644]
Debbugs/DB/Result/Correspondent.pm [new file with mode: 0644]
Debbugs/DB/Result/CorrespondentFullName.pm [new file with mode: 0644]
Debbugs/DB/Result/Maintainer.pm [new file with mode: 0644]
Debbugs/DB/Result/Message.pm [new file with mode: 0644]
Debbugs/DB/Result/MessageCorrespondent.pm [new file with mode: 0644]
Debbugs/DB/Result/MessageRef.pm [new file with mode: 0644]
Debbugs/DB/Result/Severity.pm [new file with mode: 0644]
Debbugs/DB/Result/SrcAssociation.pm [new file with mode: 0644]
Debbugs/DB/Result/SrcPkg.pm [new file with mode: 0644]
Debbugs/DB/Result/SrcVer.pm [new file with mode: 0644]
Debbugs/DB/Result/Suite.pm [new file with mode: 0644]
Debbugs/DB/Result/Tag.pm [new file with mode: 0644]
Debbugs/Status.pm
bin/debbugs-loadsql [new file with mode: 0755]
bin/debbugs-loadsql-debinfo [new file with mode: 0755]
bin/debbugs-loadsql-versions [new file with mode: 0755]
debian/control
sql/dbicdump.conf [new file with mode: 0644]
sql/dbicdump_command.sh [new file with mode: 0755]
sql/debbugs_schema.sql [new file with mode: 0644]

diff --git a/Debbugs/DB.pm b/Debbugs/DB.pm
new file mode 100644 (file)
index 0000000..f44e185
--- /dev/null
@@ -0,0 +1,20 @@
+use utf8;
+package Debbugs::DB;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Schema';
+
+__PACKAGE__->load_namespaces;
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2012-07-17 10:25:29
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:wiMg1t5hFUhnyufL3yT5fQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Load.pm b/Debbugs/DB/Load.pm
new file mode 100644 (file)
index 0000000..e67dd9f
--- /dev/null
@@ -0,0 +1,290 @@
+# This module is part of debbugs, and is released
+# under the terms of the GPL version 2, or any later version. See the
+# file README and COPYING for more information.
+# Copyright 2013 by Don Armstrong <don@donarmstrong.com>.
+
+package Debbugs::DB::Load;
+
+=head1 NAME
+
+Debbugs::DB::Load -- Utility routines for loading the database
+
+=head1 SYNOPSIS
+
+
+=head1 DESCRIPTION
+
+
+=head1 BUGS
+
+None known.
+
+=cut
+
+use warnings;
+use strict;
+use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
+use base qw(Exporter);
+
+BEGIN{
+     ($VERSION) = q$Revision$ =~ /^Revision:\s+([^\s+])/;
+     $DEBUG = 0 unless defined $DEBUG;
+
+     @EXPORT = ();
+     %EXPORT_TAGS = (load_bug    => [qw(load_bug handle_load_bug_queue)],
+                   );
+     @EXPORT_OK = ();
+     Exporter::export_ok_tags(keys %EXPORT_TAGS);
+     $EXPORT_TAGS{all} = [@EXPORT_OK];
+}
+
+use Params::Validate qw(validate_with :types);
+
+use Debbugs::Status qw(read_bug split_status_fields);
+use Debbugs::DB;
+use DateTime;
+use Debbugs::Common qw(make_list getparsedaddrs);
+use Debbugs::Config qw(:config);
+
+=head2 Bug loading
+
+Routines to load bug; exported with :load_bug
+
+=over
+
+=item load_bug
+
+     load_bug(db => $schema,
+              data => split_status_fields($data),
+              tags => \%tags,
+              queue => \%queue);
+
+Loads a bug's metadata into the database. (Does not load any messages)
+
+=over
+
+=item db -- Debbugs::DB object
+
+=item data -- Bug data (from read_bug) which has been split with split_status_fields
+
+=item tags -- tag cache (hashref); optional
+
+=item queue -- queue of operations to perform after bug is loaded; optional.
+
+=back
+
+=cut
+
+sub load_bug {
+    my %param = validate_with(params => \@_,
+                              spec => {db => {type => OBJECT,
+                                             },
+                                       data => {type => HASHREF},
+                                       tags => {type => HASHREF,
+                                                default => sub {return {}},
+                                                optional => 1},
+                                       severities => {type => HASHREF,
+                                                      default => sub {return {}},
+                                                      optional => 1,
+                                                     },
+                                       queue => {type => HASHREF,
+                                                 optional => 1},
+                                      });
+    my $s = $param{db};
+    my $data = $param{data};
+    my $tags = $param{tags};
+    my $queue = $param{queue};
+    my $severities = $param{severities};
+    my $can_queue = 1;
+    if (not defined $queue) {
+        $can_queue = 0;
+        $queue = {};
+    }
+    my %tags;
+    my $s_data = split_status_fields($data);
+    for my $tag (make_list($s_data->{keywords})) {
+       next unless defined $tag and length $tag;
+       # this allows for invalid tags. But we'll use this to try to
+       # find those bugs and clean them up
+       if (not exists $tags->{$tag}) {
+           $tags->{$tag} = $s->resultset('Tag')->
+            find_or_create({tag => $tag});
+       }
+       $tags{$tag} = $tags->{$tag};
+    }
+    my $severity = length($data->{severity}) ? $data->{severity} : $config{default_severity};
+    if (exists $severities->{$severity}) {
+        $severity = $severities->{$severity};
+    } else {
+        $severity = $s->resultset('Severity')->
+            find_or_create({severity => $severity});
+    }
+    my $bug =
+        {id => $data->{bug_num},
+         creation => DateTime->from_epoch(epoch => $data->{date}),
+         log_modified => DateTime->from_epoch(epoch => $data->{log_modified}),
+         last_modified => DateTime->from_epoch(epoch => $data->{last_modified}),
+         archived => $data->{archived},
+         (defined $data->{unarchived} and length($data->{unarchived}))?(unarchived => DateTime->from_epoch(epoch => $data->{unarchived})):(),
+         forwarded => $data->{forwarded} // '',
+         summary => $data->{summary} // '',
+         outlook => $data->{outlook} // '',
+         subject => $data->{subject} // '',
+         done_full => $data->{done} // '',
+         severity => $severity,
+         owner_full => $data->{owner} // '',
+         submitter_full => $data->{originator} // '',
+        };
+    my %addr_map =
+        (done => 'done',
+         owner => 'owner',
+         submitter => 'originator',
+        );
+    for my $addr_type (keys %addr_map) {
+        my @addrs = getparsedaddrs($data->{$addr_map{$addr_type}} // '');
+        next unless @addrs;
+        $bug->{$addr_type} = $s->resultset('Correspondent')->find_or_create({addr => $addrs[0]->address()});
+        # insert the full name as well
+        my $full_name = $addrs[0]->phrase();
+        $full_name =~ s/^\"|\"$//g;
+        $full_name =~ s/^\s+|\s+$//g;
+        $bug->{$addr_type}->update_or_create_related('correspondent_full_names',{full_name=>$full_name}) if length $full_name;
+    }
+     my $b = $s->resultset('Bug')->update_or_create($bug) or
+         die "Unable to update or create bug $bug->{id}";
+     $s->txn_do(sub {
+                  for my $ff (qw(found fixed)) {
+                      my @elements = $s->resultset('BugVer')->search({bug => $data->{bug_num},
+                                                                      found  => $ff eq 'found'?1:0,
+                                                                     });
+                      my %elements_to_delete = map {($elements[$_]->ver_string(),$elements[$_])} 0..$#elements;
+                      my %elements_to_add;
+                       my @elements_to_keep;
+                      for my $version (@{$data->{"${ff}_versions"}}) {
+                          if (exists $elements_to_delete{$version}) {
+                              push @elements_to_keep,$version;
+                          } else {
+                              $elements_to_add{$version} = 1;
+                          }
+                      }
+                       for my $version (@elements_to_keep) {
+                           delete $elements_to_delete{$version};
+                       }
+                      for my $element (keys %elements_to_delete) {
+                           $elements_to_delete{$element}->delete();
+                      }
+                      for my $element (keys %elements_to_add) {
+                          # find source package and source version id
+                          my $ne = $s->resultset('BugVer')->new_result({bug => $data->{bug_num},
+                                                                        ver_string => $element,
+                                                                        found => $ff eq 'found'?1:0,
+                                                                       }
+                                                                      );
+                          if (my ($src_pkg,$src_ver) = $element =~ m{^([^\/]+)/(.+)$}) {
+                              my $src_pkg_e = $s->resultset('SrcPkg')->single({pkg => $src_pkg});
+                              if (defined $src_pkg_e) {
+                                  $ne->src_pkg_id($src_pkg_e->id());
+                                  my $src_ver_e = $s->resultset('SrcVer')->single({src_pkg_id => $src_pkg_e->id(),
+                                                                                   ver => $src_ver
+                                                                                  });
+                                  $ne->src_ver_id($src_ver_e->id()) if defined $src_ver_e;
+                              }
+                          }
+                          $ne->insert();
+                      }
+                  }
+              });
+    $s->txn_do(sub {
+                  my $t = $s->resultset('BugTag')->search({bug => $data->{bug_num}});
+                   $t->delete() if defined $t;
+                  $s->populate(BugTag => [[qw(bug tag)], map {[$data->{bug_num}, $_->id()]} values %tags]);
+              });
+    # because these bugs reference other bugs which might not exist
+    # yet, we can't handle them until we've loaded all bugs. queue
+    # them up.
+    $queue->{merged}{$data->{bug_num}} = [@{$data->{mergedwith}}];
+    $queue->{blocks}{$data->{bug_num}} = [@{$data->{blocks}}];
+
+    if (not $can_queue) {
+        handle_load_bug_queue(db => $s,queue => $queue);
+    }
+
+    # still need to handle merges, versions, etc.
+}
+
+=item handle_load_bug_queue
+
+     handle_load_bug_queue(db => $schema,queue => $queue);
+
+Handles a queue of operations created by load bug. [These operations
+are used to handle cases where a bug referenced by a loaded bug may
+not exist yet. In cases where the bugs should exist, the queue is
+cleared automatically by load_bug if queue is undefined.
+
+=cut
+
+sub handle_load_bug_queue{
+    my %param = validate_with(params => \@_,
+                              spec => {db => {type => OBJECT,
+                                             },
+                                       queue => {type => HASHREF,
+                                                },
+                                      });
+    my $s = $param{db};
+    my $queue = $param{queue};
+    my %queue_types =
+       (merged => {set => 'BugMerged',
+                   columns => [qw(bug_id merged)],
+                   bug_id => 'bug_id',
+                  },
+        blocks => {set => 'BugBlock',
+                   columns => [qw(bug_id blocks)],
+                   bug_id => 'bug_id',
+                  },
+       );
+    for my $queue_type (keys %queue_types) {
+       for my $bug (%{$queue->{$queue_type}}) {
+           my $qt = $queue_types{$queue_type};
+           $s->txn_do(sub {
+                          $s->resultset($qt->{set})->search({$qt->{bug_id},$bug})->delete();
+                          $s->populate($qt->{set},[[@{$qt->{columns}}],
+                                                    map {[$bug,$_]} @{$queue->{$queue_type}{$bug}}]) if
+                              @{$queue->{$queue_type}{$bug}//[]};
+                      }
+                     );
+       }
+    }
+}
+
+=back
+
+=head2 Debinfo
+
+Commands to handle src and package version loading from debinfo files
+
+=item load_debinfo
+
+     load_debinfo($schema,$binname, $binver, $binarch, $srcname, $srcver);
+
+
+
+=cut
+
+sub load_debinfo {
+    my ($schema,$binname, $binver, $binarch, $srcname, $srcver) = @_;
+    my $sp = $schema->resultset('SrcPkg')->find_or_create({pkg => $srcname});
+    my $sv = $schema->resultset('SrcVer')->find_or_create({src_pkg_id=>$sp->id(),
+                                                           ver => $srcver});
+    my $arch = $schema->resultset('Arch')->find_or_create({arch => $binarch});
+    my $bp = $schema->resultset('BinPkg')->find_or_create({pkg => $binname});
+    $schema->resultset('BinVer')->find_or_create({bin_pkg_id => $bp->id(),
+                                                  src_ver_id => $sv->id(),
+                                                  arch_id    => $arch->id(),
+                                                  ver        => $binver,
+                                                 });
+}
+
+1;
+
+
+__END__
diff --git a/Debbugs/DB/Result/.gitignore b/Debbugs/DB/Result/.gitignore
new file mode 100644 (file)
index 0000000..5a4e08f
--- /dev/null
@@ -0,0 +1,2 @@
+ColumnComment.pm
+TableComment.pm
diff --git a/Debbugs/DB/Result/Arch.pm b/Debbugs/DB/Result/Arch.pm
new file mode 100644 (file)
index 0000000..420d325
--- /dev/null
@@ -0,0 +1,132 @@
+use utf8;
+package Debbugs::DB::Result::Arch;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Arch - Architectures
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<arch>
+
+=cut
+
+__PACKAGE__->table("arch");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'arch_id_seq'
+
+Architecture id
+
+=head2 arch
+
+  data_type: 'text'
+  is_nullable: 0
+
+Architecture name
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "arch_id_seq",
+  },
+  "arch",
+  { data_type => "text", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<arch_arch_key>
+
+=over 4
+
+=item * L</arch>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("arch_arch_key", ["arch"]);
+
+=head1 RELATIONS
+
+=head2 bin_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BinVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bin_vers",
+  "Debbugs::DB::Result::BinVer",
+  { "foreign.arch_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_status_caches
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugStatusCache>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_status_caches",
+  "Debbugs::DB::Result::BugStatusCache",
+  { "foreign.arch" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 15:46:42
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jkMopbSgd3Carub/plyQQA
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BinAssociation.pm b/Debbugs/DB/Result/BinAssociation.pm
new file mode 100644 (file)
index 0000000..c074597
--- /dev/null
@@ -0,0 +1,161 @@
+use utf8;
+package Debbugs::DB::Result::BinAssociation;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BinAssociation - Binary <-> suite associations
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bin_associations>
+
+=cut
+
+__PACKAGE__->table("bin_associations");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bin_associations_id_seq'
+
+Binary <-> suite association id
+
+=head2 suite
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Suite id (matches suite)
+
+=head2 bin
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Binary version id (matches bin_ver)
+
+=head2 created
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time this binary package entered this suite
+
+=head2 modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time this entry was modified
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bin_associations_id_seq",
+  },
+  "suite",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "bin",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "created",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 bin
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::BinVer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bin",
+  "Debbugs::DB::Result::BinVer",
+  { id => "bin" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 suite
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Suite>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "suite",
+  "Debbugs::DB::Result::Suite",
+  { id => "suite" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CuIGLI5HKte90nfppS4Phw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BinPkg.pm b/Debbugs/DB/Result/BinPkg.pm
new file mode 100644 (file)
index 0000000..e951e03
--- /dev/null
@@ -0,0 +1,132 @@
+use utf8;
+package Debbugs::DB::Result::BinPkg;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BinPkg - Binary packages
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bin_pkg>
+
+=cut
+
+__PACKAGE__->table("bin_pkg");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bin_pkg_id_seq'
+
+Binary package id
+
+=head2 pkg
+
+  data_type: 'text'
+  is_nullable: 0
+
+Binary package name
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bin_pkg_id_seq",
+  },
+  "pkg",
+  { data_type => "text", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bin_pkg_pkg_key>
+
+=over 4
+
+=item * L</pkg>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bin_pkg_pkg_key", ["pkg"]);
+
+=head1 RELATIONS
+
+=head2 bin_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BinVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bin_vers",
+  "Debbugs::DB::Result::BinVer",
+  { "foreign.bin_pkg" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_binpackages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugBinpackage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_binpackages",
+  "Debbugs::DB::Result::BugBinpackage",
+  { "foreign.bin_pkg" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:E/y1hURij+mI11E63GPZZg
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BinVer.pm b/Debbugs/DB/Result/BinVer.pm
new file mode 100644 (file)
index 0000000..688b7fe
--- /dev/null
@@ -0,0 +1,210 @@
+use utf8;
+package Debbugs::DB::Result::BinVer;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BinVer - Binary versions
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bin_ver>
+
+=cut
+
+__PACKAGE__->table("bin_ver");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bin_ver_id_seq'
+
+Binary version id
+
+=head2 bin_pkg
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Binary package id (matches bin_pkg)
+
+=head2 src_ver_id
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Source version (matchines src_ver)
+
+=head2 arch_id
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Architecture id (matches arch)
+
+=head2 ver
+
+  data_type: 'debversion'
+  is_nullable: 0
+
+Binary version
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bin_ver_id_seq",
+  },
+  "bin_pkg",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "src_ver_id",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "arch_id",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "ver",
+  { data_type => "debversion", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bin_ver_bin_pkg_id_arch_idx>
+
+=over 4
+
+=item * L</bin_pkg>
+
+=item * L</arch_id>
+
+=item * L</ver>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bin_ver_bin_pkg_id_arch_idx", ["bin_pkg", "arch_id", "ver"]);
+
+=head2 C<bin_ver_src_ver_id_arch_idx>
+
+=over 4
+
+=item * L</src_ver_id>
+
+=item * L</arch_id>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bin_ver_src_ver_id_arch_idx", ["src_ver_id", "arch_id"]);
+
+=head1 RELATIONS
+
+=head2 arch
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Arch>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "arch",
+  "Debbugs::DB::Result::Arch",
+  { id => "arch_id" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 bin_associations
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BinAssociation>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bin_associations",
+  "Debbugs::DB::Result::BinAssociation",
+  { "foreign.bin" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bin_pkg
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::BinPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bin_pkg",
+  "Debbugs::DB::Result::BinPkg",
+  { id => "bin_pkg" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 src_ver
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "src_ver",
+  "Debbugs::DB::Result::SrcVer",
+  { id => "src_ver_id" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3K+5M1Rohq6AB4uLnVco+w
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BinaryVersion.pm b/Debbugs/DB/Result/BinaryVersion.pm
new file mode 100644 (file)
index 0000000..a959c82
--- /dev/null
@@ -0,0 +1,98 @@
+use utf8;
+package Debbugs::DB::Result::BinaryVersion;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BinaryVersion
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<binary_versions>
+
+=cut
+
+__PACKAGE__->table("binary_versions");
+
+=head1 ACCESSORS
+
+=head2 src_pkg
+
+  data_type: 'text'
+  is_nullable: 1
+
+=head2 src_ver
+
+  data_type: 'debversion'
+  is_nullable: 1
+
+=head2 bin_pkg
+
+  data_type: 'text'
+  is_nullable: 1
+
+=head2 arch
+
+  data_type: 'text'
+  is_nullable: 1
+
+=head2 bin_ver
+
+  data_type: 'debversion'
+  is_nullable: 1
+
+=head2 src_ver_based_on
+
+  data_type: 'debversion'
+  is_nullable: 1
+
+=head2 src_pkg_based_on
+
+  data_type: 'text'
+  is_nullable: 1
+
+=cut
+
+__PACKAGE__->add_columns(
+  "src_pkg",
+  { data_type => "text", is_nullable => 1 },
+  "src_ver",
+  { data_type => "debversion", is_nullable => 1 },
+  "bin_pkg",
+  { data_type => "text", is_nullable => 1 },
+  "arch",
+  { data_type => "text", is_nullable => 1 },
+  "bin_ver",
+  { data_type => "debversion", is_nullable => 1 },
+  "src_ver_based_on",
+  { data_type => "debversion", is_nullable => 1 },
+  "src_pkg_based_on",
+  { data_type => "text", is_nullable => 1 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:PiJglTBqLYRIi63gvGWIDQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Bug.pm b/Debbugs/DB/Result/Bug.pm
new file mode 100644 (file)
index 0000000..2782522
--- /dev/null
@@ -0,0 +1,474 @@
+use utf8;
+package Debbugs::DB::Result::Bug;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Bug - Bugs
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug>
+
+=cut
+
+__PACKAGE__->table("bug");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_nullable: 0
+
+Bug number
+
+=head2 creation
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time bug created
+
+=head2 log_modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time bug log was last modified
+
+=head2 last_modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time bug status was last modified
+
+=head2 archived
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 0
+
+True if bug has been archived
+
+=head2 unarchived
+
+  data_type: 'timestamp with time zone'
+  is_nullable: 1
+
+Time bug was last unarchived; null if bug has never been unarchived
+
+=head2 forwarded
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Where bug has been forwarded to; empty if it has not been forwarded
+
+=head2 summary
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Summary of the bug; empty if it has no summary
+
+=head2 outlook
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Outlook of the bug; empty if it has no outlook
+
+=head2 subject
+
+  data_type: 'text'
+  is_nullable: 0
+
+Subject of the bug
+
+=head2 severity
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+=head2 done
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Individual who did the -done; empty if it has never been -done
+
+=head2 done_full
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+=head2 owner
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Individual who owns this bug; empty if no one owns it
+
+=head2 owner_full
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+=head2 submitter
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Individual who submitted this bug; empty if there is no submitter
+
+=head2 submitter_full
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+=head2 unknown_packages
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Package name if the package is not known
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  { data_type => "integer", is_nullable => 0 },
+  "creation",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "log_modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "last_modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "archived",
+  { data_type => "boolean", default_value => \"false", is_nullable => 0 },
+  "unarchived",
+  { data_type => "timestamp with time zone", is_nullable => 1 },
+  "forwarded",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "summary",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "outlook",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "subject",
+  { data_type => "text", is_nullable => 0 },
+  "severity",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "done",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "done_full",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "owner",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "owner_full",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "submitter",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "submitter_full",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "unknown_packages",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 bug_binpackages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugBinpackage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_binpackages",
+  "Debbugs::DB::Result::BugBinpackage",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_blocks_blocks
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugBlock>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_blocks_blocks",
+  "Debbugs::DB::Result::BugBlock",
+  { "foreign.blocks" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_blocks_bugs
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugBlock>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_blocks_bugs",
+  "Debbugs::DB::Result::BugBlock",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_merged_bugs
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugMerged>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_merged_bugs",
+  "Debbugs::DB::Result::BugMerged",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_messages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugMessage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_messages",
+  "Debbugs::DB::Result::BugMessage",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_srcpackages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugSrcpackage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_srcpackages",
+  "Debbugs::DB::Result::BugSrcpackage",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_status_caches
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugStatusCache>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_status_caches",
+  "Debbugs::DB::Result::BugStatusCache",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_tags
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugTag>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_tags",
+  "Debbugs::DB::Result::BugTag",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_vers",
+  "Debbugs::DB::Result::BugVer",
+  { "foreign.bug" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bugs_merged_merged
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugMerged>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bugs_merged_merged",
+  "Debbugs::DB::Result::BugMerged",
+  { "foreign.merged" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 done
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Correspondent>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "done",
+  "Debbugs::DB::Result::Correspondent",
+  { id => "done" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 owner
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Correspondent>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "owner",
+  "Debbugs::DB::Result::Correspondent",
+  { id => "owner" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 severity
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Severity>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "severity",
+  "Debbugs::DB::Result::Severity",
+  { id => "severity" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 submitter
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Correspondent>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "submitter",
+  "Debbugs::DB::Result::Correspondent",
+  { id => "submitter" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 15:59:31
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hRsCzIGJB1krEYpMKmSVYw
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugBinpackage.pm b/Debbugs/DB/Result/BugBinpackage.pm
new file mode 100644 (file)
index 0000000..102feeb
--- /dev/null
@@ -0,0 +1,143 @@
+use utf8;
+package Debbugs::DB::Result::BugBinpackage;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugBinpackage - Bug <-> binary package mapping
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_binpackage>
+
+=cut
+
+__PACKAGE__->table("bug_binpackage");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_binpackage_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug id (matches bug)
+
+=head2 bin_pkg
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Binary package id (matches bin_pkg)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_binpackage_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "bin_pkg",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_binpackage_id_pkg_id>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</bin_pkg>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bug_binpackage_id_pkg_id", ["bug", "bin_pkg"]);
+
+=head1 RELATIONS
+
+=head2 bin_pkg
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::BinPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bin_pkg",
+  "Debbugs::DB::Result::BinPkg",
+  { id => "bin_pkg" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:cQ0MmOnrqlxvxubcvh4PBg
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugBlock.pm b/Debbugs/DB/Result/BugBlock.pm
new file mode 100644 (file)
index 0000000..273eca0
--- /dev/null
@@ -0,0 +1,143 @@
+use utf8;
+package Debbugs::DB::Result::BugBlock;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugBlock - Bugs which block other bugs
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_blocks>
+
+=cut
+
+__PACKAGE__->table("bug_blocks");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_blocks_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug number
+
+=head2 blocks
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug number which is blocked by bug
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_blocks_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "blocks",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_blocks_bug_id_blocks_idx>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</blocks>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bug_blocks_bug_id_blocks_idx", ["bug", "blocks"]);
+
+=head1 RELATIONS
+
+=head2 block
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "block",
+  "Debbugs::DB::Result::Bug",
+  { id => "blocks" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QswG/RKpqrXvpj74XiV0WQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugMerged.pm b/Debbugs/DB/Result/BugMerged.pm
new file mode 100644 (file)
index 0000000..7e8781d
--- /dev/null
@@ -0,0 +1,143 @@
+use utf8;
+package Debbugs::DB::Result::BugMerged;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugMerged - Bugs which are merged with other bugs
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_merged>
+
+=cut
+
+__PACKAGE__->table("bug_merged");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_merged_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug number
+
+=head2 merged
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug number which is merged with bug
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_merged_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "merged",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_merged_bug_id_merged_idx>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</merged>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bug_merged_bug_id_merged_idx", ["bug", "merged"]);
+
+=head1 RELATIONS
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 merged
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "merged",
+  "Debbugs::DB::Result::Bug",
+  { id => "merged" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8wKFwMnVTQBFyOIgB82LSA
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugMessage.pm b/Debbugs/DB/Result/BugMessage.pm
new file mode 100644 (file)
index 0000000..365d275
--- /dev/null
@@ -0,0 +1,154 @@
+use utf8;
+package Debbugs::DB::Result::BugMessage;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugMessage
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_message>
+
+=cut
+
+__PACKAGE__->table("bug_message");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_message_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug id (matches bug)
+
+=head2 message
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Message id (matches message)
+
+=head2 message_number
+
+  data_type: 'integer'
+  is_nullable: 0
+
+Message number in the bug log
+
+=head2 bug_log_offset
+
+  data_type: 'integer'
+  is_nullable: 1
+
+Byte offset in the bug log
+
+=head2 offset_valid
+
+  data_type: 'timestamp with time zone'
+  is_nullable: 1
+
+Time offset was valid
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_message_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "message",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "message_number",
+  { data_type => "integer", is_nullable => 0 },
+  "bug_log_offset",
+  { data_type => "integer", is_nullable => 1 },
+  "offset_valid",
+  { data_type => "timestamp with time zone", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 message
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Message>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "message",
+  "Debbugs::DB::Result::Message",
+  { id => "message" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3UCOADGWEq7+IA7L23sa5A
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugPackage.pm b/Debbugs/DB/Result/BugPackage.pm
new file mode 100644 (file)
index 0000000..2601f95
--- /dev/null
@@ -0,0 +1,77 @@
+use utf8;
+package Debbugs::DB::Result::BugPackage;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugPackage
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_package>
+
+=cut
+
+__PACKAGE__->table("bug_package");
+
+=head1 ACCESSORS
+
+=head2 bug
+
+  data_type: 'integer'
+  is_nullable: 1
+
+=head2 pkg_id
+
+  data_type: 'integer'
+  is_nullable: 1
+
+=head2 pkg_type
+
+  data_type: 'text'
+  is_nullable: 1
+
+=head2 package
+
+  data_type: 'text'
+  is_nullable: 1
+
+=cut
+
+__PACKAGE__->add_columns(
+  "bug",
+  { data_type => "integer", is_nullable => 1 },
+  "pkg_id",
+  { data_type => "integer", is_nullable => 1 },
+  "pkg_type",
+  { data_type => "text", is_nullable => 1 },
+  "package",
+  { data_type => "text", is_nullable => 1 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:593NXq7J5AFjjfFjMLXIvw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugSrcpackage.pm b/Debbugs/DB/Result/BugSrcpackage.pm
new file mode 100644 (file)
index 0000000..736074f
--- /dev/null
@@ -0,0 +1,143 @@
+use utf8;
+package Debbugs::DB::Result::BugSrcpackage;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugSrcpackage - Bug <-> source package mapping
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_srcpackage>
+
+=cut
+
+__PACKAGE__->table("bug_srcpackage");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_srcpackage_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug id (matches bug)
+
+=head2 src_pkg
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Source package id (matches src_pkg)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_srcpackage_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "src_pkg",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_srcpackage_id_pkg_id>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</src_pkg>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bug_srcpackage_id_pkg_id", ["bug", "src_pkg"]);
+
+=head1 RELATIONS
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 src_pkg
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "src_pkg",
+  "Debbugs::DB::Result::SrcPkg",
+  { id => "src_pkg" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jirMkEXqyqHGMbRiQ2hObw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugTag.pm b/Debbugs/DB/Result/BugTag.pm
new file mode 100644 (file)
index 0000000..81c16ed
--- /dev/null
@@ -0,0 +1,143 @@
+use utf8;
+package Debbugs::DB::Result::BugTag;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugTag - Bug <-> tag mapping
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_tag>
+
+=cut
+
+__PACKAGE__->table("bug_tag");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'bug_tag_id_seq'
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug id (matches bug)
+
+=head2 tag
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Tag id (matches tag)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "bug_tag_id_seq",
+  },
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "tag",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_tag_bug_tag_id>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</tag>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("bug_tag_bug_tag_id", ["bug", "tag"]);
+
+=head1 RELATIONS
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 tag
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Tag>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "tag",
+  "Debbugs::DB::Result::Tag",
+  { id => "tag" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 15:46:42
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7cqkTgwzMw4wP3LtAKaBDg
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/BugVer.pm b/Debbugs/DB/Result/BugVer.pm
new file mode 100644 (file)
index 0000000..d35f3e6
--- /dev/null
@@ -0,0 +1,208 @@
+use utf8;
+package Debbugs::DB::Result::BugVer;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::BugVer - Bug versions
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<bug_ver>
+
+=cut
+
+__PACKAGE__->table("bug_ver");
+
+=head1 ACCESSORS
+
+=head2 bug
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Bug number
+
+=head2 ver_string
+
+  data_type: 'text'
+  is_nullable: 1
+
+Version string
+
+=head2 src_pkg
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Source package id (matches src_pkg table)
+
+=head2 src_ver_id
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Source package version id (matches src_ver table)
+
+=head2 found
+
+  data_type: 'boolean'
+  default_value: true
+  is_nullable: 0
+
+True if this is a found version; false if this is a fixed version
+
+=head2 creation
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time that this entry was created
+
+=head2 last_modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time that this entry was modified
+
+=cut
+
+__PACKAGE__->add_columns(
+  "bug",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "ver_string",
+  { data_type => "text", is_nullable => 1 },
+  "src_pkg",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "src_ver_id",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "found",
+  { data_type => "boolean", default_value => \"true", is_nullable => 0 },
+  "creation",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "last_modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+);
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<bug_ver_bug_ver_string_found_idx>
+
+=over 4
+
+=item * L</bug>
+
+=item * L</ver_string>
+
+=item * L</found>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint(
+  "bug_ver_bug_ver_string_found_idx",
+  ["bug", "ver_string", "found"],
+);
+
+=head1 RELATIONS
+
+=head2 bug
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "bug",
+  "Debbugs::DB::Result::Bug",
+  { id => "bug" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 src_pkg
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "src_pkg",
+  "Debbugs::DB::Result::SrcPkg",
+  { id => "src_pkg" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 src_ver
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "src_ver",
+  "Debbugs::DB::Result::SrcVer",
+  { id => "src_ver_id" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/WX1pwdsAUjQK28CwCaDQw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Correspondent.pm b/Debbugs/DB/Result/Correspondent.pm
new file mode 100644 (file)
index 0000000..24cba22
--- /dev/null
@@ -0,0 +1,177 @@
+use utf8;
+package Debbugs::DB::Result::Correspondent;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Correspondent - Individual who has corresponded with the BTS
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<correspondent>
+
+=cut
+
+__PACKAGE__->table("correspondent");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'correspondent_id_seq'
+
+Correspondent ID
+
+=head2 addr
+
+  data_type: 'text'
+  is_nullable: 0
+
+Correspondent address
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "correspondent_id_seq",
+  },
+  "addr",
+  { data_type => "text", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<correspondent_addr_key>
+
+=over 4
+
+=item * L</addr>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("correspondent_addr_key", ["addr"]);
+
+=head1 RELATIONS
+
+=head2 bug_owners
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_owners",
+  "Debbugs::DB::Result::Bug",
+  { "foreign.owner" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_submitters
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_submitters",
+  "Debbugs::DB::Result::Bug",
+  { "foreign.submitter" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bugs_done
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bugs_done",
+  "Debbugs::DB::Result::Bug",
+  { "foreign.done" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 correspondent_full_names
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::CorrespondentFullName>
+
+=cut
+
+__PACKAGE__->has_many(
+  "correspondent_full_names",
+  "Debbugs::DB::Result::CorrespondentFullName",
+  { "foreign.correspondent" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 message_correspondents
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::MessageCorrespondent>
+
+=cut
+
+__PACKAGE__->has_many(
+  "message_correspondents",
+  "Debbugs::DB::Result::MessageCorrespondent",
+  { "foreign.correspondent" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:PnVRI1FMGlY8Go0XOM3wwA
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/CorrespondentFullName.pm b/Debbugs/DB/Result/CorrespondentFullName.pm
new file mode 100644 (file)
index 0000000..738004b
--- /dev/null
@@ -0,0 +1,130 @@
+use utf8;
+package Debbugs::DB::Result::CorrespondentFullName;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::CorrespondentFullName - Full names of BTS correspondents
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<correspondent_full_name>
+
+=cut
+
+__PACKAGE__->table("correspondent_full_name");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'correspondent_full_name_id_seq'
+
+Correspondent full name id
+
+=head2 correspondent
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+=head2 full_name
+
+  data_type: 'text'
+  is_nullable: 0
+
+Correspondent full name (includes e-mail address)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "correspondent_full_name_id_seq",
+  },
+  "correspondent",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "full_name",
+  { data_type => "text", is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<correspondent_full_name_correspondent_full_name_idx>
+
+=over 4
+
+=item * L</correspondent>
+
+=item * L</full_name>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint(
+  "correspondent_full_name_correspondent_full_name_idx",
+  ["correspondent", "full_name"],
+);
+
+=head1 RELATIONS
+
+=head2 correspondent
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Correspondent>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "correspondent",
+  "Debbugs::DB::Result::Correspondent",
+  { id => "correspondent" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 17:05:37
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xGcJNDjhN+ehcFQYzaBxBw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Maintainer.pm b/Debbugs/DB/Result/Maintainer.pm
new file mode 100644 (file)
index 0000000..53bfc0f
--- /dev/null
@@ -0,0 +1,149 @@
+use utf8;
+package Debbugs::DB::Result::Maintainer;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Maintainer - Package maintainer names
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<maintainer>
+
+=cut
+
+__PACKAGE__->table("maintainer");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'maintainer_id_seq'
+
+Package maintainer id
+
+=head2 name
+
+  data_type: 'text'
+  is_nullable: 0
+
+Name of package maintainer
+
+=head2 created
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time maintainer record created
+
+=head2 modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time maintainer record modified
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "maintainer_id_seq",
+  },
+  "name",
+  { data_type => "text", is_nullable => 0 },
+  "created",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<maintainer_name_key>
+
+=over 4
+
+=item * L</name>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("maintainer_name_key", ["name"]);
+
+=head1 RELATIONS
+
+=head2 src_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_vers",
+  "Debbugs::DB::Result::SrcVer",
+  { "foreign.maintainer_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pjSawHrI2qYqUHgkdxgh8g
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Message.pm b/Debbugs/DB/Result/Message.pm
new file mode 100644 (file)
index 0000000..ef36a9e
--- /dev/null
@@ -0,0 +1,232 @@
+use utf8;
+package Debbugs::DB::Result::Message;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Message - Messages sent to bugs
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<message>
+
+=cut
+
+__PACKAGE__->table("message");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'message_id_seq'
+
+Message id
+
+=head2 msgid
+
+  data_type: 'text'
+  is_nullable: 1
+
+Message id header
+
+=head2 from_complete
+
+  data_type: 'text'
+  is_nullable: 1
+
+Complete from header of message
+
+=head2 from_addr
+
+  data_type: 'text'
+  is_nullable: 1
+
+Address(es) of From: headers
+
+=head2 to_complete
+
+  data_type: 'text'
+  is_nullable: 1
+
+Complete to header of message
+
+=head2 to_addr
+
+  data_type: 'text'
+  is_nullable: 1
+
+Address(es) of To: header
+
+=head2 subject
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Subject of the message
+
+=head2 sent_date
+
+  data_type: 'timestamp with time zone'
+  is_nullable: 1
+
+Time/date message was sent (from Date header)
+
+=head2 refs
+
+  data_type: 'text'
+  default_value: (empty string)
+  is_nullable: 0
+
+Contents of References: header
+
+=head2 spam_score
+
+  data_type: 'double precision'
+  is_nullable: 1
+
+Spam score from spamassassin
+
+=head2 is_spam
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+True if this message was spam and should not be shown
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "message_id_seq",
+  },
+  "msgid",
+  { data_type => "text", is_nullable => 1 },
+  "from_complete",
+  { data_type => "text", is_nullable => 1 },
+  "from_addr",
+  { data_type => "text", is_nullable => 1 },
+  "to_complete",
+  { data_type => "text", is_nullable => 1 },
+  "to_addr",
+  { data_type => "text", is_nullable => 1 },
+  "subject",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "sent_date",
+  { data_type => "timestamp with time zone", is_nullable => 1 },
+  "refs",
+  { data_type => "text", default_value => "", is_nullable => 0 },
+  "spam_score",
+  { data_type => "double precision", is_nullable => 1 },
+  "is_spam",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 bug_messages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugMessage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_messages",
+  "Debbugs::DB::Result::BugMessage",
+  { "foreign.message" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 message_correspondents
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::MessageCorrespondent>
+
+=cut
+
+__PACKAGE__->has_many(
+  "message_correspondents",
+  "Debbugs::DB::Result::MessageCorrespondent",
+  { "foreign.message" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 message_refs_messages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::MessageRef>
+
+=cut
+
+__PACKAGE__->has_many(
+  "message_refs_messages",
+  "Debbugs::DB::Result::MessageRef",
+  { "foreign.message" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 message_refs_refs
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::MessageRef>
+
+=cut
+
+__PACKAGE__->has_many(
+  "message_refs_refs",
+  "Debbugs::DB::Result::MessageRef",
+  { "foreign.refs" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:5H4wsTVgTSnpnO1XcbvhHA
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/MessageCorrespondent.pm b/Debbugs/DB/Result/MessageCorrespondent.pm
new file mode 100644 (file)
index 0000000..7792290
--- /dev/null
@@ -0,0 +1,167 @@
+use utf8;
+package Debbugs::DB::Result::MessageCorrespondent;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::MessageCorrespondent - Linkage between correspondent and message
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<message_correspondent>
+
+=cut
+
+__PACKAGE__->table("message_correspondent");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'message_correspondent_id_seq'
+
+=head2 message
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Message id (matches message)
+
+=head2 correspondent
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Correspondent (matches correspondent)
+
+=head2 correspondent_type
+
+  data_type: 'enum'
+  default_value: 'to'
+  extra: {custom_type_name => "message_correspondent_type",list => ["to","from","envfrom","cc"]}
+  is_nullable: 0
+
+Type of correspondent (to, from, envfrom, cc, etc.)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "message_correspondent_id_seq",
+  },
+  "message",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "correspondent",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "correspondent_type",
+  {
+    data_type => "enum",
+    default_value => "to",
+    extra => {
+      custom_type_name => "message_correspondent_type",
+      list => ["to", "from", "envfrom", "cc"],
+    },
+    is_nullable => 0,
+  },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<message_correspondent_message_correspondent_correspondent_t_idx>
+
+=over 4
+
+=item * L</message>
+
+=item * L</correspondent>
+
+=item * L</correspondent_type>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint(
+  "message_correspondent_message_correspondent_correspondent_t_idx",
+  ["message", "correspondent", "correspondent_type"],
+);
+
+=head1 RELATIONS
+
+=head2 correspondent
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Correspondent>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "correspondent",
+  "Debbugs::DB::Result::Correspondent",
+  { id => "correspondent" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 message
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Message>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "message",
+  "Debbugs::DB::Result::Message",
+  { id => "message" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d2QCcAGqZtl1l7tx1fEwyg
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/MessageRef.pm b/Debbugs/DB/Result/MessageRef.pm
new file mode 100644 (file)
index 0000000..9d9d514
--- /dev/null
@@ -0,0 +1,163 @@
+use utf8;
+package Debbugs::DB::Result::MessageRef;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::MessageRef - Message references
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<message_refs>
+
+=cut
+
+__PACKAGE__->table("message_refs");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'message_refs_id_seq'
+
+=head2 message
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Message id (matches message)
+
+=head2 refs
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Reference id (matches message)
+
+=head2 inferred
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+TRUE if this message reference was reconstructed; primarily of use for messages which lack In-Reply-To: or References: headers
+
+=head2 primary_ref
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+TRUE if this message->ref came from In-Reply-To: or similar.
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "message_refs_id_seq",
+  },
+  "message",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "refs",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "inferred",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+  "primary_ref",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<message_refs_message_refs_idx>
+
+=over 4
+
+=item * L</message>
+
+=item * L</refs>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("message_refs_message_refs_idx", ["message", "refs"]);
+
+=head1 RELATIONS
+
+=head2 message
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Message>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "message",
+  "Debbugs::DB::Result::Message",
+  { id => "message" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 ref
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Message>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "ref",
+  "Debbugs::DB::Result::Message",
+  { id => "refs" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:+vwRG2KAV0YTTXZE0Vv21A
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Severity.pm b/Debbugs/DB/Result/Severity.pm
new file mode 100644 (file)
index 0000000..5a50252
--- /dev/null
@@ -0,0 +1,147 @@
+use utf8;
+package Debbugs::DB::Result::Severity;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Severity - Bug severity
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<severity>
+
+=cut
+
+__PACKAGE__->table("severity");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'severity_id_seq'
+
+Severity id
+
+=head2 severity
+
+  data_type: 'text'
+  is_nullable: 0
+
+Severity name
+
+=head2 ordering
+
+  data_type: 'integer'
+  default_value: 5
+  is_nullable: 0
+
+Severity ordering (more severe severities have higher numbers)
+
+=head2 strong
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+True if severity is a strong severity
+
+=head2 obsolete
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+Whether a severity level is obsolete (should not be set on new bugs)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "severity_id_seq",
+  },
+  "severity",
+  { data_type => "text", is_nullable => 0 },
+  "ordering",
+  { data_type => "integer", default_value => 5, is_nullable => 0 },
+  "strong",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+  "obsolete",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<severity_severity_key>
+
+=over 4
+
+=item * L</severity>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("severity_severity_key", ["severity"]);
+
+=head1 RELATIONS
+
+=head2 bugs
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::Bug>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bugs",
+  "Debbugs::DB::Result::Bug",
+  { "foreign.severity" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 19:35:10
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SVJ20W+hu/tjDthRG38xtA
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/SrcAssociation.pm b/Debbugs/DB/Result/SrcAssociation.pm
new file mode 100644 (file)
index 0000000..fff8c4c
--- /dev/null
@@ -0,0 +1,161 @@
+use utf8;
+package Debbugs::DB::Result::SrcAssociation;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::SrcAssociation - Source <-> suite associations
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<src_associations>
+
+=cut
+
+__PACKAGE__->table("src_associations");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'src_associations_id_seq'
+
+Source <-> suite association id
+
+=head2 suite
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Suite id (matches suite)
+
+=head2 source
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Source version id (matches src_ver)
+
+=head2 created
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time this source package entered this suite
+
+=head2 modified
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Time this entry was modified
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "src_associations_id_seq",
+  },
+  "suite",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "source",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "created",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "modified",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 source
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "source",
+  "Debbugs::DB::Result::SrcVer",
+  { id => "source" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 suite
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Suite>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "suite",
+  "Debbugs::DB::Result::Suite",
+  { id => "suite" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7lYnCaf4vZZFcZoz2S7O9A
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/SrcPkg.pm b/Debbugs/DB/Result/SrcPkg.pm
new file mode 100644 (file)
index 0000000..ac28c90
--- /dev/null
@@ -0,0 +1,200 @@
+use utf8;
+package Debbugs::DB::Result::SrcPkg;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::SrcPkg - Source packages
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<src_pkg>
+
+=cut
+
+__PACKAGE__->table("src_pkg");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'src_pkg_id_seq'
+
+Source package id
+
+=head2 pkg
+
+  data_type: 'text'
+  is_nullable: 0
+
+Source package name
+
+=head2 pseduopkg
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+=head2 alias_of
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Source package id which this source package is an alias of
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "src_pkg_id_seq",
+  },
+  "pkg",
+  { data_type => "text", is_nullable => 0 },
+  "pseduopkg",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+  "alias_of",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<src_pkg_pkg_key>
+
+=over 4
+
+=item * L</pkg>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("src_pkg_pkg_key", ["pkg"]);
+
+=head1 RELATIONS
+
+=head2 alias_of
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "alias_of",
+  "Debbugs::DB::Result::SrcPkg",
+  { id => "alias_of" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 bug_srcpackages
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugSrcpackage>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_srcpackages",
+  "Debbugs::DB::Result::BugSrcpackage",
+  { "foreign.src_pkg" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_vers",
+  "Debbugs::DB::Result::BugVer",
+  { "foreign.src_pkg" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 src_pkgs
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcPkg>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_pkgs",
+  "Debbugs::DB::Result::SrcPkg",
+  { "foreign.alias_of" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 src_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_vers",
+  "Debbugs::DB::Result::SrcVer",
+  { "foreign.src_pkg" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:w1ifDwgGG57aeGxFptavbg
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/SrcVer.pm b/Debbugs/DB/Result/SrcVer.pm
new file mode 100644 (file)
index 0000000..cd99a16
--- /dev/null
@@ -0,0 +1,265 @@
+use utf8;
+package Debbugs::DB::Result::SrcVer;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::SrcVer - Source Package versions
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<src_ver>
+
+=cut
+
+__PACKAGE__->table("src_ver");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'src_ver_id_seq'
+
+Source package version id
+
+=head2 src_pkg
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 0
+
+Source package id (matches src_pkg table)
+
+=head2 ver
+
+  data_type: 'debversion'
+  is_nullable: 0
+
+Version of the source package
+
+=head2 maintainer_id
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Maintainer id (matches maintainer table)
+
+=head2 upload_date
+
+  data_type: 'timestamp with time zone'
+  default_value: current_timestamp
+  is_nullable: 0
+  original: {default_value => \"now()"}
+
+Date this version of the source package was uploaded
+
+=head2 based_on
+
+  data_type: 'integer'
+  is_foreign_key: 1
+  is_nullable: 1
+
+Source package version this version is based on
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "src_ver_id_seq",
+  },
+  "src_pkg",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+  "ver",
+  { data_type => "debversion", is_nullable => 0 },
+  "maintainer_id",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+  "upload_date",
+  {
+    data_type     => "timestamp with time zone",
+    default_value => \"current_timestamp",
+    is_nullable   => 0,
+    original      => { default_value => \"now()" },
+  },
+  "based_on",
+  { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<src_ver_src_pkg_id_ver>
+
+=over 4
+
+=item * L</src_pkg>
+
+=item * L</ver>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("src_ver_src_pkg_id_ver", ["src_pkg", "ver"]);
+
+=head1 RELATIONS
+
+=head2 based_on
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "based_on",
+  "Debbugs::DB::Result::SrcVer",
+  { id => "based_on" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 bin_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BinVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bin_vers",
+  "Debbugs::DB::Result::BinVer",
+  { "foreign.src_ver_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_vers",
+  "Debbugs::DB::Result::BugVer",
+  { "foreign.src_ver_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 maintainer
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::Maintainer>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "maintainer",
+  "Debbugs::DB::Result::Maintainer",
+  { id => "maintainer_id" },
+  {
+    is_deferrable => 1,
+    join_type     => "LEFT",
+    on_delete     => "CASCADE",
+    on_update     => "CASCADE",
+  },
+);
+
+=head2 src_associations
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcAssociation>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_associations",
+  "Debbugs::DB::Result::SrcAssociation",
+  { "foreign.source" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 src_pkg
+
+Type: belongs_to
+
+Related object: L<Debbugs::DB::Result::SrcPkg>
+
+=cut
+
+__PACKAGE__->belongs_to(
+  "src_pkg",
+  "Debbugs::DB::Result::SrcPkg",
+  { id => "src_pkg" },
+  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+
+=head2 src_vers
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcVer>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_vers",
+  "Debbugs::DB::Result::SrcVer",
+  { "foreign.based_on" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-03-27 18:54:20
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hhXOPJ8se5BVKMsbvf+szw
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Suite.pm b/Debbugs/DB/Result/Suite.pm
new file mode 100644 (file)
index 0000000..3723aca
--- /dev/null
@@ -0,0 +1,175 @@
+use utf8;
+package Debbugs::DB::Result::Suite;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Suite - Debian Release Suite (stable, testing, etc.)
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<suite>
+
+=cut
+
+__PACKAGE__->table("suite");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'suite_id_seq'
+
+Suite id
+
+=head2 suite_name
+
+  data_type: 'text'
+  is_nullable: 0
+
+Suite name
+
+=head2 version
+
+  data_type: 'text'
+  is_nullable: 1
+
+Suite version; NULL if there is no appropriate version
+
+=head2 codename
+
+  data_type: 'text'
+  is_nullable: 1
+
+Suite codename
+
+=head2 active
+
+  data_type: 'boolean'
+  default_value: true
+  is_nullable: 1
+
+TRUE if the suite is still accepting uploads
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "suite_id_seq",
+  },
+  "suite_name",
+  { data_type => "text", is_nullable => 0 },
+  "version",
+  { data_type => "text", is_nullable => 1 },
+  "codename",
+  { data_type => "text", is_nullable => 1 },
+  "active",
+  { data_type => "boolean", default_value => \"true", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<suite_suite_name_key>
+
+=over 4
+
+=item * L</suite_name>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("suite_suite_name_key", ["suite_name"]);
+
+=head1 RELATIONS
+
+=head2 bin_associations
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BinAssociation>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bin_associations",
+  "Debbugs::DB::Result::BinAssociation",
+  { "foreign.suite" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 bug_status_caches
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugStatusCache>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_status_caches",
+  "Debbugs::DB::Result::BugStatusCache",
+  { "foreign.suite" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+=head2 src_associations
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::SrcAssociation>
+
+=cut
+
+__PACKAGE__->has_many(
+  "src_associations",
+  "Debbugs::DB::Result::SrcAssociation",
+  { "foreign.suite" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 15:46:42
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Wp8D70L0WeBbMqWkFEZEyQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
diff --git a/Debbugs/DB/Result/Tag.pm b/Debbugs/DB/Result/Tag.pm
new file mode 100644 (file)
index 0000000..85a2263
--- /dev/null
@@ -0,0 +1,127 @@
+use utf8;
+package Debbugs::DB::Result::Tag;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+Debbugs::DB::Result::Tag - Bug tags
+
+=cut
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L<DBIx::Class::InflateColumn::DateTime>
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime");
+
+=head1 TABLE: C<tag>
+
+=cut
+
+__PACKAGE__->table("tag");
+
+=head1 ACCESSORS
+
+=head2 id
+
+  data_type: 'integer'
+  is_auto_increment: 1
+  is_nullable: 0
+  sequence: 'tag_id_seq'
+
+Tag id
+
+=head2 tag
+
+  data_type: 'text'
+  is_nullable: 0
+
+Tag name
+
+=head2 obsolete
+
+  data_type: 'boolean'
+  default_value: false
+  is_nullable: 1
+
+Whether a tag is obsolete (should not be set on new bugs)
+
+=cut
+
+__PACKAGE__->add_columns(
+  "id",
+  {
+    data_type         => "integer",
+    is_auto_increment => 1,
+    is_nullable       => 0,
+    sequence          => "tag_id_seq",
+  },
+  "tag",
+  { data_type => "text", is_nullable => 0 },
+  "obsolete",
+  { data_type => "boolean", default_value => \"false", is_nullable => 1 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L</id>
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 UNIQUE CONSTRAINTS
+
+=head2 C<tag_tag_key>
+
+=over 4
+
+=item * L</tag>
+
+=back
+
+=cut
+
+__PACKAGE__->add_unique_constraint("tag_tag_key", ["tag"]);
+
+=head1 RELATIONS
+
+=head2 bug_tags
+
+Type: has_many
+
+Related object: L<Debbugs::DB::Result::BugTag>
+
+=cut
+
+__PACKAGE__->has_many(
+  "bug_tags",
+  "Debbugs::DB::Result::BugTag",
+  { "foreign.tag" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-04-01 15:46:42
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:O+iuATuRz+/8rETu8oYO9Q
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+1;
index b28ff5355658e4a24dc17bc29bc06da172334e39..1dc6ef8a73e91c4de7470fcb1f831ef4c514b804 100644 (file)
@@ -191,6 +191,7 @@ sub read_bug{
     my $status;
     my $log;
     my $location;
+    my $report;
     if (not defined $param{summary}) {
         my $lref;
         ($lref,$location) = @param{qw(bug location)};
@@ -200,13 +201,16 @@ sub read_bug{
         }
         $status = getbugcomponent($lref, 'summary', $location);
         $log    = getbugcomponent($lref, 'log'    , $location);
+        $report    = getbugcomponent($lref, 'report'    , $location);
         return undef unless defined $status;
         return undef if not -e $status;
     }
     else {
         $status = $param{summary};
         $log = $status;
+        $report = $status;
         $log =~ s/\.summary$/.log/;
+        $report =~ s/\.summary$/.report/;
         ($location) = $status =~ m/(db-h|db|archive)/;
          ($param{bug}) = $status =~ m/(\d+)\.summary$/;
     }
@@ -277,7 +281,12 @@ sub read_bug{
     my $status_modified = (stat($status))[9];
     # Add log last modified time
     $data{log_modified} = (stat($log))[9] // (stat("${log}.gz"))[9];
+    my $report_modified = (stat($report))[9] // $data{log_modified};
     $data{last_modified} = max($status_modified,$data{log_modified});
+    # if the date isn't set (ancient bug), use the smallest of any of the modified
+    if (not defined $data{date} or not length($data{date})) {
+        $data{date} = min($report_modified,$status_modified,$data{log_modified});
+    }
     $data{location} = $location;
     $data{archived} = (defined($location) and ($location eq 'archive'))?1:0;
     $data{bug_num} = $param{bug};
diff --git a/bin/debbugs-loadsql b/bin/debbugs-loadsql
new file mode 100755 (executable)
index 0000000..6b7d68b
--- /dev/null
@@ -0,0 +1,237 @@
+#! /usr/bin/perl
+# debbugs-loadsql is part of debbugs, and is released
+# under the terms of the GPL version 2, or any later version, at your
+# option. See the file README and COPYING for more information.
+# Copyright 2012 by Don Armstrong <don@donarmstrong.com>.
+
+
+use warnings;
+use strict;
+
+use Getopt::Long qw(:config no_ignore_case);
+use Pod::Usage;
+
+=head1 NAME
+
+debbugs-loadsql -- load debbugs sql database
+
+=head1 SYNOPSIS
+
+debbugs-loadsql [options]
+
+ Options:
+  --quick, -q only load changed bugs
+  --progress Show progress bar
+  --service, -s service name
+  --sysconfdir, -c postgresql service config dir
+  --spool-dir debbugs spool directory
+  --debug, -d debugging level (Default 0)
+  --help, -h display this help
+  --man, -m display manual
+
+=head1 OPTIONS
+
+=over
+
+=item B<--quick, -q>
+
+Only load changed bugs
+
+=item B<--progress>
+
+Show progress bar (requires Term::ProgressBar)
+
+=item B<--service,-s>
+
+Postgreql service to use; defaults to debbugs
+
+=item B<--sysconfdir,-c>
+
+System configuration directory to use; if not set, defaults to the
+postgresql default. [Operates by setting PGSYSCONFDIR]
+
+=item B<--spool-dir>
+
+Debbugs spool directory; defaults to the value configured in the
+debbugs configuration file.
+
+=item B<--verbose>
+
+Output more information about what is happening. Probably not useful
+if you also set --progress.
+
+=item B<--debug, -d
+
+Debug verbosity.
+
+=item B<--help, -h>
+
+Display brief useage information.
+
+=item B<--man, -m>
+
+Display this manual.
+
+=back
+
+
+=cut
+
+
+use vars qw($DEBUG);
+
+use Debbugs::Common qw(checkpid lockpid get_hashname getparsedaddrs getbugcomponent make_list);
+use Debbugs::Config qw(:config);
+use Debbugs::Status qw(read_bug split_status_fields);
+use Debbugs::Log;
+use Debbugs::DB;
+use Debbugs::DB::Load qw(load_bug handle_load_bug_queue);
+use DateTime;
+use File::stat;
+
+
+my %options =
+    (debug           => 0,
+     help            => 0,
+     man             => 0,
+     verbose         => 0,
+     quiet           => 0,
+     quick           => 0,
+     service         => 'debbugs',
+     progress        => 0,
+    );
+
+
+GetOptions(\%options,
+           'quick|q',
+           'service|s',
+           'sysconfdir|c',
+           'progress!',
+           'spool_dir|spool-dir=s',
+           'verbose|v+',
+           'quiet+',
+           'debug|d+','help|h|?','man|m');
+
+pod2usage() if $options{help};
+pod2usage({verbose=>2}) if $options{man};
+
+$DEBUG = $options{debug};
+
+my @USAGE_ERRORS;
+$options{verbose} = $options{verbose} - $options{quiet};
+
+if ($options{progress}) {
+    eval "use Term::ProgressBar";
+    push @USAGE_ERRORS, "You asked for a progress bar, but Term::ProgressBar isn't installed" if $@;
+}
+
+
+pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
+
+if (exists $options{sysconfdir}) {
+    if (not defined $options{sysconfdir} or not length $options{sysconfdir}) {
+       delete $ENV{PGSYSCONFDIR};
+    } else {
+       $ENV{PGSYSCONFDIR} = $options{sysconfdir};
+    }
+}
+
+if (exists $options{spool_dir} and defined $options{spool_dir}) {
+    $config{spool_dir} = $options{spool_dir};
+}
+chdir($config{spool_dir}) or die "chdir $config{spool_dir} failed: $!";
+
+my $verbose = $options{debug};
+
+my $initialdir = "db-h";
+
+if (defined $ARGV[0] and $ARGV[0] eq "archive") {
+    $initialdir = "archive";
+}
+
+if (not lockpid($config{spool_dir}.'/lock/debbugs-loadsql')) {
+     if ($options{quick}) {
+         # If this is a quick run, just exit
+         print STDERR "Another debbugs-loadsql is running; stopping\n" if $verbose;
+         exit 0;
+     }
+     print STDERR "Another debbugs-loadsql is running; stopping\n";
+     exit 1;
+}
+
+
+# connect to the database; figure out how to handle errors properly
+# here.
+my $schema = Debbugs::DB->connect('dbi:Pg:service='.$options{service}) or
+    die "Unable to connect to database: ";
+
+my $time = 0;
+my $start_time = time;
+
+
+my @dirs = (@ARGV?@ARGV : $initialdir);
+my $cnt = 0;
+my %tags;
+my %severities;
+my %queue;
+my $tot_dirs = @ARGV ? @ARGV : 0;
+my $done_dirs = 0;
+my $avg_subfiles = 0;
+my $completed_files = 0;
+my $p;
+if ($options{progress}) {
+    $p = eval "Term::ProgressBar->new({count => 1,ETA=>q(linear)})";
+    warn "Unable to initialize progress bar: $@" if not $p;
+}
+while (my $dir = shift @dirs) {
+    printf "Doing dir %s ...\n", $dir if $verbose;
+
+    opendir(DIR, "$dir/.") or die "opendir $dir: $!";
+    my @subdirs = readdir(DIR);
+    closedir(DIR);
+
+    my @list = map { m/^(\d+)\.summary$/?($1):() } @subdirs;
+    $tot_dirs -= @dirs;
+    push @dirs, map { m/^(\d+)$/ && -d "$dir/$1"?("$dir/$1"):() } @subdirs;
+    $tot_dirs += @dirs;
+    if ($avg_subfiles == 0) {
+        $avg_subfiles = @list;
+    }
+
+    $p->target($avg_subfiles*($tot_dirs-$done_dirs)+$completed_files+@list) if $p;
+    $avg_subfiles = ($avg_subfiles * $done_dirs + @list) / ($done_dirs+1);
+    $done_dirs += 1;
+
+    for my $bug (@list) {
+        $completed_files++;
+        $p->update($completed_files) if $p;
+       print "Up to $cnt bugs...\n" if (++$cnt % 100 == 0 && $verbose);
+       my $stat = stat(getbugcomponent($bug,'summary',$initialdir));
+       if (not defined $stat) {
+           print STDERR "Unable to stat $bug $!\n";
+           next;
+       }
+       next if $stat->mtime < $time;
+       my $data = read_bug(bug => $bug,
+                           location => $initialdir);
+        eval {
+            load_bug(db => $schema,
+                     data => split_status_fields($data),
+                     tags => \%tags,
+                     severities => \%severities,
+                     queue => \%queue);
+        };
+        if ($@) {
+            use Data::Dumper;
+            print STDERR Dumper($data) if $DEBUG;
+            die "failure while trying to load bug $bug\n$@";
+        }
+    }
+}
+$p->remove() if $p;
+handle_load_bug_queue(db => $schema,
+                      queue => \%queue);
+
+
+
+__END__
diff --git a/bin/debbugs-loadsql-debinfo b/bin/debbugs-loadsql-debinfo
new file mode 100755 (executable)
index 0000000..2d491d9
--- /dev/null
@@ -0,0 +1,156 @@
+#! /usr/bin/perl
+# debbugs-loadsql-debinfo is part of debbugs, and is released
+# under the terms of the GPL version 2, or any later version, at your
+# option. See the file README and COPYING for more information.
+# Copyright 2012 by Don Armstrong <don@donarmstrong.com>.
+
+
+use warnings;
+use strict;
+
+use Getopt::Long qw(:config no_ignore_case);
+use Pod::Usage;
+
+=head1 NAME
+
+debbugs-loadsql-debinfo -- load debbugs sql versions database
+
+=head1 SYNOPSIS
+
+debbugs-loadsql-debinfo [options]
+
+ Options:
+  --service, -s service name
+  --sysconfdir, -c postgresql service config dir
+  --debug, -d debugging level (Default 0)
+  --help, -h display this help
+  --man, -m display manual
+
+=head1 OPTIONS
+
+=over
+
+=item B<--quick, -q>
+
+Only load changed bugs
+
+=item B<--service,-s>
+
+Postgreql service to use; defaults to debbugs
+
+=item B<--sysconfdir,-c>
+
+System configuration directory to use; if not set, defaults to the
+postgresql default. [Operates by setting PGSYSCONFDIR]
+
+=item B<--debug, -d
+
+Debug verbosity.
+
+=item B<--help, -h>
+
+Display brief useage information.
+
+=item B<--man, -m>
+
+Display this manual.
+
+=back
+
+
+=cut
+
+
+use vars qw($DEBUG);
+
+use Debbugs::Common qw(checkpid lockpid get_hashname getparsedaddrs getbugcomponent make_list);
+use Debbugs::Config qw(:config);
+use Debbugs::Status qw(read_bug split_status_fields);
+use Debbugs::Log;
+use Debbugs::DB;
+use DateTime;
+use File::stat;
+
+
+my %options = (debug           => 0,
+              help            => 0,
+              man             => 0,
+              verbose         => 0,
+              quiet           => 0,
+              quick           => 0,
+              service         => 'debbugs',
+             );
+
+
+GetOptions(\%options,
+          'quick|q',
+          'service|s',
+          'sysconfdir|c',
+          'debug|d+','help|h|?','man|m');
+
+pod2usage() if $options{help};
+pod2usage({verbose=>2}) if $options{man};
+
+$DEBUG = $options{debug};
+
+my @USAGE_ERRORS;
+$options{verbose} = $options{verbose} - $options{quiet};
+
+pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
+
+if (exists $options{sysconfdir}) {
+    if (not defined $options{sysconfdir} or not length $options{sysconfdir}) {
+       delete $ENV{PGSYSCONFDIR};
+    } else {
+       $ENV{PGSYSCONFDIR} = $options{sysconfdir};
+    }
+}
+
+my $verbose = $options{debug};
+
+my $initialdir = "db-h";
+
+# connect to the database; figure out how to handle errors properly
+# here.
+my $s = Debbugs::DB->connect('dbi:Pg:service='.$options{service}) or
+    die "Unable to connect to database: ";
+
+my @files = @ARGV;
+
+my %arch;
+for my $file (@files) {
+    my $fh = IO::File->new($file,'r') or
+       die "Unable to open $file for reading: $!";
+    while (<$fh>) {
+       chomp;
+       next unless length $_;
+       my ($binname, $binver, $binarch, $srcname, $srcver) = split;
+       # if $srcver is not defined, this is probably a broken
+       # .debinfo file [they were causing #686106, see commit
+       # 49c85ab8 in dak.] Basically, $binarch didn't get put into
+       # the file, so we'll fudge it from the filename.
+       if (not defined $srcver) {
+           ($srcname,$srcver) = ($binarch,$srcname);
+           ($binarch) = $file =~ /_([^\.]+)\.debinfo/;
+       }
+       my $sp = $s->resultset('SrcPkg')->find_or_create({pkg => $srcname});
+       my $sv = $s->resultset('SrcVer')->find_or_create({src_pkg_id=>$sp->id(),
+                                                         ver => $srcver});
+        my $arch;
+        if (defined $arch{$binarch}) {
+            $arch = $arch{$binarch};
+        } else {
+            $arch = $s->resultset('Arch')->find_or_create({arch => $binarch});
+            $arch{$binarch} = $arch;
+        }
+       my $bp = $s->resultset('BinPkg')->find_or_create({pkg => $binname});
+       $s->resultset('BinVer')->find_or_create({bin_pkg_id => $bp->id(),
+                                                src_ver_id => $sv->id(),
+                                                arch_id    => $arch->id(),
+                                                ver        => $binver,
+                                               });
+    }
+}
+
+
+__END__
diff --git a/bin/debbugs-loadsql-versions b/bin/debbugs-loadsql-versions
new file mode 100755 (executable)
index 0000000..8ab9868
--- /dev/null
@@ -0,0 +1,153 @@
+#! /usr/bin/perl
+# debbugs-loadsql-versions is part of debbugs, and is released
+# under the terms of the GPL version 2, or any later version, at your
+# option. See the file README and COPYING for more information.
+# Copyright 2012 by Don Armstrong <don@donarmstrong.com>.
+
+
+use warnings;
+use strict;
+
+use Getopt::Long qw(:config no_ignore_case);
+use Pod::Usage;
+
+=head1 NAME
+
+debbugs-loadsql-versions -- load debbugs sql versions database
+
+=head1 SYNOPSIS
+
+debbugs-loadsql-versions [options]
+
+ Options:
+  --service, -s service name
+  --sysconfdir, -c postgresql service config dir
+  --debug, -d debugging level (Default 0)
+  --help, -h display this help
+  --man, -m display manual
+
+=head1 OPTIONS
+
+=over
+
+=item B<--quick, -q>
+
+Only load changed bugs
+
+=item B<--service,-s>
+
+Postgreql service to use; defaults to debbugs
+
+=item B<--sysconfdir,-c>
+
+System configuration directory to use; if not set, defaults to the
+postgresql default. [Operates by setting PGSYSCONFDIR]
+
+=item B<--debug, -d
+
+Debug verbosity.
+
+=item B<--help, -h>
+
+Display brief useage information.
+
+=item B<--man, -m>
+
+Display this manual.
+
+=back
+
+
+=cut
+
+
+use vars qw($DEBUG);
+
+use Debbugs::Common qw(checkpid lockpid get_hashname getparsedaddrs getbugcomponent make_list);
+use Debbugs::Config qw(:config);
+use Debbugs::Status qw(read_bug split_status_fields);
+use Debbugs::Log;
+use Debbugs::DB;
+use DateTime;
+use File::stat;
+
+
+my %options = (debug           => 0,
+              help            => 0,
+              man             => 0,
+              verbose         => 0,
+              quiet           => 0,
+              quick           => 0,
+              service         => 'debbugs',
+             );
+
+
+GetOptions(\%options,
+          'quick|q',
+          'service|s',
+          'sysconfdir|c',
+          'spool_dir|spool-dir=s',
+          'debug|d+','help|h|?','man|m');
+
+pod2usage() if $options{help};
+pod2usage({verbose=>2}) if $options{man};
+
+$DEBUG = $options{debug};
+
+my @USAGE_ERRORS;
+$options{verbose} = $options{verbose} - $options{quiet};
+
+pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
+
+if (exists $options{sysconfdir}) {
+    if (not defined $options{sysconfdir} or not length $options{sysconfdir}) {
+       delete $ENV{PGSYSCONFDIR};
+    } else {
+       $ENV{PGSYSCONFDIR} = $options{sysconfdir};
+    }
+}
+
+my $verbose = $options{debug};
+
+# connect to the database; figure out how to handle errors properly
+# here.
+my $s = Debbugs::DB->connect('dbi:Pg:service='.$options{service}) or
+    die "Unable to connect to database: ";
+
+my @files = @ARGV;
+for my $file (@files) {
+    my $fh = IO::File->new($file,'r') or
+       die "Unable to open $file for reading: $!";
+    my @versions;
+    my %src_pkgs;
+    while (<$fh>) {
+       chomp;
+       next unless length $_;
+       if (/(\w[-+0-9a-z.]+) \(([^\(\) \t]+)\)/) {
+           push @versions, [$1,$2];
+       }
+    }
+    close($fh);
+    my $ancestor_sv;
+    for my $i (reverse 0..($#versions)) {
+        my $sp;
+        if (not defined $src_pkgs{$versions[$i][0]}) {
+            $src_pkgs{$versions[$i][0]} =
+                $s->resultset('SrcPkg')->find({pkg => $versions[$i][0]});
+        }
+        $sp = $src_pkgs{$versions[$i][0]};
+        # There's probably something wrong if the source package
+        # doesn't exist, but we'll skip it for now
+       next unless defined $sp;
+       my $sv = $s->resultset('SrcVer')->find({src_pkg_id=>$sp->id(),
+                                               ver => $versions[$i][1],
+                                              });
+       if (defined $ancestor_sv and defined $sv and not defined $sv->based_on()) {
+           $sv->update({based_on => $ancestor_sv->id()})
+       }
+       $ancestor_sv = $sv;
+    }
+}
+
+
+__END__
index e99301a98fe60e55b0ef0cf0a78fa0dd3a7cbaa2..74c47b1d76585fe7b56d605ccd691c6c792df769 100644 (file)
@@ -13,7 +13,7 @@ Build-Depends-Indep: libparams-validate-perl,
  libhttp-server-simple-perl, libtest-www-mechanize-perl,
  libmail-rfc822-address-perl, libsafe-hole-perl, libuser-perl,
  libconfig-simple-perl, libtest-pod-perl, liblist-moreutils-perl,
- libtext-template-perl
+ libtext-template-perl, libdbix-class-perl, libdatetime-format-pg-perl
 Homepage: http://wiki.debian.org/Teams/Debbugs
 
 Package: debbugs
diff --git a/sql/dbicdump.conf b/sql/dbicdump.conf
new file mode 100644 (file)
index 0000000..f9c2741
--- /dev/null
@@ -0,0 +1,12 @@
+schema_class Debbugs::DB::Schema
+
+lib .
+
+<connect_info>
+    dsn     dbi:Pg:service=snp
+</connect_info>
+
+<loader_options>
+    components  InflateColumn::DateTime
+    components  TimeStamp
+</loader_options>
\ No newline at end of file
diff --git a/sql/dbicdump_command.sh b/sql/dbicdump_command.sh
new file mode 100755 (executable)
index 0000000..b56ad68
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if ! [ -d "sql" ] || ! [ -d "Debbugs" ]; then 
+    echo "In the wrong directory"
+    exit 1;
+fi;
+
+dbicdump -I. -o dump_directory=. \
+    -o components='["InflateColumn::DateTime"]' \
+    -o preserve_case=1 \
+    Debbugs::DB dbi:Pg:service=debbugs '' '';
+
diff --git a/sql/debbugs_schema.sql b/sql/debbugs_schema.sql
new file mode 100644 (file)
index 0000000..d2ecfa2
--- /dev/null
@@ -0,0 +1,476 @@
+
+DROP TABLE bug_status_cache CASCADE;
+DROP VIEW  bug_package CASCADE;
+DROP VIEW binary_versions CASCADE;
+DROP TABLE bug_tag CASCADE;
+DROP TABLE tag CASCADE;
+DROP TABLE severity CASCADE;
+DROP TABLE bug CASCADE;
+DROP TABLE src_pkg CASCADE;
+DROP TABLE bug_ver CASCADE;
+DROP TABLE src_ver CASCADE;
+DROP TABLE arch CASCADE;
+DROP TABLE bin_ver CASCADE;
+DROP TABLE bin_pkg CASCADE;
+DROP TABLE bug_blocks CASCADE;
+DROP TABLE bug_merged CASCADE;
+DROP TABLE bug_srcpackage CASCADE;
+DROP TABLE bug_binpackage CASCADE;
+DROP TABLE suite CASCADE;
+DROP TABLE bin_associations CASCADE;
+DROP TABLE src_associations CASCADE;
+DROP TABLE maintainer CASCADE;
+DROP TABLE bug_message CASCADE;
+DROP TABLE message_correspondent CASCADE;
+DROP TABLE correspondent_full_name CASCADE;
+DROP TABLE correspondent CASCADE;
+DROP TABLE message_refs CASCADE;
+DROP TABLE message CASCADE;
+DROP TYPE message_correspondent_type CASCADE;
+DROP TABLE table_comments CASCADE;
+DROP TABLE column_comments CASCADE;
+DROP TYPE bug_status_type CASCADE;
+
+-- the following two tables are used to provide documentation about
+-- the tables and columns for DBIx::Class::Schema::Loader
+CREATE TABLE table_comments (
+       table_name TEXT UNIQUE NOT NULL,
+       comment_text TEXT NOT NULL
+);
+CREATE TABLE column_comments (
+       table_name TEXT  NOT NULL,
+       column_name TEXT  NOT NULL,
+       comment_text TEXT NOT NULL
+);
+CREATE UNIQUE INDEX ON column_comments(table_name,column_name);
+
+CREATE TABLE maintainer (
+       id SERIAL PRIMARY KEY,
+       name TEXT NOT NULL UNIQUE,
+       created TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
+       modified TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
+);
+INSERT INTO table_comments  VALUES ('maintainer','Package maintainer names');
+INSERT INTO column_comments VALUES ('maintainer','id','Package maintainer id');
+INSERT INTO column_comments VALUES ('maintainer','name','Name of package maintainer');
+INSERT INTO column_comments VALUES ('maintainer','created','Time maintainer record created');
+INSERT INTO column_comments VALUES ('maintainer','modified','Time maintainer record modified');
+
+CREATE TABLE correspondent (
+       id SERIAL PRIMARY KEY,
+       addr TEXT NOT NULL UNIQUE
+);
+INSERT INTO table_comments VALUES ('correspondent','Individual who has corresponded with the BTS');
+INSERT INTO column_comments VALUES ('correspondent','id','Correspondent ID');
+INSERT INTO column_comments VALUES ('correspondent','addr','Correspondent address');
+
+CREATE TABLE severity (
+       id SERIAL PRIMARY KEY,
+       severity TEXT NOT NULL UNIQUE,
+       ordering INT NOT NULL DEFAULT 5,
+       strong BOOLEAN DEFAULT FALSE,
+       obsolete BOOLEAN DEFAULT FALSE
+);
+INSERT INTO table_comments VALUES ('severity','Bug severity');
+INSERT INTO column_comments VALUES ('severity','id','Severity id');
+INSERT INTO column_comments VALUES ('severity','severity','Severity name');
+INSERT INTO column_comments VALUES ('severity','ordering','Severity ordering (more severe severities have higher numbers)');
+INSERT INTO column_comments VALUES ('severity','strong','True if severity is a strong severity');
+INSERT INTO column_comments VALUES ('severity','obsolete','Whether a severity level is obsolete (should not be set on new bugs)');
+
+-- bugs table
+CREATE TABLE bug (
+       id INTEGER NOT NULL PRIMARY KEY,
+       creation TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+       log_modified TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+       last_modified TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+       archived BOOLEAN NOT NULL DEFAULT FALSE,
+       unarchived TIMESTAMP WITH TIME ZONE,
+       forwarded TEXT NOT NULL DEFAULT '',
+       summary TEXT NOT NULL DEFAULT '',
+       outlook TEXT NOT NULL DEFAULT '',
+       subject TEXT NOT NULL,
+       severity INT NOT NULL REFERENCES severity(id),
+       done INT REFERENCES correspondent(id),
+       done_full TEXT NOT NULL DEFAULT '',
+       owner INT REFERENCES correspondent(id),
+       owner_full TEXT NOT NULL DEFAULT '',
+       -- submitter would ideally be NOT NULL, but there are some ancient bugs which do not have submitters
+       submitter INT REFERENCES correspondent(id),
+       submitter_full TEXT NOT NULL DEFAULT '',
+       unknown_packages TEXT NOT NULL DEfAULT ''
+);
+INSERT INTO table_comments VALUES ('bug','Bugs');
+INSERT INTO column_comments VALUES ('bug','id','Bug number');
+INSERT INTO column_comments VALUES ('bug','creation','Time bug created');
+INSERT INTO column_comments VALUES ('bug','log_modified','Time bug log was last modified');
+INSERT INTO column_comments VALUES ('bug','last_modified','Time bug status was last modified');
+INSERT INTO column_comments VALUES ('bug','archived','True if bug has been archived');
+INSERT INTO column_comments VALUES ('bug','unarchived','Time bug was last unarchived; null if bug has never been unarchived');
+INSERT INTO column_comments VALUES ('bug','forwarded','Where bug has been forwarded to; empty if it has not been forwarded');
+INSERT INTO column_comments VALUES ('bug','summary','Summary of the bug; empty if it has no summary');
+INSERT INTO column_comments VALUES ('bug','outlook','Outlook of the bug; empty if it has no outlook');
+INSERT INTO column_comments VALUES ('bug','subject','Subject of the bug');
+INSERT INTO column_comments VALUES ('bug','done','Individual who did the -done; empty if it has never been -done');
+INSERT INTO column_comments VALUES ('bug','owner','Individual who owns this bug; empty if no one owns it');
+INSERT INTO column_comments VALUES ('bug','submitter','Individual who submitted this bug; empty if there is no submitter');
+INSERT INTO column_comments VALUES ('bug','unknown_packages','Package name if the package is not known');
+
+CREATE INDEX ON bug(creation);
+CREATE INDEX ON bug(log_modified);
+CREATE INDEX ON bug(done);
+CREATE INDEX ON bug(owner);
+CREATE INDEX ON bug(submitter);
+CREATE INDEX ON bug(forwarded);
+
+
+
+CREATE TABLE bug_blocks (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug,
+       blocks INT NOT NULL REFERENCES bug,
+       CONSTRAINT bug_doesnt_block_itself CHECK (bug <> blocks)
+);
+CREATE UNIQUE INDEX bug_blocks_bug_id_blocks_idx ON bug_blocks(bug,blocks);
+CREATE INDEX bug_blocks_bug_id_idx ON bug_blocks(bug);
+CREATE INDEX bug_blocks_blocks_idx ON bug_blocks(blocks);
+INSERT INTO table_comments VALUES ('bug_blocks','Bugs which block other bugs');
+INSERT INTO column_comments VALUES ('bug_blocks','bug','Bug number');
+INSERT INTO column_comments VALUES ('bug_blocks','blocks','Bug number which is blocked by bug');
+
+
+CREATE TABLE bug_merged (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug,
+       merged INT NOT NULL REFERENCES bug,
+       CONSTRAINT bug_doesnt_merged_itself CHECK (bug <> merged)
+);
+CREATE UNIQUE INDEX bug_merged_bug_id_merged_idx ON bug_merged(bug,merged);
+CREATE INDEX bug_merged_bug_id_idx ON bug_merged(bug);
+CREATE INDEX bug_merged_merged_idx ON bug_merged(merged);
+INSERT INTO table_comments  VALUES ('bug_merged','Bugs which are merged with other bugs');
+INSERT INTO column_comments VALUES ('bug_merged','bug','Bug number');
+INSERT INTO column_comments VALUES ('bug_merged','merged','Bug number which is merged with bug');
+
+CREATE TABLE src_pkg (
+       id SERIAL PRIMARY KEY,
+       pkg TEXT NOT NULL UNIQUE,
+       pseduopkg BOOLEAN DEFAULT FALSE,
+       alias_of INT REFERENCES src_pkg ON UPDATE CASCADE ON DELETE CASCADE
+       CONSTRAINT src_pkg_doesnt_alias_itself CHECK (id <> alias_of)
+);
+INSERT INTO table_comments VALUES ('src_pkg','Source packages');
+INSERT INTO column_comments VALUES ('src_pkg','id','Source package id');
+INSERT INTO column_comments VALUES ('src_pkg','pkg','Source package name');
+INSERT INTO column_comments VALUES ('src_pkg','pseudopkg','True if this is a pseudo package');
+INSERT INTO column_comments VALUES ('src_pkg','alias_of','Source package id which this source package is an alias of');
+
+
+
+CREATE TABLE src_ver (
+       id SERIAL PRIMARY KEY,
+       src_pkg INT NOT NULL REFERENCES src_pkg
+            ON UPDATE CASCADE ON DELETE CASCADE,
+       ver public.debversion NOT NULL,
+       maintainer_id INT REFERENCES maintainer
+            ON UPDATE CASCADE ON DELETE SET NULL,
+       upload_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+       based_on INT REFERENCES src_ver
+            ON UPDATE CASCADE ON DELETE CASCADE
+);
+CREATE UNIQUE INDEX src_ver_src_pkg_id_ver ON src_ver(src_pkg,ver);
+INSERT INTO table_comments VALUES ('src_ver','Source Package versions');
+INSERT INTO column_comments VALUES ('src_ver','id','Source package version id');
+INSERT INTO column_comments VALUES ('src_ver','src_pkg','Source package id (matches src_pkg table)');
+INSERT INTO column_comments VALUES ('src_ver','ver','Version of the source package');
+INSERT INTO column_comments VALUES ('src_ver','maintainer_id','Maintainer id (matches maintainer table)');
+INSERT INTO column_comments VALUES ('src_ver','upload_date','Date this version of the source package was uploaded');
+INSERT INTO column_comments VALUES ('src_ver','based_on','Source package version this version is based on');
+
+
+
+CREATE TABLE bug_ver (
+       bug INT NOT NULL REFERENCES bug
+         ON UPDATE CASCADE ON DELETE RESTRICT,
+       ver_string TEXT,
+       src_pkg INT REFERENCES src_pkg
+            ON UPDATE CASCADE ON DELETE SET NULL,
+       src_ver_id INT REFERENCES src_ver
+            ON UPDATE CASCADE ON DELETE SET NULL,
+       found BOOLEAN NOT NULL DEFAULT TRUE,
+       creation TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+       last_modified TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
+);
+CREATE INDEX bug_ver_src_pkg_id_idx ON bug_ver(src_pkg);
+CREATE INDEX bug_ver_src_pkg_id_src_ver_id_idx ON bug_ver(src_pkg,src_ver_id);
+CREATE INDEX bug_ver_src_ver_id_idx ON bug_ver(src_ver_id);
+CREATE UNIQUE INDEX ON bug_ver(bug,ver_string,found);
+INSERT INTO table_comments VALUES ('bug_ver','Bug versions');
+INSERT INTO column_comments VALUES ('bug_ver','bug','Bug number');
+INSERT INTO column_comments VALUES ('bug_ver','ver_string','Version string');
+INSERT INTO column_comments VALUES ('bug_ver','src_pkg','Source package id (matches src_pkg table)');
+INSERT INTO column_comments VALUES ('bug_ver','src_ver_id','Source package version id (matches src_ver table)');
+INSERT INTO column_comments VALUES ('bug_ver','found','True if this is a found version; false if this is a fixed version');
+INSERT INTO column_comments VALUES ('bug_ver','creation','Time that this entry was created');
+INSERT INTO column_comments VALUES ('bug_ver','last_modified','Time that this entry was modified');
+
+
+CREATE TABLE arch (
+       id SERIAL PRIMARY KEY,
+       arch TEXT NOT NULL UNIQUE
+);
+INSERT INTO table_comments VALUES ('arch','Architectures');
+INSERT INTO column_comments VALUES ('arch','id','Architecture id');
+INSERT INTO column_comments VALUES ('arch','arch','Architecture name');
+
+
+CREATE TABLE bin_pkg (
+       id SERIAL PRIMARY KEY,
+       pkg TEXT NOT NULL UNIQUE
+);
+INSERT INTO table_comments VALUES ('bin_pkg','Binary packages');
+INSERT INTO column_comments VALUES ('bin_pkg','id','Binary package id');
+INSERT INTO column_comments VALUES ('bin_pkg','pkg','Binary package name');
+
+
+CREATE TABLE bin_ver(
+       id SERIAL PRIMARY KEY,
+       bin_pkg INT NOT NULL REFERENCES bin_pkg
+            ON UPDATE CASCADE ON DELETE CASCADE,
+       src_ver_id INT NOT NULL REFERENCES src_ver
+            ON UPDATE CASCADE ON DELETE CASCADE,
+       arch_id INT NOT NULL REFERENCES arch
+                   ON UPDATE CASCADE ON DELETE CASCADE,
+       ver public.debversion NOT NULL
+);
+CREATE INDEX bin_ver_ver_idx ON bin_ver(ver);
+CREATE UNIQUE INDEX bin_ver_bin_pkg_id_arch_idx ON bin_ver(bin_pkg,arch_id,ver);
+CREATE UNIQUE INDEX bin_ver_src_ver_id_arch_idx ON bin_ver(src_ver_id,arch_id);
+CREATE INDEX bin_ver_bin_pkg_id_idx ON bin_ver(bin_pkg);
+CREATE INDEX bin_ver_src_ver_id_idx ON bin_ver(src_ver_id);
+INSERT INTO table_comments VALUES ('bin_ver','Binary versions');
+INSERT INTO column_comments VALUES ('bin_ver','id','Binary version id');
+INSERT INTO column_comments VALUES ('bin_ver','bin_pkg','Binary package id (matches bin_pkg)');
+INSERT INTO column_comments VALUES ('bin_ver','src_ver_id','Source version (matchines src_ver)');
+INSERT INTO column_comments VALUES ('bin_ver','arch_id','Architecture id (matches arch)');
+INSERT INTO column_comments VALUES ('bin_ver','ver','Binary version');
+
+CREATE TABLE tag (
+       id SERIAL PRIMARY KEY,
+       tag TEXT NOT NULL UNIQUE,
+       obsolete BOOLEAN DEFAULT FALSE
+);
+INSERT INTO table_comments VALUES ('tag','Bug tags');
+INSERT INTO column_comments VALUES ('tag','id','Tag id');
+INSERT INTO column_comments VALUES ('tag','tag','Tag name');
+INSERT INTO column_comments VALUES ('tag','obsolete','Whether a tag is obsolete (should not be set on new bugs)');
+
+CREATE TABLE bug_tag (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug,
+       tag INT NOT NULL REFERENCES tag
+);
+INSERT INTO table_comments VALUES ('bug_tag','Bug <-> tag mapping');
+INSERT INTO column_comments VALUES ('bug_tag','bug','Bug id (matches bug)');
+INSERT INTO column_comments VALUES ('bug_tag','tag','Tag id (matches tag)');
+
+CREATE UNIQUE INDEX bug_tag_bug_tag_id ON bug_tag (bug,tag);
+CREATE INDEX bug_tag_tag_id ON bug_tag (tag);
+CREATE INDEX bug_tag_bug_id ON bug_tag (bug);
+
+
+
+CREATE TABLE bug_binpackage (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug,
+       bin_pkg INT NOT NULL REFERENCES bin_pkg
+);
+CREATE UNIQUE INDEX bug_binpackage_id_pkg_id ON bug_binpackage(bug,bin_pkg);
+INSERT INTO table_comments VALUES ('bug_binpackage','Bug <-> binary package mapping');
+INSERT INTO column_comments VALUES ('bug_binpackage','bug','Bug id (matches bug)');
+INSERT INTO column_comments VALUES ('bug_binpackage','bin_pkg','Binary package id (matches bin_pkg)');
+
+CREATE TABLE bug_srcpackage (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug,
+       src_pkg INT NOT NULL REFERENCES src_pkg ON UPDATE CASCADE ON DELETE CASCADE
+);
+CREATE UNIQUE INDEX bug_srcpackage_id_pkg_id ON bug_srcpackage(bug,src_pkg);
+INSERT INTO table_comments VALUES ('bug_srcpackage','Bug <-> source package mapping');
+INSERT INTO column_comments VALUES ('bug_srcpackage','bug','Bug id (matches bug)');
+INSERT INTO column_comments VALUES ('bug_srcpackage','src_pkg','Source package id (matches src_pkg)');
+
+CREATE VIEW bug_package (bug,pkg_id,pkg_type,package) AS
+       SELECT b.bug,b.bin_pkg,'binary',bp.pkg FROM bug_binpackage b JOIN bin_pkg bp ON bp.id=b.bin_pkg UNION
+              SELECT s.bug,s.src_pkg,'source',sp.pkg FROM bug_srcpackage s JOIN src_pkg sp ON sp.id=s.src_pkg;
+
+CREATE VIEW binary_versions (src_pkg, src_ver, bin_pkg, arch, bin_ver) AS
+       SELECT sp.pkg AS src_pkg, sv.ver AS src_ver, bp.pkg AS bin_pkg, a.arch AS arch, b.ver AS bin_ver,
+       svb.ver AS src_ver_based_on, spb.pkg AS src_pkg_based_on
+       FROM bin_ver b JOIN arch a ON b.arch_id = a.id
+                             JOIN bin_pkg bp ON b.bin_pkg  = bp.id
+                      JOIN src_ver sv ON b.src_ver_id  = sv.id
+                      JOIN src_pkg sp ON sv.src_pkg = sp.id
+                      LEFT OUTER JOIN src_ver svb ON sv.based_on = svb.id
+                      LEFT OUTER JOIN src_pkg spb ON spb.id = svb.src_pkg;
+
+CREATE TABLE suite (
+       id SERIAL PRIMARY KEY,
+       suite_name TEXT NOT NULL UNIQUE,
+       version TEXT,
+       codename TEXT,
+       active BOOLEAN DEFAULT TRUE);
+CREATE INDEX ON suite(codename);
+CREATE INDEX ON suite(version);
+INSERT INTO table_comments VALUES ('suite','Debian Release Suite (stable, testing, etc.)');
+INSERT INTO column_comments VALUES ('suite','id','Suite id');
+INSERT INTO column_comments VALUES ('suite','suite_name','Suite name');
+INSERT INTO column_comments VALUES ('suite','version','Suite version; NULL if there is no appropriate version');
+INSERT INTO column_comments VALUES ('suite','codename','Suite codename');
+INSERT INTO column_comments VALUES ('suite','active','TRUE if the suite is still accepting uploads');
+
+CREATE TABLE bin_associations (
+       id SERIAL PRIMARY KEY,
+       suite INT NOT NULL REFERENCES suite ON DELETE CASCADE ON UPDATE CASCADE,
+       bin INT NOT NULL REFERENCES bin_ver ON DELETE CASCADE ON UPDATE CASCADE,
+       created TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
+       modified TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
+);
+INSERT INTO table_comments VALUES ('bin_associations','Binary <-> suite associations');
+INSERT INTO column_comments VALUES ('bin_associations','id','Binary <-> suite association id');
+INSERT INTO column_comments VALUES ('bin_associations','suite','Suite id (matches suite)');
+INSERT INTO column_comments VALUES ('bin_associations','bin','Binary version id (matches bin_ver)');
+INSERT INTO column_comments VALUES ('bin_associations','created','Time this binary package entered this suite');
+INSERT INTO column_comments VALUES ('bin_associations','modified','Time this entry was modified');
+
+CREATE TABLE src_associations (
+       id SERIAL PRIMARY KEY,
+       suite INT NOT NULL REFERENCES suite ON DELETE CASCADE ON UPDATE CASCADE,
+       source INT NOT NULL REFERENCES src_ver ON DELETE CASCADE ON UPDATE CASCADE,
+       created TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
+       modified TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
+);
+INSERT INTO table_comments VALUES ('src_associations','Source <-> suite associations');
+INSERT INTO column_comments VALUES ('src_associations','id','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('src_associations','suite','Suite id (matches suite)');
+INSERT INTO column_comments VALUES ('src_associations','source','Source version id (matches src_ver)');
+INSERT INTO column_comments VALUES ('src_associations','created','Time this source package entered this suite');
+INSERT INTO column_comments VALUES ('src_associations','modified','Time this entry was modified');
+
+
+
+CREATE TYPE bug_status_type AS ENUM ('pending','forwarded','pending-fixed','fixed','absent','done');
+CREATE TABLE bug_status_cache (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug ON DELETE CASCADE ON UPDATE CASCADE,
+       suite INT REFERENCES suite ON DELETE CASCADE ON UPDATE CASCADE,
+       arch INT REFERENCES arch ON DELETE CASCADE ON UPDATE CASCADE,
+       status bug_status_type NOT NULL,
+       modified TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
+       asof TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
+);
+CREATE UNIQUE INDEX ON bug_status_cache(bug,suite,arch);
+CREATE INDEX ON bug_status_cache(bug);
+CREATE INDEX ON bug_status_cache(status);
+INSERT INTO table_comments  VALUES ('bug_status_cache','Source <-> suite associations');
+INSERT INTO column_comments VALUES ('bug_status_cache','id','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','bug','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','suite','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','arch','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','status','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','modified','Source <-> suite association id');
+INSERT INTO column_comments VALUES ('bug_status_cache','asof','Source <-> suite association id');
+
+
+
+CREATE TABLE message (
+       id SERIAL PRIMARY KEY,
+       msgid TEXT,
+       from_complete TEXT,
+       from_addr TEXT,
+       to_complete TEXT,
+       to_addr TEXT,
+       subject TEXT NOT NULL DEFAULT '',
+       sent_date TIMESTAMP WITH TIME ZONE,
+       refs TEXT NOT NULL DEFAULT '',
+       spam_score FLOAT,
+       is_spam BOOLEAN DEFAULT FALSE
+);
+INSERT INTO table_comments VALUES ('message','Messages sent to bugs');
+INSERT INTO column_comments VALUES ('message','id','Message id');
+INSERT INTO column_comments VALUES ('message','msgid','Message id header');
+INSERT INTO column_comments VALUES ('message','from_complete','Complete from header of message');
+INSERT INTO column_comments VALUES ('message','from_addr','Address(es) of From: headers');
+INSERT INTO column_comments VALUES ('message','to_complete','Complete to header of message');
+INSERT INTO column_comments VALUES ('message','to_addr','Address(es) of To: header');
+INSERT INTO column_comments VALUES ('message','subject','Subject of the message');
+INSERT INTO column_comments VALUES ('message','sent_date','Time/date message was sent (from Date header)');
+INSERT INTO column_comments VALUES ('message','refs','Contents of References: header');
+INSERT INTO column_comments VALUES ('message','spam_score','Spam score from spamassassin');
+INSERT INTO column_comments VALUES ('message','is_spam','True if this message was spam and should not be shown');
+
+CREATE INDEX ON message(msgid);
+
+CREATE TABLE message_refs (
+       id SERIAL PRIMARY KEY,
+       message INT NOT NULL REFERENCES message ON DELETE CASCADE ON UPDATE CASCADE,
+       refs INT NOT NULL REFERENCES message ON DELETE CASCADE ON UPDATE CASCADE,
+       inferred BOOLEAN DEFAULT FALSE,
+       primary_ref BOOLEAN DEFAULT FALSE,
+       CONSTRAINT message_doesnt_reference_itself CHECK (message <> refs)
+);
+CREATE UNIQUE INDEX ON message_refs(message,refs);
+CREATE INDEX ON message_refs(refs);
+CREATE INDEX ON message_refs(message);
+INSERT INTO table_comments VALUES ('message_refs','Message references');
+INSERT INTO column_comments VALUES ('message_refs','message','Message id (matches message)');
+INSERT INTO column_comments VALUES ('message_refs','refs','Reference id (matches message)');
+INSERT INTO column_comments VALUES ('message_refs','inferred','TRUE if this message reference was reconstructed; primarily of use for messages which lack In-Reply-To: or References: headers');
+INSERT INTO column_comments VALUES ('message_refs','primary_ref','TRUE if this message->ref came from In-Reply-To: or similar.');
+
+
+
+CREATE TABLE correspondent_full_name(
+       id SERIAL PRIMARY KEY,
+       correspondent INT NOT NULL REFERENCES correspondent ON DELETE CASCADE ON UPDATE CASCADE,
+       full_name TEXT NOT NULL
+);
+CREATE UNIQUE INDEX ON correspondent_full_name(correspondent,full_name);
+
+INSERT INTO table_comments VALUES ('correspondent_full_name','Full names of BTS correspondents');
+INSERT INTO column_comments VALUES ('correspondent_full_name','id','Correspondent full name id');
+INSERT INTO column_comments VALUES ('correspondent_full_name','correpsondent','Correspondent ID (matches correspondent)');
+INSERT INTO column_comments VALUES ('correspondent_full_name','full_name','Correspondent full name (includes e-mail address)');
+
+CREATE TYPE message_correspondent_type AS ENUM ('to','from','envfrom','cc');
+
+CREATE TABLE message_correspondent (
+       id SERIAL PRIMARY KEY,
+       message INT NOT NULL REFERENCES message ON DELETE CASCADE ON UPDATE CASCADE,
+       correspondent INT NOT NULL REFERENCES correspondent ON DELETE CASCADE ON UPDATE CASCADE,
+       correspondent_type message_correspondent_type NOT NULL DEFAULT 'to'
+);
+INSERT INTO table_comments VALUES ('message_correspondent','Linkage between correspondent and message');
+INSERT INTO column_comments VALUES ('message_correspondent','message','Message id (matches message)');
+INSERT INTO column_comments VALUES ('message_correspondent','correspondent','Correspondent (matches correspondent)');
+INSERT INTO column_comments VALUES ('message_correspondent','correspondent_type','Type of correspondent (to, from, envfrom, cc, etc.)');
+
+CREATE UNIQUE INDEX ON message_correspondent(message,correspondent,correspondent_type);
+CREATE INDEX ON message_correspondent(correspondent);
+CREATE INDEX ON message_correspondent(message);
+
+CREATE TABLE bug_message (
+       id SERIAL PRIMARY KEY,
+       bug INT NOT NULL REFERENCES bug ON DELETE CASCADE ON UPDATE CASCADE,
+       message INT NOT NULL REFERENCES message ON DELETE CASCADE ON UPDATE CASCADE,
+       message_number INT NOT NULL,
+       bug_log_offset INT,
+       offset_valid TIMESTAMP WITH TIME ZONE
+);
+INSERT INTO table_comments VALUES ('bug_mesage','Mapping between a bug and a message');
+INSERT INTO column_comments VALUES ('bug_message','bug','Bug id (matches bug)');
+INSERT INTO column_comments VALUES ('bug_message','message','Message id (matches message)');
+INSERT INTO column_comments VALUES ('bug_message','message_number','Message number in the bug log');
+INSERT INTO column_comments VALUES ('bug_message','bug_log_offset','Byte offset in the bug log');
+INSERT INTO column_comments VALUES ('bug_message','offset_valid','Time offset was valid');
+