=pod

=head1 NAME

OBB - object-orient, model-building base class

=head1 SYNOPSIS

In package C<Some::Pack> :

  package Some::Pack ; use OBB ; our @ISA = qw(OBB) ;

  # make package globals

  __PACKAGE__ -> Mk_class_methods
    ( VERSION => undef
    , MY_GLOB => {}
    ) ;

    $version = VERSION ( '3.1' ) ;

Usage in C<main> or some other package :

  use Some::Pack ;
  $pack    = Some::Pack -> Make    ; # create an instance
  $version = Some::Pack -> Version ; # get a global

C<Some::Pack> :

   # make attribute methods

  __PACKAGE__ -> Mk_methods ( qw(name1 name2 name3) ) ;

  # in methods
    $self -> name1
    $self -> name1 ( $name )
    $self -> Debug # predicate ; get verbosity

C<main> :

  # get/set with access methods
    my $name = $pack -> name1 ;
    $pack -> name1 ( $name ) ;

  # get/set verbosity of a package
    Some::Pack -> Debug ;
    Some::Pack -> Verbose ( 1 ) ;
  # ... or an instance
    $pack -> Verbose     ;
    $pack -> Debug ( 1 ) ;

  # Dump
    $pack -> Dump
    print Pretty $pack ;
    print Inline $pack ;

=head1 DESCRIPTION

OBB is a I<base class> : it is used to augment functionality of
other packages.

About the notation :

=over 4

=item *

Symbol -> is Perl's C<%AR%> operator ;
symbol => is Perl's I<fat comma> 'C<%FC%>'.

=item *

Symbols (( and )) are used for grouping.

=item *

[[ I<a> ]] means : I<a> is optional.

=item *

(( I<a> || I<b> )) means : either I<a> or I<b>.

=back

So, [[ I<a> || I<b> ]] means : optionally, I<a> or I<b>.

Now some terminology :

=over 4

=item OBB-package

An I<OBB-package> is a package X which somehow
is a (@ISA) an OBB (responds to OBB methods).

=item OBB-instance

An I<OBB-instance> is an instance of an OBB-package.

=item OBB-object or I<obbject>

An I<OBB-object> (or I<obbject>) is an OBB-package or an OBB-instance.

=item class-method

A I<class-method> C<X::NAME()> gets/sets scalar C<$X::NAME>.

  # package X ; our $NAME ;
  # In other packages :
  get : X -> NAME
  set : X -> NAME ( $val )

=item access-method

An I<access-method> C<X::name()> gets/sets attribute C<name>
of instances of package C<X>.

  # $x is an instance of package X : $x = X -> Make ;
  get : $x -> name
  set : $x -> name ( $val )

=back

=head2 OBB object creation

=over 4

=item general

OBB objects may be created with OBB's method C<Make>,
which calls method C<New>, and then calls method C<Init>.

Method C<New> just creates the object, blessed into the right package ;
method C<Init> initialises the object with the attribute-values
supplied to C<Make>.

In general, do not redefine method C<Make>.
Redefine C<New> to create array-like OBB-objects (see C<New>).
Redefine C<Init> to customise objects.

=item C<Make ()>

  $new = $obbj -> Make ( [[ attr1 => val1, ... ]] )
  $new = $obbj -> Make ( $hashref )

OBB's method C<Make> creates an object C<$new>, blessed into package $obbj
(or C<ref $obbj> if C<$obbj> is a blessed reference) ; then, it calls
C<$new -> Init> with the arguments supplied.

C<Make> returns what C<Init> returns ; usually the created object.

=item C<New ()>

  $new = $obbj -> New

C<New> returns C<{}>, blessed into (the) package (of) C<$obbj>.

If you want a package I<X> with array-like objects,
then redefine C<New> in package I<X> :

  package X ;
  sub New { my $self = shift ; bless [], $self ; }

Note: you can't create access-methods for such a package.

=item C<Init ()>

  $new -> Init ( attr1 => val1, ... )
  $new -> Init ( $hashref )

