package SetDB; use strict; use SetDB::Graph; use SetDB::Set; use Data::Dumper; =head1 NAME DBIx::SetDB - View a database the way the designer does, as sets. =head1 SYNOPSIS use strict; use DBI; use DBIx::SetDB; # Okay, first we set up our DBI connection my $dbi = DBI->connect( 'DBI:mysql:database=setdb_test;host=localhost', 'setdb', 'setdb'); # Now we set up our schema use vars qw( $schema ); do 'schema.pl'; # This creates our SetDB database my $db = new SetDB($dbi, $schema); # Lets get a set of people and their books my $people = $db->newSet('person', ['book'], ['address']); # Now loop through and print out each person while(my $person = $people->fetchNext()) { print "Name: $person->{name}\n"; # This is the set of books which that person has my $books = $person->{book}; # Lets go ahead and print all of their books while(my $book = $books->fetchNext()) { print " Book: $book->{title}\n"; # Demonstrate updates by adding ' sucks!' to the book's title $book->{title} .= ' sucks!'; } $books->restart(); # Lets go ahead and print all of their books while(my $book = $books->fetchNext()) { print " Book: $book->{title}\n"; } # This is the set of books which that person has my $addrs = $person->{address}; # Lets go ahead and print all of their books while(my $addr = $addrs->fetchNext()) { print " Street: $addr->{street}\n"; } } =head1 INTRODUCTION This package is an abstraction on top of DBI to view databases as sets of things (though it is also aware of relationships between the things). =head1 METHODS =over 4 =item $db = new SetDB create a new SetDB object =cut sub new { my $class = shift; my $dbi = shift; my $schema = shift; my $self = {}; bless $self, $class; $self->{dbi} = $dbi; $self->schema($schema); return $self; } =item $db->schema($new_schema) Get the schema. If a new schema is passed as a parameter than it replaces the existing schema. =cut sub schema { my $self = shift; if(my $new_schema = shift) { $self->{schema} = $self->getGraph($new_schema); } return $self->{schema}; } =item $db->newSet( ... ) This creates (and returns) a new set using the given definition (the yadda-yadda "..." stuff). See SetDB::Set::new( ... ) for a detailed discussion of the set-design notation stuff. =cut sub newSet { my $self = shift; my @sets = @_; my $set = new SetDB::Set($self, @sets); return $set; } =item $db->getGraph() Set up an undirected graph from a raw schema. Each edge is named with the equality that connects the two nodes. This is used by a set to infer connecting tables. =cut sub getGraph { my $self = shift; my %schema = %{shift @_}; my $graph = new SetDB::Graph(); # Each item in the schema will become a node foreach my $s (keys %schema) { # Add the node (or get a copy of the existing node) my $node1 = $graph->addNode($s); # Copy all the data from the schema into the node $node1->{data} = $schema{$s} # These will become edges my @refs = keys %{$schema{$s}{'refs'}}; my $key = $schema{$s}{'key'}; $key = 'id' unless $key; foreach my $r (@refs) { my $name = "$s.$r = $schema{$s}{'refs'}{$r}{'table'}.$key"; my $node2 = $graph->addNode($schema{$s}{'refs'}{$r}{'table'}); my $edge = $graph->addEdge($node1, $node2, $name); $edge->{data}{leftField} = $r; $edge->{data}{rightField} = $key; } } return $graph; } =back =head1 SEE ALSO SetDB::Set, SetDB::Tuple =head1 AUTHOR Brock Wilcox =head1 COPYRIGHT Copyright (c) 2004 Brock Wilcox . All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;