Closer to what will be the final version

Index: Makefile
===================================================================
RCS file: /cvs/ports/databases/sqlports/Makefile,v
retrieving revision 1.10
diff -u -p -r1.10 Makefile
--- Makefile    15 Sep 2007 22:27:39 -0000      1.10
+++ Makefile    18 Aug 2008 11:25:55 -0000
@@ -1,28 +1,35 @@
 # $OpenBSD: Makefile,v 1.10 2007/09/15 22:27:39 simon Exp $
 
-CATEGORIES=    databases
-DISTNAME=      sqlports-0.5
-PKGNAME=       ${DISTNAME}p0
-DISTFILES=
-COMMENT=       sqlite database of ports
-MAINTAINER=    Marc Espie <[EMAIL PROTECTED]>
-
-PERMIT_PACKAGE_CDROM=  Yes
-PERMIT_PACKAGE_FTP=    Yes
-PERMIT_DISTFILES_CDROM=        Yes
-PERMIT_DISTFILES_FTP=  Yes
+CATEGORIES =           databases
+V =                    1.0
+DISTNAME =             sqlports-$V
+DISTFILES =
+COMMENT =              sqlite database of ports
+COMMENT-main =         ${COMMENT}, user version
+COMMENT-compact =      ${COMMENT}, program version
+MAINTAINER =           Marc Espie <[EMAIL PROTECTED]>
+FULLPKGNAME-compact =  sqlports-compact-$V
+FULLPKGNAME-main =     sqlports-$V
 
-DBNAME=        ${WRKBUILD}/sqlports
+
+PERMIT_PACKAGE_CDROM = Yes
+PERMIT_PACKAGE_FTP =   Yes
+PERMIT_DISTFILES_CDROM =Yes
+PERMIT_DISTFILES_FTP = Yes
+MULTI_PACKAGES =       -main -compact
+
+DBNAME =               ${WRKBUILD}/sqlports
 
 do-build:
-       cd ${PORTSDIR} && ${MAKE} dump-vars| \
+       cd ${PORTSDIR} && ${MAKE} dump-vars NO_IGNORE=Yes| \
        perl ${FILESDIR}/mksqlitedb ${DBNAME}
 
 do-install:
        ${INSTALL_DATA} ${DBNAME} ${PREFIX}/share
+       ${INSTALL_DATA} ${DBNAME}-compact ${PREFIX}/share
 
-BUILD_DEPENDS= ::databases/p5-DBD-SQLite
-NO_REGRESS=    Yes
-NO_CHECKSUM=   Yes
+BUILD_DEPENDS =                ::databases/p5-DBD-SQLite
+NO_REGRESS =           Yes
+NO_CHECKSUM =          Yes
 
 .include <bsd.port.mk>
Index: files/mksqlitedb
===================================================================
RCS file: /cvs/ports/databases/sqlports/files/mksqlitedb,v
retrieving revision 1.4
diff -u -p -r1.4 mksqlitedb
--- files/mksqlitedb    27 Dec 2006 11:16:10 -0000      1.4
+++ files/mksqlitedb    18 Aug 2008 11:25:55 -0000
@@ -22,6 +22,9 @@
 
 use strict;
 use warnings;
+use Getopt::Std;
+
+our ($opt_v);
 
 sub words($)
 {
@@ -31,6 +34,262 @@ sub words($)
        return split(/\s+/, $v);
 }
 