C<Init> sets attributes I<attr1>, I<attr2>, ... of instance C<$new> using
those attributes C<$attr> for which C<$new> has an access-method :

  $new -> can ( $attr )

C<Init> returns the initialised object ;
it must return C<undef> on failure.

If you redefine method C<Init>, use C<SUPER::Init>
to access the I<original> C<Init> method ; example :

  # redefine Init
  sub Init
    { my $self = shift ;
      my %opts = @_ ;
      return undef unless $self -> SUPER::Init ( %opts ) ;
      # now do your thing
      # return $self or undef
    }

=back

=head2 Class- and access-methods

=over 4

=item C<$pack -> Mk_class_methods ( NAME1 => initial-value, ... )>

Method C<Mk_class_methods> creates class-methods
I<NAME1>, I<NAME2>, ... in package C<$pack>.

  package $pack ;
  our $NAME1 ;
  sub NAME1 { ... }
  ...

Class-method C<X::NAME> gets/sets scalar C<$X::NAME>.

If the initial value for a name I<NAME> is defined, it calls

  $pack -> NAME ( $initial_value )

Class-methods must have uppercase alpha-numeric names.

Method C<Mk_class_methods> throws a fatal error
if package-variable C<$X::NAME> already exists.

=item C<$pack -> Mk_methods ( name1, name2, ... [[, $sub ]] )>

=item C<$pack -> Mk_methods ( [ ... ] [[, $sub ]] )>

Method C<Mk_methods> creates access-methods
I<name1>, I<name2>, ... in package C<$pack>.

Access-method C<name> of an OBB-package C<$pack>
gets/sets attribute I<name> of instances of C<$pack>.

Access-methods must have (lowercase) alpha-numeric names.

Method C<Mk_methods> throws a fatal error for C<$name>,
if package C<$pack> already implements a method C<$name>.

You may supply a code-reference C<$sub> :

  $sub = sub { my ( $self, $attr [[, $val ]] ) = @_ ; .... }

The default C<$sub> is C<OBB::DEFAULT_ACCESS_METHOD> ;
a 2-argument call returns C<$self->{$attr}> ;
a 3-argument call sets C<$self->{$attr} = $val> first.

For example, to create access methods that return lists for array-refs
in list context :

  sub my_getset
    { my $res = OBB::DEFAULT_ACCESS_METHOD ( @_ ) ;
      ( wantarray and 'ARRAY' eq ref $res ) ? @$res : $res ;
    }

  MyPack -> Mk_methods ( qw(name1 name2), \&my_getset ) ;

=back

=head2 Verbosity

=over 4

=item C<OBB> verbosity-levels

OBB has I<verbosity-levels> :

   levels  == %LEVELS%
   default == %DEF_LVL%

These are I<levels> in the sense that I<high> → (implies) I<low> :

  %REVERSE%

For example :

  package X::Some_package ;

  sub some_method
    { ...
      if ( $error )
        { print $error if $self → Terse ;
          print $more  if $self → Verbose ;
          print $guts  if $self → Debug ;
        }
    }

If the verbosity of C<X> or C<X::Some_package> is set to C<Terse>,
only the C<$error> is printed ; if the verbosity is set to C<Debug>,
then C<$more> and C<$guts> are printed too.

So, it is easy (for instance) to turn on debugging for
(1) some instance of some package, or
(2) all instances of a package, or
(3) all instances of a package-tree.

=item C<My_verbosity ()>

Any obbject can have a I<verbosity-level> :

  get : $level = $obbj → My_verbosity
  set : $level = $obbj → My_verbosity ( $level )

For C<My_verbosity>, I<undef> is a proper argument or result.

You can also I<get> the verbosity with :

  $bool = $obbj → My_silent
  $bool = $obbj → My_quiet
  $bool = $obbj → My_terse
  $bool = $obbj → My_verbose
  $bool = $obbj → My_debug

... and I<set> the verbosity with :

  $bool = $obbj → My_silent ( $bool )
  ...
  $bool = $obbj → My_debug  ( $bool )

=item C<Verbosity ()>

Perhaps more useful is :

  $obbj → Verbosity

Function C<Verbosity> returns :

=over 4

=item *

C<$obbj -> My_verbosity>, if that is defined ;

=item *

otherwise, if C<$obbj> is I<blessed>, C<My_verbosity> of the class
(or a I<super-class>) of C<$obbj>, if that is defined ;
the I<classes> are searched in the usual (C<@ISA>) order.

=back

By default, C<Verbosity> returns the default verbosity,
so the result is always defined.

Function C<Verbosity> can be used to set the verbosity of an obbject :

  $obbj → Verbosity ( 'Debug' ) ;

Every level has an associated function to get/set a specific level :

  $bool = $obbj → Silent  [[ ($bool) ]]
  $bool = $obbj → Quiet   [[ ($bool) ]]
  $bool = $obbj → Terse   [[ ($bool) ]]
  $bool = $obbj → Verbose [[ ($bool) ]]
  $bool = $obbj → Debug   [[ ($bool) ]]

The I<verbosity> of an obbject isn't stored as an attribute,
so I<verbosity> also works for non-hash obbjects.

=item C<Set_verbosity ()>

Verbosity can be tied to a (GetOpt-like) option hash :

  $obbj → Set_verbosity ( 'q Quiet v Verbose d Debug', %opt )

The C<%opt> may have values for keys C<qw(q v d)> ; the first
key I<x> for which C<$opt{x}> is I<true>, sets the verbosity
of C<$obbj>.
If no C<$opt{x}> is I<true>, the verbosity of C<$obbj> is set
to the default-level.

=item C<Verbosity-levels ()>

=item C<Default_verbosity ()>

You can get/set the verbosity-levels of package C<$pack> :

   get : $pack → Verbosity_levels
   set : $pack → Verbosity_levels ( Name0, Name1, ... )

   get : $pack → Default_verbosity
   set : $pack → Default_verbosity ( $level )

By default, C<Default_verbosity> is C<Name0>.
The verbosity-functions I<Name0>, I<Name1> etc are
compiled into package C<$pack>.

=back

=head2 Printing

=over 4

=item C<Print ()>

=item C<Printf ()>

Methods C<Print> and C<Prinft> just C<print> and C<printf> ;
they can be re-defined in other OBB-packages.

=back

=head2 Dumping

=head3 package OBB::Dumper

You can format any value with a C<OBB::Dumper> :

  $dumper -> Text ( $value )

=over 4

=item * Attributes

An C<OBB::Dumper> uses the following attributes when formatting a C<$value>.
Defaults are shown as I<=> default>.

In this section, the I<contents> of a reference C<$r> is C<%$r> for hashrefs,
C<@$r> for arrayrefs and C<ref($r)> for anything else.

=over 4

=item pretty => 1

If B<pretty> is set, the dumper pretty-prints an indented tree ;
if not, the dumper returns a single, dense string.
See the C<Example> below.

=item tag => '%DTAG%'

Some string to identify the dumped value.
In B<pretty> dumps, the dumper uses the default if B<tag> is undefined.

=item prints => undef

If B<prints> is set, the dumper prints ;
if not defined, B<pretty> decides : B<pretty> strings are printed.
The dumper uses C<$object->Print> if applicable.

=item levels => undef

If defined, the dumper will only show attribute-values in
the first few levels of C<$value> (if any).
An attribute-value C<$val> at the maximum level is shown as C<ref($val)>.

When a dumper encounters a reference C<$r> for the first time,
it shows the contents of C<$r>.
When it re-visits C<$r>, it shows C<$r> as
an attribute/index-path to C<$r> :

  path $value     == 'root'
  path $r %AR% {$a} == path($r).$attr
  path $r %AR% [$i] == path($r).$i

=over 4

=item examples

A data-structure is I<recursive> if it contains a reference
to (some part of) itself ; for instance :

  %Exa1%

Or, more complicated :

  %Exa2%

=back

=item verbose => 0