+package AbstractInserter;
+# this is the object to use to put stuff into the db...
+sub new
+{
+       my ($class, $db, $i) = @_;
+       bless {db => $db, transaction => 0, threshold => $i, vars => {}, done 
=> {} }, $class;
+}
+
+sub set
+{
+       my ($self, $ref) = @_;
+       $self->{ref} = $ref;
+}
+
+sub db
+{
+       return shift->{db};
+}
+
+sub last_id
+{
+       return shift->db->func('last_insert_rowid');
+}
+
+sub insert_done
+{
+       my $self = shift;
+       if ($self->{transaction}++ % $self->{threshold} == 0) {
+               $self->db->commit;
+       }
+}
+
+sub new_table
+{
+       my ($self, $name, @cols) = @_;
+
+       return if defined $self->{done}->{$name};
+
+       $self->db->do("DROP TABLE IF EXISTS $name");
+       print "CREATE TABLE $name (".join(', ', @cols).")\n" if $main::opt_v;
+       $self->db->do("CREATE TABLE $name (".join(', ', @cols).")");
+       $self->{done}->{$name} = 1;
+}
+
+sub prepare
+{
+       my ($self, $s) = @_;
+       return $self->db->prepare($s);
+}
+
+sub finish_port
+{
+       my $self = shift;
+       my @values = ($self->ref);
+       for my $i (@{$self->{varlist}}) {
+               push(@values, $self->{vars}->{$i});
+       }
+       $self->{insert_ports}->execute(@values);
+       $self->{vars} = {};
+}
+
+sub addports
+{
+       my ($self, $var, $value) = @_;
+       $self->{vars}->{$var} = $value;
+}
+
+sub create_tables
+{
+       my ($self, $vars) = @_;
+
+       $self->db->commit;
+       $self->new_table("Ports", $self->pathref." PRIMARY KEY", map {$_." 
".$vars->{$_}->sqltype } sort @{$self->{varlist}});
+       $self->{insert_ports} = $self->prepare("INSERT OR REPLACE INTO Ports (".
+           join(", ", "FULLPKGPATH", @{$self->{varlist}}).") VALUES (".
+           join(", ", "?", map {'?'} @{$self->{varlist}}).")");
+       $self->{insert_pathkey} = $self->prepare("INSERT OR REPLACE INTO Paths 
(FULLPKGPATH, PKGPATH) VALUES (?, ?)");
+}
+
+sub ref
+{
+       return shift->{ref};
+}
+
+package CompactInserter;
+our @ISA=(qw(AbstractInserter));
+
+our $c = {
+       Library => 0,
+       Run => 1,
+       Build => 2,
+       Regress => 3
+};
+
+sub convert_depends
+{
+       my ($self, $value) = @_;
+       return $c->{$value};
+}
+
+
+sub pathref
+{
+       return "FULLPKGPATH INTEGER NOT NULL";
+}
+
+sub create_tables
+{
+       my ($self, $vars) = @_;
+       # create the various tables, dropping old versions
+
+       my @keys;
+
+       while (my ($name, $class) = each %$vars) {
+               if (!defined( $class->table() )) {
+                       push(@keys, $name." ".$class->sqltype);
+                       push(@{$self->{varlist}}, $name);
+               }
+               $class->create_table($self);
+       }
+
+       $self->new_table("Paths", "ID INTEGER PRIMARY KEY", "FULLPKGPATH TEXT 
NOT NULL UNIQUE", "PKGPATH INTEGER");
+       $self->SUPER::create_tables($vars);
+       $self->{find_pathkey} =  $self->prepare("SELECT ID From Paths WHERE 
FULLPKGPATH=(?)");
+       $self->SUPER::create_tables($vars);
+}
+
+sub find_pathkey
+{
+       my ($self, $key) = @_;
+
+       if ($key eq '') {
+               print STDERR "Empty pathkey\n";
+               return 0;
+       }
+
+       # get pathkey for existing value
+       $self->{find_pathkey}->execute($key);
+       my $z = $self->{find_pathkey}->fetchrow_arrayref;
+       if (!defined $z) {
+               # if none, we create one
+               my $path = $key;
+               $path =~ s/\,.*//;
+               if ($path ne $key) {
+                       $path = $self->find_pathkey($path);
+               } else {
+                       $path = undef;
+               }
+               $self->{insert_pathkey}->execute($key, $path);
+               $self->insert_done;
+               return $self->last_id;
+       } else {
+               return $z->[0];
+       }
+}
+
+sub set_newkey
+{
+       my ($self, $key) = @_;
+
+       $self->set($self->find_pathkey($key));
+}
+
+sub find_keyword_id
+{
+       my ($self, $key, $t) = @_;
+       $self->{$t}->{find_key1}->execute($key);
+       my $a = $self->{$t}->{find_key1}->fetchrow_arrayref;
+       if (!defined $a) {
+               $self->{$t}->{find_key2}->execute($key);
+               $self->insert_done;
+               return $self->last_id;
+       } else {
+               return $a->[0];
+       }
+}
+
+sub create_keyword_table
+{
+       my ($self, $t) = @_;
+       $self->new_table($t,
+           "KEYREF INTEGER PRIMARY KEY AUTOINCREMENT", 
+           "VALUE TEXT NOT NULL UNIQUE");
+       $self->{$t}->{find_key1} = $self->prepare("SELECT KEYREF FROM $t WHERE 
VALUE=(?)");
+       $self->{$t}->{find_key2} = $self->prepare("INSERT INTO $t (VALUE) 
VALUES (?)");
+}
+
+package NormalInserter;
+our @ISA=(qw(AbstractInserter));
+
+our $c = {
+       Library => 'L',
+       Run => 'R',
+       Build => 'B',
+       Regress => 'Regress'
+};
+
+sub convert_depends
+{
+       my ($self, $value) = @_;
+       return $c->{$value};
+}
+
+sub create_tables
+{
+       my ($self, $vars) = @_;
+       # create the various tables, dropping old versions
+
+       my @keys;
+
+       while (my ($name, $class) = each %$vars) {
+               push(@keys, $name." ".$class->sqltype);
+               push(@{$self->{varlist}}, $name);
+               $class->create_table($self);
+       }
+
+       $self->new_table("Paths", "FULLPKGPATH TEXT NOT NULL PRIMARY KEY", 
"PKGPATH TEXT NOT NULL");
+       $self->SUPER::create_tables($vars);
+
+}
+
+sub pathref
+{
+       return "FULLPKGPATH TEXT NOT NULL";
+}
+
+sub set_newkey
+{
+       my ($self, $key) = @_;
+
+       my $path = $key;
+       $path =~ s/\,.*//;
+       $self->{insert_pathkey}->execute($key, $path);
+       $self->set($key);
+       $self->insert_done;
+}
+
+sub find_pathkey
+{
+       my ($self, $key) = @_;
+
+       return $key;
+}
+
+# no keyword for this dude
+sub find_keyword_id
+{
+       my ($self, $key, $t) = @_;
+       return $key;
+}
+
+sub create_keyword_table
+{
+       my ($self, $t) = @_;
+}
+
 # use a Template Method approach to store the variable values.
 
 # rule: we store each value in the main table, after converting YesNo
@@ -38,11 +297,92 @@ sub words($)
 # to store them in secondary tables (because of one/many associations).
 
 package AnyVar;
+sub new
+{
+       my ($class, $var, $value) = @_;
+       bless [$var, $value], $class;
+}
+
+sub var
+{
+       return shift->[0];
+}
+
+sub value
+{
+       return shift->[1];
+}
+
+sub add
+{
+       my ($self, $ins) = @_;
+       $ins->addports($self->var, $self->value);
+}
+
+sub addvalue
+{
+       my ($self, $ins, $value) = @_;
+       $ins->addports($self->var, $value);
+}
+
+sub sqltype()
+{
+       return "TEXT";
+}
+
+sub table()
+{
+       return undef;
+}
+
+sub keyword
+{
+       my ($self, $ins, $value) = @_;
+       return $ins->find_keyword_id($value, $self->keyword_table);
+}
+
+# by default, there's no separate table
+sub create_table
+{
+}
+
+sub keyword_table()
+{
+       return "Keywords";
+}
+
+package KeyVar;
+our @ISA=(qw(AnyVar));
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       my $stmt=$db->prepare("UPDATE Ports SET $var=(?) WHERE RowID=(?)");
-       $stmt->execute($value, $rowid);
+       my ($self, $ins) = @_;
+       $self->SUPER::addvalue($ins, $self->keyword($ins, $self->value));
+}
+
+sub sqltype()
+{
+       return "INTEGER NOT NULL";
+}
+
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->create_keyword_table($self->keyword_table);
+}
+
+package OptKeyVar;
+our @ISA=(qw(KeyVar));
+sub add
+{
+       my ($self, $ins) = @_;
+       if ($self->value ne '') {
+               $self->SUPER::add($ins);
+       }
+}
+
+sub sqltype()
+{
+       return "INTEGER";
 }
 
 package YesNoVar;
@@ -50,8 +390,13 @@ our @ISA=(qw(AnyVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       $class->SUPER::add($pkgpath, $db, $var, $value =~ m/^Yes/i ? 1 : undef, 
$rowid);
+       my ($self, $ins) = @_;
+       $self->SUPER::addvalue($ins, $self->value =~ m/^Yes/i ? 1 : undef);
+}
+
+sub sqltype()
+{
+       return "INTEGER";
 }
 
 # variable is always defined, but we don't need to store empty values.
@@ -60,9 +405,9 @@ our @ISA=(qw(AnyVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       return if $value eq '';
-       $class->SUPER::add($pkgpath, $db, $var, $value, $rowid);
+       my ($self, $ins) = @_;
+       return if $self->value eq '';
+       $self->SUPER::add($ins);
 }
 
 
@@ -70,55 +415,124 @@ sub add
 # end up being treated as WANTLIB as well.
 
 package DependsVar;
+our @ISA=(qw(AnyVar));
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       AnyVar->add($pkgpath, $db, $var, $value, $rowid);
-       for my $depends (main::words $value) {
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       for my $depends (main::words $self->value) {
                my ($libs, $pkgspec, $pkgpath2, $rest) = split(/\:/, $depends);
-               my $stmt = $db->prepare("INSERT INTO Depends (FULLPKGPATH, 
FULLDEPENDS, DEPENDSPATH, TYPE) VALUES (?, ?, ?, ?)");
-               $stmt->execute($pkgpath, $depends, $pkgpath2, $class->type());
+               my $stmt = $ins->prepare("INSERT OR REPLACE INTO Depends 
(FULLPKGPATH, FULLDEPENDS, DEPENDSPATH, TYPE, PKGSPEC, REST) VALUES (?, ?, ?, 
?, ?, ?)");
+               $stmt->execute($ins->ref, $depends, 
$ins->find_pathkey($pkgpath2), $ins->convert_depends($self->depends_type), 
$pkgspec, $rest);
+               $ins->insert_done;
                if ($libs ne '') {
                        for my $lib (split(/\,/, $libs)) {
-                               $class->addlib($pkgpath, $db, $lib);
+                               $self->addlib($ins, $lib);
                        }
                }
        }
 }
 
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->new_table("Depends", $inserter->pathref, "FULLDEPENDS TEXT 
NOT NULL", "PKGSPEC TEXT" , "REST TEXT", "DEPENDSPATH TEXT NOT NULL", "TYPE 
TEXT NOT NULL");
+}
+
 sub addlib
 {
 }
 
+sub table()
+{
+       return "Depends";
+}
+
+sub sqltype()
+{
+       return "TEXT";
+}
+
 package LibDependsVar;
 our @ISA=(qw(DependsVar));
-sub type() { 'L' }
+sub depends_type() { 'Library' }
 
 sub addlib
 {
-       my ($class, $pkgpath, $db, $lib) = @_;
-       WantlibVar->addvalue($pkgpath, $db, $lib);
+       my ($self, $ins, $lib) = @_;
+       WantlibVar->addvalue($ins, $lib);
 }
 
 package RunDependsVar;
 our @ISA=(qw(DependsVar));
-sub type() { 'R' }
+sub depends_type() { 'Run' }
 
 package BuildDependsVar;
 our @ISA=(qw(DependsVar));
-sub type() { 'B' }
+sub depends_type() { 'Build' }
 
 package RegressDependsVar;
 our @ISA=(qw(DependsVar));
-sub type() { 'Regress' }
+sub depends_type() { 'Regress' }
 
-# Stuff that gets stored in another table as well
+# Stuff that gets stored in another table
 package SecondaryVar;
+our @ISA=(qw(AnyVar));
 sub addvalue
 {
-       my ($class, $pkgpath, $db, $value) = @_;
-       my $stmt = $db->prepare("INSERT OR REPLACE INTO ".$class->table." 
(FULLPKGPATH, VALUE) VALUES (?, ?)");
-       $stmt->execute($pkgpath, $value);
+       my ($self, $ins, $value) = @_;
+       my $stmt = $ins->prepare("INSERT OR REPLACE INTO ".$self->table." 
(FULLPKGPATH, VALUE) VALUES (?, ?)");
+       $stmt->execute($ins->ref, $value);
+       $ins->insert_done;
+}
+
+sub addkeyword
+{
+       my ($self, $ins, $value) = @_;
+       $self->addvalue($ins, $self->keyword($ins, $value));
+}
+
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->new_table($self->table, $inserter->pathref, 
+           "VALUE TEXT NOT NULL", "UNIQUE(FULLPKGPATH, VALUE)");
+       KeyVar::create_table($self, $inserter);
+}
+
+sub keyword_table()
+{
+       return "Keywords";
+}
+sub sqltype() { "TEXT" }
+
+package MasterSitesVar;
+our @ISA=(qw(AnyVar));
+sub add
+{
+       my ($self, $ins) = @_;
+
+       my $stmt = $ins->prepare("INSERT OR REPLACE INTO ".$self->table." 
(FULLPKGPATH, N, VALUE) VALUES (?, ?, ?)");
+
+       my $n;
+       if ($self->var =~ m/^MASTER_SITES(\d)$/) {
+               $n = $1;
+       }
+       $stmt->execute($ins->ref, $n, $self->value);
+       $ins->insert_done;
+}
+
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->new_table($self->table, $inserter->pathref, 
+           "N INTEGER", "VALUE TEXT NOT NULL", "UNIQUE(FULLPKGPATH, N, 
VALUE)");
+       KeyVar::create_table($self, $inserter);
+}
+
+sub table()
+{
+       return "MasterSites";
 }
 
 # Generic handling for any blank-separated list
@@ -127,10 +541,22 @@ our @ISA=(qw(SecondaryVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       AnyVar->add($pkgpath, $db, $var, $value, $rowid);
-       for my $d (main::words $value) {
-               $class->addvalue($pkgpath, $db, $d) if $d ne '';
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       for my $d (main::words $self->value) {
+               $self->addvalue($ins, $d) if $d ne '';
+       }
+}
+
+package ListKeyVar;
+our @ISA=(qw(SecondaryVar));
+
+sub add
+{
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       for my $d (main::words $self->value) {
+               $self->addkeyword($ins, $d) if $d ne '';
        }
 }
 
@@ -139,9 +565,9 @@ our @ISA=(qw(SecondaryVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       AnyVar->add($pkgpath, $db, $var, $value, $rowid);
-       my @l = (main::words $value);
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       my @l = (main::words $self->value);
        while (my $v = shift @l) {
                while ($v =~ m/^[^']*\'[^']*$/ || $v =~m/^[^"]*\"[^"]*$/) {
                        $v.=' '.shift @l;
@@ -152,38 +578,52 @@ sub add
                if ($v =~ m/^\'(.*)\'$/) {
                    $v = $1;
                }
-               $class->addvalue($pkgpath, $db, $v) if $v ne '';
+               $self->addvalue($ins, $v) if $v ne '';
        }
 }
 
-package DefinedListVar;
-our @ISA=(qw(ListVar));
+package DefinedListKeyVar;
+our @ISA=(qw(ListKeyVar));
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       return if $value eq '';
-       $class->SUPER::add($pkgpath, $db, $var, $value, $rowid);
+       my ($self, $ins) = @_;
+       return if $self->value eq '';
+       $self->SUPER::add($ins);
 }
 
 package FlavorsVar;
-our @ISA=(qw(DefinedListVar));
+our @ISA=(qw(DefinedListKeyVar));
 sub table() { 'Flavors' }
 
+package PseudoFlavorsVar;
+our @ISA=(qw(DefinedListKeyVar));
+sub table() { 'PseudoFlavors' }
+
 package CategoriesVar;
-our @ISA=(qw(ListVar));
+our @ISA=(qw(ListKeyVar));
 sub table() { 'Categories' }
+sub keyword_table() { 'CategoryKeys' }
 
 package MultiVar;
 our @ISA=(qw(ListVar));
 sub table() { 'Multi' }
 
+sub add
+{
+       my ($self, $ins) = @_;
+       return if $self->value eq '-';
+       $self->SUPER::add($ins);
+}
+
 package ModulesVar;
-our @ISA=(qw(ListVar));
+our @ISA=(qw(ListKeyVar));
 sub table() { 'Modules' }
+sub keyword_table() { 'ModuleKeys' }
 
 package ConfigureVar;
-our @ISA=(qw(DefinedListVar));
+our @ISA=(qw(DefinedListKeyVar));
 sub table() { 'Configure' }
+sub keyword_table() { 'ConfigureKeys' }
 
 package ConfigureArgsVar;
 our @ISA=(qw(QuotedListVar));
@@ -192,27 +632,52 @@ sub table() { 'ConfigureArgs' }
 package WantlibVar;
 our @ISA=(qw(ListVar));
 sub table() { 'Wantlib' }
+sub _add
+{
+       my ($self, $ins, $value, $extra) = @_;
+       my $stmt = $ins->prepare("INSERT OR REPLACE INTO ".$self->table." 
(FULLPKGPATH, VALUE, EXTRA) VALUES (?, ?, ?)");
+       $stmt->execute($ins->ref, 
+           $self->keyword($ins, $value), $extra);
+       $ins->insert_done;
+}
+
 sub addvalue
 {
-       my ($class, $pkgpath, $db, $value) = @_;
-       $class->SUPER::addvalue($pkgpath, $db, $value);
-       if ($value =~ m/\.(?:\>?\=)?\d+\.\d+$/) {
-               $class->SUPER::addvalue($pkgpath, $db, $`);
-       } elsif ($value =~ m/\.(?:\>?\=)?\d+$/) {
-               $class->SUPER::addvalue($pkgpath, $db, $`);
+       my ($self, $ins, $value) = @_;
+       if ($value =~ m/^(.*)(\.(?:\>?\=)?\d+\.\d+)$/) {
+               $self->_add($ins, $1, $2);
+       } elsif ($value =~ m/^(.*)(\.(?:\>?\=)?\d+)$/) {
+               $self->_add($ins, $1, $2);
+       } else {
+               $self->_add($ins, $value, undef);
        }
 }
 
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->new_table($self->table, $inserter->pathref, 
+           "VALUE TEXT NOT NULL", "EXTRA TEXT", "UNIQUE(FULLPKGPATH, VALUE)");
+       KeyVar::create_table($self, $inserter);
+}
+
+sub keyword_table() { 'Library' }
+
+package OnlyForArchVar;
+our @ISA=(qw(QuotedListKeyVar));
+sub table() { 'OnlyForArch' }
+sub keyword_table() { 'Arches' }
+
 package FileVar;
 our @ISA=(qw(SecondaryVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       AnyVar->add($pkgpath, $db, $var, $value, $rowid);
-       open my $file, '<', $value or return;
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       open my $file, '<', $self->value or return;
        local $/ = undef;
-       $class->addvalue($pkgpath, $db, <$file>);
+       $self->addvalue($ins, <$file>);
 }
 
 sub table() { 'Descr' }
@@ -222,31 +687,79 @@ our @ISA=(qw(AnyVar));
 
 sub add
 {
-       my ($class, $pkgpath, $db, $var, $value, $rowid) = @_;
-       $class->SUPER::add($pkgpath, $db, $var, $value, $rowid);
-       my $stmt = $db->prepare("INSERT INTO Shared_Libs (FULLPKGPATH, LIBNAME, 
VERSION) VALUES (?, ?, ?)");
-       my %t = main::words($value);
+       my ($self, $ins) = @_;
+       $self->SUPER::add($ins);
+       my $stmt = $ins->prepare("INSERT OR REPLACE INTO Shared_Libs 
(FULLPKGPATH, LIBNAME, VERSION) VALUES (?, ?, ?)");
+       my %t = main::words($self->value);
        while (my ($k, $v) = each %t) {
-               $stmt->execute($pkgpath, $k, $v);
+               $stmt->execute($ins->ref, $self->keyword($ins, $k), $v);
+               $ins->insert_done;
        }
 }
 
+sub create_table
+{
+       my ($self, $inserter) = @_;
+       $inserter->new_table("Shared_Libs", $inserter->pathref, 
+           "LIBNAME TEXT NOT NULL", "VERSION TEXT NOT NULL", 
+           "UNIQUE (FULLPKGPATH, LIBNAME)");
+       KeyVar::create_table($self, $inserter);
+}
+
+sub table()
+{
+       "Shared_Libs"
+}
+
+sub keyword_table() 
+{
+       return "Library";
+}
+       
+package EmailVar;
+our @ISA=(qw(KeyVar));
+sub keyword_table()
+{
+       return "Email";
+}
+
+package YesKeyVar;
+our @ISA=(qw(KeyVar));
+sub keyword_table()
+{
+       return "Keywords2";
+}
+
+package AutoVersionVar;
+our @ISA=(qw(OptKeyVar));
+
+sub keyword_table()
+{
+       return "AutoVersion";
+}
 
 package main;
 
 use DBI;
 
+getopt('v');
 my $dbname;
 if (@ARGV > 0) {
        $dbname = shift;
 } else {
        $dbname = 'sqlports';
 }
+my @inserters;
 
 my $db =DBI->connect("dbi:SQLite:dbname=$dbname", '', '', {AutoCommit => 0});
+my $db2 =DBI->connect("dbi:SQLite:dbname=$dbname-compact", '', '', {AutoCommit 
=> 0});
+push(@inserters, NormalInserter->new($db, 1000));
+push(@inserters, CompactInserter->new($db2, 1000));
+
+
 my $vars = {
-    AUTOCONF_VERSION => 'AnyVar',
-    AUTOMAKE_VERSION => 'AnyVar',
+    AUTOCONF_VERSION => 'AutoVersionVar',
+    AUTOMAKE_VERSION => 'AutoVersionVar',
     BROKEN => 'AnyVar',
     BUILD_DEPENDS => 'BuildDependsVar',
     CATEGORIES=> 'CategoriesVar',
@@ -263,35 +776,35 @@ my $vars = {
     HOMEPAGE => 'AnyVar',
     IS_INTERACTIVE => 'AnyVar',
     LIB_DEPENDS => 'LibDependsVar',
-    MAINTAINER=> 'AnyVar',
-    MASTER_SITES => 'AnyVar',
-    MASTER_SITES0 => 'AnyVar',
-    MASTER_SITES1 => 'AnyVar',
-    MASTER_SITES2 => 'AnyVar',
-    MASTER_SITES3 => 'AnyVar',
-    MASTER_SITES4=> 'AnyVar',
-    MASTER_SITES5 => 'AnyVar',
-    MASTER_SITES6 => 'AnyVar',
-    MASTER_SITES7 => 'AnyVar',
-    MASTER_SITES8 => 'AnyVar',
-    MASTER_SITES9=> 'AnyVar',
+    MAINTAINER=> 'EmailVar',
+    MASTER_SITES => 'MasterSitesVar',
+    MASTER_SITES0 => 'MasterSitesVar',
+    MASTER_SITES1 => 'MasterSitesVar',
+    MASTER_SITES2 => 'MasterSitesVar',
+    MASTER_SITES3 => 'MasterSitesVar',
+    MASTER_SITES4=> 'MasterSitesVar',
+    MASTER_SITES5 => 'MasterSitesVar',
+    MASTER_SITES6 => 'MasterSitesVar',
+    MASTER_SITES7 => 'MasterSitesVar',
+    MASTER_SITES8 => 'MasterSitesVar',
+    MASTER_SITES9=> 'MasterSitesVar',
     MODULES => 'ModulesVar',
     MULTI_PACKAGES => 'MultiVar',
     NO_BUILD => 'YesNoVar',
     NO_REGRESS => 'YesNoVar',
     ONLY_FOR_ARCHS => 'AnyVar',
     PACKAGES => 'AnyVar',
-    PERMIT_DISTFILES_CDROM => 'AnyVar',
-    PERMIT_DISTFILES_FTP=> 'AnyVar',
-    PERMIT_PACKAGE_CDROM => 'AnyVar',
-    PERMIT_PACKAGE_FTP=> 'AnyVar',
+    PERMIT_DISTFILES_CDROM => 'YesKeyVar',
+    PERMIT_DISTFILES_FTP=> 'YesKeyVar',
+    PERMIT_PACKAGE_CDROM => 'YesKeyVar',
+    PERMIT_PACKAGE_FTP=> 'YesKeyVar',
     PKGNAME => 'AnyVar',
-    PKG_ARCH => 'AnyVar',
-    PSEUDO_FLAVORS => 'DefinedVar',
+    PKG_ARCH => 'KeyVar',
+    PSEUDO_FLAVORS => 'PseudoFlavorsVar',
     REGRESS_DEPENDS => 'RegressDependsVar',
     REGRESS_IS_INTERACTIVE => 'AnyVar',
     RUN_DEPENDS => 'RunDependsVar',
-    SEPARATE_BUILD => 'AnyVar',
+    SEPARATE_BUILD => 'YesKeyVar',
     SHARED_LIBS => 'SharedLibsVar',
     SHARED_ONLY => 'YesNoVar',
     SUBPACKAGE => 'DefinedVar',
@@ -303,37 +816,16 @@ my $vars = {
     WANTLIB => 'WantlibVar',
 };
 
-# create the various tables, dropping old versions
-
-for my $t (qw(Categories Flavors Multi Modules Configure ConfigureArgs 
Wantlib)) {
-    $db->do("DROP TABLE IF EXISTS $t");
-    $db->do("CREATE TABLE $t (FULLPKGPATH TEXT NOT NULL, VALUE TEXT NOT NULL, 
UNIQUE(FULLPKGPATH, VALUE))");
-}
-$db->do("DROP TABLE IF EXISTS Depends");
-$db->do("CREATE TABLE Depends (FULLPKGPATH TEXT NOT NULL, FULLDEPENDS TEXT NOT 
NULL, DEPENDSPATH TEXT NOT NULL, TYPE TEXT NOT NULL)");
-$db->do("DROP TABLE IF EXISTS Shared_Libs");
-$db->do("CREATE TABLE Shared_Libs (FULLPKGPATH TEXT NOT NULL, LIBNAME TEXT NOT 
NULL, VERSION TEXT NOT NULL, UNIQUE (FULLPKGPATH, LIBNAME))");
-$db->do("DROP TABLE IF EXISTS Ports");
-$db->do("CREATE TABLE Ports (FULLPKGPATH TEXT NOT NULL PRIMARY KEY, ".
-       join(',', (map {$_." TEXT"} (keys %$vars))).")");
-$db->do("DROP TABLE IF EXISTS Paths");
-$db->do("CREATE TABLE Paths (FULLPKGPATH TEXT NOT NULL PRIMARY KEY, PKGPATH 
TEXT NOT NULL)");
-$db->do("DROP TABLE IF EXISTS Descr");
-$db->do("CREATE TABLE Descr (FULLPKGPATH TEXT NOT NULL PRIMARY KEY, VALUE TEXT 
NOT NULL)");
-$db->commit();
-
-my $stmt = $db->prepare("SELECT RowID FROM Ports WHERE FULLPKGPATH=(?)");
-my $stmt2= $db->prepare("INSERT INTO Ports (FULLPKGPATH) VALUES (?)");
-my $stmt3= $db->prepare("INSERT INTO Paths (FULLPKGPATH, PKGPATH) VALUES (?, 
?)");
+for my $inserter (@inserters) {
+       $inserter->create_tables($vars);
+}
 
-my $i = 0;
-my $rowid;
 my $lastkey;
 while (<STDIN>) {
        chomp;
        # kill noise
        if (m/^\=\=\=/) {
-               print $_, "\n";
+               print "---", $_, "\n";
                next;
        }
        next unless m/^(.*?)\.([A-Z][A-Z_0-9]*)\=(.*)$/;
@@ -345,28 +837,23 @@ while (<STDIN>) {
        }
 
        if (!(defined $lastkey) || $key ne $lastkey) {
-               # get rowid for existing value
-               $stmt->execute($key);
-               my $z = $stmt->fetchall_arrayref;
-               if (@$z == 0) {
-                       # if none, we create one
-                       $stmt2->execute($key);
-                       my $path = $key;
-                       $path =~ s/\,.*//;
-                       $stmt3->execute($key, $path);
-                       $stmt->execute($key);
-                       $z = $stmt->fetchall_arrayref;
+               if (defined $lastkey) {
+                       for my $inserter (@inserters) {
+                               $inserter->finish_port;
+                       }
+               }
+               for my $inserter (@inserters) {
+                       $inserter->set_newkey($key);
                }
-               $rowid = $z->[0]->[0];
                $lastkey = $key;
        }
-       $vars->{$var}->add($key, $db, $var, $value, $rowid);
-
-       # and we commit just once every 1000 transactions, for efficiency
-       $i++;
-       if ($i % 1000 == 0) {
-               $db->commit();
+       my $v = $vars->{$var}->new($var, $value);
+       for my $inserter (@inserters) {
+               $v->add($inserter);
        }
 }
-$db->commit();
+for my $inserter (@inserters) {
+       $inserter->finish_port;
+       $inserter->db->commit;
+}
 
Index: pkg/DESCR
===================================================================
RCS file: pkg/DESCR
diff -N pkg/DESCR
--- pkg/DESCR   1 Aug 2006 16:22:22 -0000       1.4
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,74 +0,0 @@
-SQLite database of every port in the system. This can be queried through
-e.g., sqlitebrowser, or any kind of programming interface.
-
-Database Schema:
-- Ports(FULLPKGPATH, ...)
-holds all the information retrieved through various variables, e.g.,:
-    AUTOCONF_VERSION 
-    AUTOMAKE_VERSION 
-    BROKEN 
-    *DEPENDS 
-    CATEGORIES
-    COMMENT 
-    CONFIGURE_STYLE 
-    DESCR 
-    PACKAGING 
-    DISTFILES 
-    DISTNAME 
-    DIST_SUBDIR 
-    FLAVORS 
-    HOMEPAGE 
-    IS_INTERACTIVE 
-    MAINTAINER
-    MASTER_SITES*
-    MODULES 
-    MULTI_PACKAGES 
-    NO_*
-    ONLY_FOR_ARCHS 
-    PACKAGES 
-    PERMIT_*
-    PKGNAME 
-    PKG_ARCH 
-    PSEUDO_FLAVORS 
-    REGRESS_IS_INTERACTIVE 
-    RUN_DEPENDS 
-    SEPARATE_BUILD 
-    SHARED_LIBS 
-    SHARED_ONLY 
-    SUBPACKAGE 
-    SUPDISTFILES 
-    USE_*
-    WANTLIB 
-This information is mostly unchanged, except for replacing Yes/No variables
-with 1/0. Variables not present in a given port are left undefined.
-
-The FULLPKGPATH is complete, including flavors markers. For each port with
-MULTI_PACKAGES setting, another entry is written with PACKAGING set, and
-the correct SUBPACKAGE.  
-
-- Paths (FULLPKGPATH, PKGPATH)
-PKGPATH is the stripped down version or FULLPKGPATH, without flavors 
-or subpackage markers.
-
-- Flavors(FULLPKGPATH, VALUE)
-- Categories(FULLPKGPATH, VALUE)
-- Multi(FULLPKGPATH, VALUE)
-- Modules(FULLPKGPATH, VALUE)
-- Configure(FULLPKGPATH, VALUE)
-- ConfigureArgs(FULLPKGPATH, VALUE)
-All of these values are actually lists. After disassembling the list,
-one can find many entries in these secondary tables.
-
-- Depends(FULLPKGPATH, FULLDEPENDS, DEPENDSPATH, TYPE)
-All depends are stored in a single table, including the type:
-R -> run
-L -> lib
-B -> build
-Regress -> regress
-with FULLDEPENDS the full text of the dependency, and DEPENDSPATH the PKGPATH
-we depend upon.
-- Wantlib(FULLPKGPATH, VALUE)
-All the libraries the FULLPKGPATH depends upon, with and without version 
number,
-coming from either the WANTLIB variable or various LIB_DEPENDS.
-
-- Shared_Libs(FULLPKGPATH, LIBNAME, VERSION)
Index: pkg/DESCR-compact
===================================================================
RCS file: pkg/DESCR-compact
diff -N pkg/DESCR-compact
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pkg/DESCR-compact   18 Aug 2008 11:25:55 -0000
@@ -0,0 +1,91 @@
+SQLite database of every port in the system. This can be queried through
+e.g., sqlitebrowser, or any kind of programming interface.
+
+This schema is mostly optimized for tools, and cumbersome to query by
+hand.
+
+Database Schema:
+- Paths (ID, FULLPKGPATH, PKGPATH)
+PKGPATH points to a PATHS entry corresponding to the stripped down version of 
+FULLPKGPATH, without flavors or subpackage markers, or is null if FULLPKGPATH
+is already stripped.  Every other FULLPKGPATH, PKGPATH, DEPENDSPATH entry
+in the database points to this table.
+
+- Ports(FULLPKGPATH, ...)
+holds all the information retrieved through various variables that is not
+stored in specialized tables, e.g.,:
+    AUTOCONF_VERSION 
+    AUTOMAKE_VERSION 
+    BROKEN 
+    COMMENT 
+    DESCR 
+    PACKAGING 
+    DISTFILES 
+    DISTNAME 
+    DIST_SUBDIR 
+    FLAVORS 
+    HOMEPAGE 
+    IS_INTERACTIVE 
+    MAINTAINER
+    MULTI_PACKAGES 
+    NO_*
+    ONLY_FOR_ARCHS 
+    PACKAGES 
+    PERMIT_*
+    PKGNAME 
+    PKG_ARCH 
+    PSEUDO_FLAVORS 
+    REGRESS_IS_INTERACTIVE 
+    SEPARATE_BUILD 
+    SHARED_ONLY 
+    SUBPACKAGE 
+    SUPDISTFILES 
+    USE_*
+
+This information is mostly unchanged, except for replacing Yes/No variables
+with 1/0. Variables not present in a given port are left undefined.
+
+The FULLPKGPATH is complete, including flavors markers. For each port with
+MULTI_PACKAGES setting, another entry is written with PACKAGING set, and
+the correct SUBPACKAGE.
+
+- Flavors(FULLPKGPATH, VALUE)
+- PseudoFlavors(FULLPKGPATH, VALUE)
+- Categories(FULLPKGPATH, VALUE)
+- Multi(FULLPKGPATH, VALUE)            ('-' values are not stored)
+- Modules(FULLPKGPATH, VALUE)
+- Configure(FULLPKGPATH, VALUE)        (corresponds to CONFIGURE_STYLE)
+- ConfigureArgs(FULLPKGPATH, VALUE)
+- MasterSites(FULLPKGPATH, N, VALUE)
+All of these values are actually lists. After disassembling the list,
+one can find many entries in these secondary tables.
+
+
+Each keyword table follows the same scheme
+TABLENAME(KEYREF, VALUE)
+
+
+- Depends(FULLPKGPATH, FULLDEPENDS, PKGSPEC, REST, DEPENDSPATH, TYPE)
+All depends are stored in a single table, including the type:
+0 -> library
+1 -> run
+2 -> build
+3 -> regress
+with FULLDEPENDS the full text of the dependency, and DEPENDSPATH the key to
+the PKGPATH we depend upon.
+- Wantlib(FULLPKGPATH, VALUE, EXTRA)
+All the libraries the FULLPKGPATH depends upon, with and without version 
number,
+coming from either the WANTLIB variable or various LIB_DEPENDS.
+
+- Shared_Libs(FULLPKGPATH, LIBNAME, VERSION)
+
+Some information, both in the main table and in secondary tables 
+is stored as keyword references to other tables:
+AUTOCONF_VERSION, AUTOMAKE_VERSION -> AUTOVERSION
+MAINTAINER -> EMAIL
+CATEGORIES -> CATEGORYKEYS
+CONFIGURE -> CONFIGURE_KEYS
+MODULES -> MODULEKEYS
+WANTLIB.VALUE, SHARED_LIBS.LIBNAME -> LIBRARY
+PERMIT_*, SEPARATE_BUILD -> KEYWORDS2
+FLAVORS, PSEUDO_FLAVORS, PKG_ARCH -> KEYWORDS
Index: pkg/DESCR-main
===================================================================
RCS file: pkg/DESCR-main
diff -N pkg/DESCR-main
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pkg/DESCR-main      18 Aug 2008 11:25:55 -0000
@@ -0,0 +1,74 @@
+SQLite database of every port in the system. This can be queried through
+e.g., sqlitebrowser, or any kind of programming interface.
+
+Database Schema:
+- Ports(FULLPKGPATH, ...)
+holds all the information retrieved through various variables, e.g.,:
+    AUTOCONF_VERSION 
+    AUTOMAKE_VERSION 
+    BROKEN 
+    *DEPENDS 
+    CATEGORIES
+    COMMENT 
+    CONFIGURE_STYLE 
+    DESCR 
+    PACKAGING 
+    DISTFILES 
+    DISTNAME 
+    DIST_SUBDIR 
+    FLAVORS 
+    HOMEPAGE 
+    IS_INTERACTIVE 
+    MAINTAINER
+    MASTER_SITES*
+    MODULES 
+    MULTI_PACKAGES 
+    NO_*
+    ONLY_FOR_ARCHS 
+    PACKAGES 
+    PERMIT_*
+    PKGNAME 
+    PKG_ARCH 
+    PSEUDO_FLAVORS 
+    REGRESS_IS_INTERACTIVE 
+    RUN_DEPENDS 
+    SEPARATE_BUILD 
+    SHARED_LIBS 
+    SHARED_ONLY 
+    SUBPACKAGE 
+    SUPDISTFILES 
+    USE_*
+    WANTLIB 
+This information is mostly unchanged, except for replacing Yes/No variables
+with 1/0. Variables not present in a given port are left undefined.
+
+The FULLPKGPATH is complete, including flavors markers. For each port with
+MULTI_PACKAGES setting, another entry is written with PACKAGING set, and
+the correct SUBPACKAGE.  
+
+- Paths (FULLPKGPATH, PKGPATH)
+PKGPATH is the stripped down version or FULLPKGPATH, without flavors 
+or subpackage markers.
+
+- Flavors(FULLPKGPATH, VALUE)
+- Categories(FULLPKGPATH, VALUE)
+- Multi(FULLPKGPATH, VALUE)
+- Modules(FULLPKGPATH, VALUE)
+- Configure(FULLPKGPATH, VALUE)
+- ConfigureArgs(FULLPKGPATH, VALUE)
+All of these values are actually lists. After disassembling the list,
+one can find many entries in these secondary tables.
+
+- Depends(FULLPKGPATH, FULLDEPENDS, DEPENDSPATH, TYPE)
+All depends are stored in a single table, including the type:
+R -> run
+L -> lib
+B -> build
+Regress -> regress
+with FULLDEPENDS the full text of the dependency, and DEPENDSPATH the PKGPATH
+we depend upon.
+- Wantlib(FULLPKGPATH, VALUE)
+All the libraries the FULLPKGPATH depends upon, with and without version 
number,
+coming from either the WANTLIB variable or various LIB_DEPENDS.
+
+- Shared_Libs(FULLPKGPATH, LIBNAME, VERSION)
Index: pkg/PLIST
===================================================================
RCS file: pkg/PLIST
diff -N pkg/PLIST
--- pkg/PLIST   10 Jul 2006 10:57:59 -0000      1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,2 +0,0 @@
[EMAIL PROTECTED] $OpenBSD: PLIST,v 1.1.1.1 2006/07/10 10:57:59 espie Exp $
-share/sqlports
Index: pkg/PLIST-compact
===================================================================
RCS file: pkg/PLIST-compact
diff -N pkg/PLIST-compact
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pkg/PLIST-compact   18 Aug 2008 11:25:55 -0000
@@ -0,0 +1,2 @@
[EMAIL PROTECTED] $OpenBSD: PLIST,v 1.1.1.1 2006/07/10 10:57:59 espie Exp $
+share/sqlports-compact
Index: pkg/PLIST-main
===================================================================
RCS file: pkg/PLIST-main
diff -N pkg/PLIST-main
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ pkg/PLIST-main      18 Aug 2008 11:25:55 -0000
@@ -0,0 +1,2 @@
[EMAIL PROTECTED] $OpenBSD: PLIST,v 1.1.1.1 2006/07/10 10:57:59 espie Exp $
+share/sqlports

Reply via email to