Show ignored attributes as C<name : E<lt>ignoredE<gt>> ;
For sub-objects blessed in some class I<Class>, show the class.

=back

=item * Instance methods

A dumper C<$dumper> responds to the following methods :

=over 4

=item Text ( $value [[, $attr => val, ... ]] )

C<Text> returns the contents of C<$value> as a string.

=back

=item * Example

Here is a dump of OBB's I<Verbosity> data :

=over 4

=item * B<levels> == 0

References are shown as C<ref> I<attribute-value>.

  %%DUMP( OBB -> OBB_LEVELS, levels=>0 )%%

With C<pretty => 0, tag => undef> :

  %%DUMP( OBB -> OBB_LEVELS, levels=>0, pretty=>0, tag => undef )%%

=item * B<levels> == 1

Only the contents of level-1 attributes are shown ;
note the display of I<root->store->tabl>.

Note the display of I<root->store->base> :
it is a reference to I<root>.

  %%DUMP( OBB -> OBB_LEVELS, levels=>1 )%%

With C<pretty => 0> :

  %%DUMP( OBB -> OBB_LEVELS, levels=>1, pretty=>0 )%%

=back

=back

=head3 Dumping obbjects

=over 4

=item OBB -> DUMPER

OBB's class-method C<DUMPER> returns a new dumper.
By default this is a default dumper, but other
classes may return a pre-configured dumper.

Now, C<$x->DUMPER> returns a C<OBB::Dumper> object, if

=over 4

=item *

C<$x> is an obbject, or

=item *

C<$x> is blessed into a package that defines or inherits method C<DUMPER>.

=back

=item OBB -> Dump

  $obbject -> Dump [[ ( 'tag' ) ]]
  $obbject -> Dump ( %options )

C<Dump> :

=over 4

=item *

Sets C<$dumper> = $obbj -> DUMPER ;

=item *

possibly, set C<$dumper> options ;

=item *

returns the result of C<$dumper -> Dump ( $obbject )>.

=back

=back

=head3 OBB exports

OBB exports functions :

=over 4

=item C<Pretty ( $value [[, attr => $val, ... ]] )>

=item C<Inline ( $value [[, attr => $val, ... ]] )>

=back

By default, C<Pretty> prints and C<Inline> doesn't.
C<Inline> has ((B<pretty> => C<0>, B<tag> => C<''>)).

=head3 Dumping non-OBB-values

To dump a non-OBB-value C<$value>, use C<Inline> or C<Pretty>, or

  OBB -> DUMPER -> Text ( $value [[ options ]] )

Or define and use a C<$dumper> :

  my $dumper = OBB -> dumper ;
  sub dmp
    { my $val = shift ;
      my $tag = shift ;
      OBB -> DUMPER -> Text ( $val, tag => $tag ) ;
    }
  dmp $foo ;
  dmp $bar, 'my bar'

=head3 Hiding attributes

OBB-packages may want to hide (in dumps) certain attributes.
For instance if an object contains a pointer to a parent-object.
If/when a dumping such an object, you don't want to see the
I<contents> of the parent.

=over 4

=item C<OBB::Hide ( $pack, $attr, ... )>

In a package, hide attributes with :

  __PACKAGE__ -> Hide ( $attr, ... ) ;

C<Hide()> creates a class-method C<$pack::HIDES = { $attr => 1, ... }>.

=back

=head2 C<OBB::JSON>

Let's call a I<json> (or JSON-like object) a data structure that
consists of (unblessed) arrayrefs, hashrefs and non-ref scalars.

Now suppose you have to handle a bunch of jsons with the same structure ;
two jsons are I<similar> if they only differ in the I<value> of
the non-ref scalars and the I<length> of the arrays.

When given an example json C<$model>, OBB can create a C<Blesser> for
jsons similar to C<$model>.

=head3 Blessings : C<Mk_blesser>, C<Bless>

=over 4

=item C<Mk_blesser ( $model, $pack [[, key_map => {}, row_map => {} ]] )>

C<Mk_blesser> takes a json C<$model> and returns a C<OBB::JSON::Blesser>.

  $blesser = OBB -> Mk_blesser ( $model )

The C<$blesser> can a bless a C<$json> (similar to C<$model>) into
the class-tree C<$pack>.

  $blesser -> Bless ( $json )

=over 4

=item *

C<Mk_blesser> creates a class-tree (rooted at C<$pack>)
with a package-name for each arrayref and hashref in C<$model>.

=item *

For each arrayref, it creates a proper C<New> method,
which blesses C<[]> into the right package.

=item *

For each hashref (with keys C<$key1>, C<$key2>, ...),
it creates access-methods named I<key1>, I<key2> etc.

=back

Let's explain further details with an example.

Suppose we have a bunch of jsons which look like this :

  %%DUMP( $json, tag => '$json', verbose => 1 )%%

Similar jsons have a long list of I<{epoch,path,type}>-triples
in C<$json->{recent}>.

We now use C<json> as a template and create a C<Blesser> :

  my $blesser = OBB -> Mk_blesser
    ( $json, 'Foo', key_map => $key_map, row_map => $row_map) ;

Ignore C<key_map> and C<row_map> for now.

=item C<Bless ( $json )>

Using C<$blesser>, we can now C<Bless> a similar, unblessed json C<$sim>

  $blesser -> Bless ( $sim )

turning C<$sim> into :

  %%DUMP( $copy, tag => '$sim', verbose => 1 )%%

After the blessing, C<$sim> has some extra properties :

=over 4

=item package-tree

=over 4

=item *

C<$sim> is blessed into package C<Foo>,

=item *

C<$sim -> {meta}> is blessed into package C<Foo::meta>

=item *

C<$sim -> {meta}{Producers}> is blessed into package
C<Foo::meta::Producers> etc.

=back

=item access-methods

We can use access-methods on (sub)components :

=over 4

=item *

C<$sim -> meta [[($val)]]>

=item *

C<$sim -> meta -> Producers [[($val)]]>

=back

=item C<key_map>

When a hashref has a non-alphanumeric key, C<Mk_blesser> can be
provided with a C<key_map> :

  %%DUMP( OBB::JSON -> example_key_map, tag => 'key_map' )%%

Key C<$0> in C<$sim->{meta}{Producers}> is mapped to I<dollar0>:
Package C<Foo::meta::Producers> has access-method C<dollar0>.

=item C<row_map>

A row-element of a arrayref has no I<name> (only a I<index-number>) ;
we can name them (in the package-tree) using a C<row_map> :

  %%DUMP( OBB::JSON -> example_row_map )%%

The row-elements of arrayref C<$sim->{recent}> are blessed into package
C<Foo::recent::event>.

The default name for row-elements is I<elem>.

=back

=back

=head3 Using blessed jsons

Consider the Model–View–Controller (MVC) software architecture pattern.

In general, it is advisable to put functionality into the I<Model>.

If circumstances dictate that you have to use (bare) jsons as your model,
you can benefit from blessing them into a package-tree.

The package-tree enables you to treat components as I<objects>
and add functionality by extending the component's package.

In the example above, add a method to C<Foo::meta::minmax> with :

  package Foo::meta::minmax ;
  sub my_thing
    { my $self = shift ;
      # do your thing with $self -> min, $self -> max etc
    }

  # in your application use :
  $res = $json -> meta -> minmax -> my_thing

=head2 DBI database access

OBB enables you to use a database as a model, but you
must I<define> the database first by giving a description
of the database's tables and columns.

When you define a database I<Foo>, it is blessed into class
C<OBB::Dbs::Foo>.
Foo's tables are blessed into class C<OBB::Tab::Foo> ;
specifically, table I<bar> is blessed into C<OBB::Tab::Foo::bar>.

Foo's columns are blessed into class C<OBB::Col::Foo> ;
specifically, I<bar>'s columns are blessed into
(a subclass of) C<OBB::Col::Foo::bar>,
for instance C<OBB::Col::Foo::bar::my_col>.

So, I<defining> a database object gives you a detailed class
hierarchy, providing lots of hooks to add/change functionality
on many levels : all tables or a specific table,
all columns or all table-specific columns or a specific column,
all records or all table-specific records
etc.

=head3 C<Define_dbs ()>

Method C<OBB::Define_dbs ( $name )> creates a C<OBB::Dbs::I<$name>> object.

  $db = OBB -> Define_dbs ( 'Foo' )

C<$db> is a C<OBB::Dbs::Foo>, which is a C<OBB::Dbs>.

=head3 C<OBB::Dbs>

=head4 C<OBB::Dbs> attributes :

=over 4

=item * C<Dbh>

The database handle

=item * C<Tabs>

A list of C<OBB::Tab> (database table) objects.

=item * C<Tabl>

A hashref mapping physical table names to C<OBB::Tab>
(database table) objects.

=item * C<Cnt_que>

C<Cnt_que> counts the number of queries.

=item * C<Cnt_rec>

C<Cnt_rec> counts the number of retrieved records.

=back

=head4 C<Define_tab ()>

Method C<Define_tab ( $name )> creates a table obbject.

  $tab = $db -> Define_tab ( 'bar' )

C<$tab> is a
C<OBB::Tab::Foo::bar> =>
C<OBB::Tab::Foo> =>
C<OBB::Tab>.

C<Define_tab ( $name )> creates an access method :

  $db -> bar

C<Define_tab ( 'bar' )> also creates C<OBB::Col> sub-classes :
C<OBB::Col::Foo::bar> =>
C<OBB::Col::Foo> =>
C<OBB::Col>.

C<Define_tab ( 'bar' )> also creates C<OBB::Rec> sub-classes :
C<OBB::Rec::Foo::bar> =>
C<OBB::Rec::Foo> =>
C<OBB::Rec>.

=head4 C<Connect ()>

=head4 C<Disconnect ()>

  $dbh = $db -> Connect ( ... )

Connect/disconnect to/from a database.

Method C<Connect> simply calls C<DBI->connect>, passing all it's arguments.
On success it sets the database handle.
On failure, use C<$DBI::Errstr> to get the error message.

=head4 C<Has_tab ()>

  $tab = $db -> Has_tab ( $name )

Method C<Has_tab> returns a table object with I<logical> name C<$name>,
if it exists.

=head4 C<As_tab ()>

  $tab = $db -> As_tab ( $tabl )

Method C<As_tab> returns a table object with I<physical> name C<$tabl>,
if it exists.

=head4 C<Query ()>

Method C<Query> prepares and executes some sql statement. 

  $db -> Query ( sql => 'command', attr = { ... }, args => [ ... ] )

where C<attr> contains attributes used in the I<prepare> call,
and C<args> contains values passed in the I<execute> call.

Method C<Query> returns :

=over 4

=item * for I<select statements> : the result of C<selectall_arrayref()>,
an arrayref of hashrefs

=item * for I<other statements> : the result of C<do ( $sql, $attr, @$args )>

=back

=head3 C<OBB::Tab>

=head4 C<OBB::Tab> attributes :

=over 4

=item * C<Base>

a reference to the parent database object.

=item * C<Name>

the logical table-name

=item * C<Tabl>

the name of the table, as defined in the database.

=item * C<Pkey>

The name the table's column containing the primary key.

=item * C<Cols>

A list of references to the table's columns objects.

=item * C<Defs>

A hashref mapping (logical) column-names to default values.

=item * C<Tags>

A list of column names ; these tags are used to create a short
description of a table-record, this defaults to the value
of the record's primary key ; see C<OBB::Rec::Tag()>.

=back

=head4 C<Define_col ()>

Method C<Define_col ( $name )> creates a column obbject.

  $my_col = $tab -> Define_col ( 'my_col' )

C<$my_col> is a
C<OBB::Col::Foo::bar::my_col> =>
C<OBB::Col::Foo::bar> =>
C<OBB::Col::Foo> =>
C<OBB::Col>.

C<Define_col ( $name )> creates an access method in the column's parent-table
object :

  $tab -> my_col

=head4 C<Col_names ()>

Method C<Col_names> returns a list of the names of the columns of a table.

=head4 C<New_rec ()>

Method C<New_rec> creates a new record for table C<$tab>,
blessed into a subclass of C<OBB::Rec>.

  $rec = $tab -> New_rec [[ ( attr1 => val1, ... ) ]]

=head4 C<Make_sql ()>

Method C<Make_sql> creates an sql-statement.

  $tab -> Make_sql
      ( fields => "$tabl.*"
      , from   => $tabl
      , where  => ''
      , group  => ''
      , having => ''
      , order  => ''
      , limit  => ''
      )

where C<$tabl = $tab -> Tabl>.
The method is useful when creating a nested C<SELECT> statement.

=head4 C<Select ()>

Method C<Select> executes a I<SELECT>-statement.

  $tab -> Select
    [[ ( Make_sql options )
    || ( sql => 'some select statement' )
    ]]

The method returns a list of blessed records.

=head4 C<Select1 ()>

Method C<Select1> returns at most one record ;
the result of the the corresponding C<Select ( ..., limit => 1 )>.

=head4 C<Select_hash ()>

  $hashref = $tab -> Select_hash ( name => column_name, %opts )

Same as C<Select>, but returns a hashref with ($key,$rec)-pairs where

  $key == $rec -> column_name

Method C<Select_hash> returns an error-string if the $keys are not unique.

=head4 C<Try ()>

  $rec = $tab -> Try ( $pval )

Method C<Try> returns the record where C<$tab->Pkey> has value C<$pval>.
If no such record exists, the method returns C<undef>.

=head4 C<Get ()>

  $rec = $tab -> Get ( $pval )

Same as C<Try>, except that a missing record is a fatal error.
If no such record exists, a fatal error is raised.

=head4 C<Delete ()>

=head4 C<Delete_all ()>

  $tab -> Delete ( where => 'clause' )
  $tab -> Delete_all ()

Method C<Delete> deletes records from table C<$tab>.
The I<clause> should not be empty.

To delete a record with primary key C<id> :

  $tab -> Delete ( where => "id = ?", args => [ $id ] )

=head4 C<In_db ()>

  $tab -> In_db

Predicate ; true if C<$tab -> Tabl> exists in the database.

=head4 C<Foreign_key_info ()>

XXX

=head3 C<OBB::Col>

=head4 C<OBB::Col> attributes :

=over 4

=item * C<Name>

The column's name

=item * C<Tabl>

A reference to the column's parent table object.

=item * C<Type => [[ text || int || bool || serial ]]>

The column's datatype.

=item * C<Pkey => 0>

A boolean ; true if the column contains the primary-key.

=item * C<Null => 1>

A boolean ; true if the column may contain NULL values.

=item * C<Def => undef>

A default value for this column.

=item * C<Uniq => 0>

A boolean ; true if the column's values must be unique.

=item * C<Fkey => undef>

Forreign key contraint ; may contain a reference to another C<OBB::Col> object.

=back

=head4 C<notnull ()>

Method C<$col -> notnull> returns C<not $col -> Null>.

=head3 C<OBB::Rec>

=head4 C<OBB::Rec> attributes :

=over 4

=item * C<Tabl>

A reference to the record's parent-table object.

=back

=head4 C<Base ()>

Method C<$rec -> Base> returns a reference to the record's
parent-database object.

=head4 C<Cols ()>

Method C<$rec -> Cols> returns the parent-table's column list.

=head4 C<Pkey ()>

Method C<$rec -> Pkey> returns (the name of) the parent-table's
primary key column.

=head4 C<Check ()>

  $error = $rec -> Check [[ ( excl => [ name1, ... ] ) ]]

Method C<Check> checks the record for I<notnull> and I<foreign key>
constraints ; it returns a error-string on failure.
Names in the C<excl> list are not checked, as are values
of type I<serial>.

=head4 C<Insert ()>

  $mesg = $rec -> Insert [[ ( excl => [ name1, ... ] ) ]]

Method C<Insert> inserts the record into the database.
It returns a diagnostic string.
Names in the C<excl> list are not specified in the C<INSERT> command,
as are names of columns of type I<serial>.

=head4 C<Update ()>

  $mesg = $rec -> Update [[ ( excl => [ name1, ... ] ) ]]

Method C<Update> updates the record in the database.
It returns a diagnostic string, specifying the changes.
Names in the C<excl> list are not specified in the C<UPDATE> command,
as are names of columns of type I<serial>.
The record's (value of the) primary key is used to identify the record
in the C<UPDATE> command.

=head4 C<Save ()>

  $msg = $rec -> Save [[ ( excl => [ name1, ... ] ) ]]

Method C<Save> uses either C<Insert> or C<Update> to save the
record's contents in the database, depending on the record's
primary value (the value of C<$rec->Pkey>).

=head4 C<Delete ()>

  $mesg = $rec -> Delete

The record's (value of the) primary key is used to identify the record
in the C<Delete> command.

=head3 Meta info

OBB supplies an interface to DBI's meta-info.
All methods return a list of hashrefs ;

  $tab -> Table_info
  $col -> Column_info
  $tab -> Foreign_key_info

=head3 Debugging

For all query-like methods, C<$obbj -> Method ( %opts )>
prints the executed sql-statement and args-list,
when C<$opts { debug }> or C<$obbj -> Debug> is true.
For instance :

  $tab -> Select ( ..., debug => 1 )

or

  $tab -> Debug ( 1 )
  ...
  $tab -> Select ( ... )

or

  OBB::Tab -> Debug ( 1 )
  ...
  $tab -> Select ( ... )

=head1 EXAMPLE

Let's model a school, with teachers, pupils and courses.

  package OBB::School ;
  use OBB ; use vars qw(@ISA) ; @ISA = qw(OBB) ;
  __PACKAGE__ -> Mk_methods ( [ qw(id name address) ) ;

  { package main ; my $school = School -> Make ;
  }

  package OBB::Teacher ;
  use OBB ; use vars qw(@ISA) ; @ISA = qw(OBB) ;

  __PACKAGE__ -> Mk_methods ( qw(id name initials given) ) ;
  __PACKAGE__ -> Mk_class_methods
    ( ID => 1 ) ;

  sub given_name { my $self = shift ; $self -> given ; }

  sub full_name
    { my $self = shift ;
      $self -> Printf ( 'No name for id (%s)', $self -> id )
        if $self -> Verbose and ! defined $self -> name ;
      sprintf "%s %s", $self -> initials, $self -> name ;
    }

  # example : give each instance a defined id ; redefine Init :
  sub Init
    { my $self = shift ;
      my %opts = @_ ;
      return undef unless $self -> SUPER::Init ( %opts ) ;
      $self -> id ( $ID ++ ) unless $self -> id ;
      $self ;
    }

  package main ;

  # create a Teacher
  my $rpf = Teacher -> Make
    ( name => 'Feynman', initials => 'R.P.', given => 'Richard' ) ;

=head1 AUTHOR

=begin html

  <p>
  &copy; %YEARS%
  <a href="http://www.staff.science.uu.nl/~penni101/">Henk P. Penning</a>,
  <a href="http://www.uu.nl/faculty/science/EN/">Faculty of Science</a>,
  <a href="http://www.uu.nl/">Utrecht University</a>
  <br />
  %VERSION% - %DATE% - dev revision %REVISION%
  </p>
  <hr />

<p>
<a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10" style="border-width:0"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
&nbsp;
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border:0;width:88px;height:31px" alt="Valid CSS!"
src="http://jigsaw.w3.org/css-validator/images/vcss" /></a>
</p>

=end html

=begin man

  (c) %YEARS% Henk P. Penning
  Faculty of Science, Utrecht University
  http://www.staff.science.uu.nl/~penni101/ -- penning@uu.nl
  %VERSION% - %DATE% - doc revision %REVISION%

=end man

=cut
