cvsuser 02/01/30 11:48:13
Modified: P5EEx/Blue/P5EEx/Blue Repository.pm
Log:
reorder methods within the file for clearer POD output
Revision Changes Path
1.7 +597 -545 p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm
Index: Repository.pm
===================================================================
RCS file: /cvs/public/p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -w -r1.6 -r1.7
--- Repository.pm 24 Jan 2002 04:15:07 -0000 1.6
+++ Repository.pm 30 Jan 2002 19:48:13 -0000 1.7
@@ -1,6 +1,6 @@
#############################################################################
-## $Id: Repository.pm,v 1.6 2002/01/24 04:15:07 spadkins Exp $
+## $Id: Repository.pm,v 1.7 2002/01/30 19:48:13 spadkins Exp $
#############################################################################
package P5EEx::Blue::Repository;
@@ -122,6 +122,53 @@
A Repository is a means by which data may be stored somewhere without
knowing what underlying technology is storing the data.
+A Repository is the central persistence concept within the P5EE.
+A Repository does not present a uniquely object-oriented view of
+its data. Rather it presents a "logical relational" data model.
+It does not return objects, but rows of data.
+
+The "logical data model" means that a developer can program to
+the data model which usually comes out of system requirements analysis,
+closely modelling the business. All of the changes to this
+logical data model that are
+incorporated during physical database design are abstracted
+away, such as:
+
+ * physical table naming,
+ * physical column naming,
+ * normalization of data into parent tables, and
+ * splitting of tables based on various physical constraints.
+
+This could be called object-to-relational mapping, but it is more
+accurately called logical-to-physical-relational mapping.
+
+Despite the fact that the Repository is a relational data storage
+abstraction, persistent objects (i.e. Entity Widgets) can be built to
+save and restore their state from a Repository. Furthermore, the
+built-in support for non-scalar fields (references to arbitrarily
+complex perl data structures) and the ability for Entity Widgets
+to encapsulate more than one row of data, makes the technology quite
+fit for object-oriented development.
+
+The design of the Repository is based around three important uses of
+data.
+
+ * Transaction Processing
+ * Batch Processing
+ * Report Generation
+
+(more about this later)
+
+The Repository abstraction seeks to solve the following problems.
+
+ * objects may have attributes that come from multiple sources
+ * caching
+ * isolated from physical database changes
+ * transactions
+ * data source independence
+ * no save/restore
+ * devel/test/prod environments
+
=cut
#############################################################################
@@ -136,11 +183,11 @@
=item * Class: P5EEx::Blue::Repository
-=item * Class: P5EEx::Blue::Repository::BerkeleyDB
+=item * Class: P5EEx::Blue::Repository::DBI
=item * Class: P5EEx::Blue::Repository::File
-=item * Class: P5EEx::Blue::Repository::DBI
+=item * Class: P5EEx::Blue::Repository::BerkeleyDB
=item * Class: P5EEx::Blue::Repository::LDAP
@@ -150,6 +197,15 @@
=item * Class: P5EEx::Blue::Repository::SOAP
- remote data storage
+=item * Class: P5EEx::Blue::Repository::Cache
+ - use the Cache::Cache module
+
+=item * Class: P5EEx::Blue::Repository::SPOPS
+ - maybe?
+
+=item * Class: P5EEx::Blue::Repository::Tangram
+ - maybe?
+
=back
=cut
@@ -233,99 +289,6 @@
=cut
-#####################################################################
-# init()
-#####################################################################
-
-=head2 init()
-
- * Signature: $repository->init();
- * Signature: $repository->init($named);
- * Param: deferConnection integer
- * Return: void
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $self->init();
-
-Initialize the {config} structure and the {name} attribute.
-
-Every Service constructor (Repository is derived from Service) will
-invoke the init() method near the end of Repository object construction.
-
-The standard behavior (implemented here) in init() is to initialize
-variables of the Repository, call init2(), connect to the repository,
-and load the repository metadata.
-
-=cut
-
-sub init {
- my ($self, $args) = @_;
- my ($dbidriver, $dbname, $dbuser, $dbpass, $dbioptions, $dbschema);
- my ($name, $config);
-
- $self->{numrows} = 0;
- $self->{error} = "";
-
- $self->init2($args);
-
- if (!$self->{config}{deferConnection} && !$self->connect()) {
- my ($config);
- $config = $self->{config};
-
- print STDERR "Error on connect():";
- foreach (keys %$config) {
- print STDERR " $_=[", $config->{$_}, "]";
- }
- print STDERR "\n";
- return(undef);
- }
-
- $self->load_rep_metadata();
-}
-
-#############################################################################
-# init2()
-#############################################################################
-
-=head2 init2()
-
- * Signature: $repository->init2();
- * Signature: $repository->init2($named);
- * Param: deferConnection integer
- * Return: void
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $self->init2();
-
-The default behavior of init2() is defined here in the Repository class
-and is intended to be overridden (if necessary) in the subclass which
-implements the details of access to the physical data store.
-
-This default behavior is simply to copy the values in the configuration
-into the attributes of the object itself. i.e.
-
- $self->{$var} = $self->{config}{$var};
-
-=cut
-
-sub init2 { # OVERRIDE IN SUBCLASS TO GET NON-DEFAULT CAPABILITIES
- my $self = shift;
-
- my ($config, $var);
- $config = $self->{config};
- if (defined $config) {
- foreach $var (keys %$config) {
- $self->{$var} = $config->{$var};
- }
- }
-}
-
#############################################################################
# PUBLIC METHODS
#############################################################################
@@ -577,421 +540,156 @@
=cut
#############################################################################
-# load_rep_metadata()
+# get_type_names()
#############################################################################
-=head2 load_rep_metadata()
+=head2 get_type_names()
- * Signature: $repository->load_rep_metadata();
+ * Signature: $typenames = $repository->get_type_names();
* Param: void
- * Return: void
+ * Return: $typenames []
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $self->load_rep_metadata();
-
-Initializes the repository metadata information from the {config}.
+ $typenames = $rep->get_type_names();
+ print join(",", @$typenames), "\n";
- * List of tables (+ displayable labels)
- * List of column types (+ displayable labels)
+Returns the standard set of type names for columns in a repository.
+These are perl-friendly type names which are useful to do data validation.
-Then it calls load_rep_metadata_auto() in order for the repository
-itself to be consulted for its metadata information.
+ * string
+ * text
+ * integer
+ * float
+ * date
+ * time
+ * datetime
+ * binary
=cut
-# load metadata about TYPES supported by the repository
-# and the list of TABLES in it.
-sub load_rep_metadata {
+sub get_type_names {
my ($self) = @_;
+ $self->{types};
+}
- my ($repconfig, $table, $tables, $table_defs, $table_def, $native_table, $idx);
- $repconfig = $self->{repconfig};
+#############################################################################
+# get_type_labels()
+#############################################################################
- # start with the list of tables that was configured (or the empty list)
- $tables = $repconfig->{tables};
- $tables = [] if (!defined $tables);
- $self->{tables} = $tables;
+=head2 get_type_labels()
- # start with the hash of tables defined (or the empty hash)
- $table_defs = $repconfig->{table};
- $table_defs = {} if (!defined $table_defs);
- $self->{table} = $table_defs;
+ * Signature: $typelabels = $repository->get_type_labels();
+ * Param: void
+ * Return: $typelabels {}
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
- # for each table named in the configuration, give it a number up front
- for ($idx = 0; $idx <= $#$tables; $idx++) {
- $table = $tables->[$idx];
- $table_defs->{$table}{idx} = $idx;
+ Sample Usage:
+
+ $typelabels = $rep->get_type_labels();
+ foreach (sort keys %$typelabels) {
+ print "$_ => $typelabels->{$_}\n";
}
- # for each table in the hash (random order), add them to the end
- foreach $table (keys %$table_defs) {
- $table_def = $table_defs->{$table};
- $table_def->{name} = $table;
- $table_def->{label} = $table if (! $table_def->{label});
+Returns a hash of all of the repository types and the labels
+which should be used when displaying them to the user through
+the user interface.
- # table has not been added to the list and it's not explicitly "hidden", so
add it
- if (!defined $table_def->{idx} && ! $table_def->{hide}) {
- push(@$tables, $table);
- $table_def->{idx} = $#$tables;
+ * string => "Characters"
+ * text => "Paragraph"
+ * integer => "Integer"
+ * float => "Number"
+ * date => "Date"
+ * time => "Time"
+ * datetime => "Date and Time"
+ * binary => "Binary Data"
- # we're not hiding physical tables and a native table was defined, so
make an entry
- if (! $self->{hide_physical}) {
- $native_table = $table_def->{native_table};
- if (defined $native_table) {
- $table_defs->{$native_table} = $table_defs->{$table};
- }
- }
- }
+=cut
- $self->{table_labels}{$table} = $table_def->{label};
+sub get_type_labels {
+ my ($self) = @_;
+ $self->{type_labels};
}
- my ($type, $types, $type_defs);
+#############################################################################
+# get_type_def()
+#############################################################################
- # start with the hash of types defined (or the empty hash)
- $type_defs = $repconfig->{type};
- $type_defs = {} if (!defined $type_defs);
- $self->{type} = $type_defs;
+=head2 get_type_def()
- # define the standard list of Repository types
- $types = [ "string", "text", "integer", "float", "date", "time", "datetime",
"binary" ];
- $self->{types} = $types;
+ * Signature: $typedef = $rep->get_type_def($typename);
+ * Param: $typename string
+ * Return: $typedef {}
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
- # define the standard list of Repository labels
- $self->{type_labels} = {
- "string" => "Characters",
- "text" => "Paragraph",
- "integer" => "Integer",
- "float" => "Number",
- "date" => "Date",
- "time" => "Time",
- "datetime" => "Date and Time",
- "binary" => "Binary Data",
- };
+ Sample Usage:
- # figure the index in the array of each type
- for ($idx = 0; $idx <= $#$types; $idx++) {
- $type = $types->[$idx];
- $self->{type}{$type}{idx} = $idx;
- }
+ $typedef = $rep->get_type_def("string");
+ print "$typedef->{name} $typedef->{label}\n";
- # load up all additional information from the native metadata
- $self->load_rep_metadata_auto();
+Gets a reference to a "type definition", which allows you to access all
+of the attributes of the requested type
+(currently only "name" and "label").
+
+=cut
+
+sub get_type_def {
+ my ($self, $type) = @_;
+ $self->{type}{$type};
}
#############################################################################
-# load_rep_metadata_auto()
+# get_table_names()
#############################################################################
-=head2 load_rep_metadata_auto()
+=head2 get_table_names()
- * Signature: $repository->load_rep_metadata_auto();
+ * Signature: $tablenames = $rep->get_table_names();
* Param: void
- * Return: void
+ * Return: $tablenames []
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $repository->load_rep_metadata_auto();
-
-Loads repository metadata from the repository itself
-(to complement metadata in the configuration and perhaps
-override it).
+ $tablenames = $rep->get_table_names();
+ print join(",", @$tablenames), "\n";
-The default implementation does nothing.
-It is intended to be overridden in the subclass
-(if the repository has any sort of metadata).
+Returns the set of table names in the repository.
=cut
-sub load_rep_metadata_auto { # OVERRIDE IN SUBCLASS (IF DESIRED)
+sub get_table_names {
my ($self) = @_;
+ $self->{tables};
}
#############################################################################
-# load_table_metadata()
+# get_table_labels()
#############################################################################
-=head2 load_table_metadata()
+=head2 get_table_labels()
- * Signature: $self->load_table_metadata();
+ * Signature: $tablelabels = $rep->get_table_labels();
* Param: void
- * Return: void
+ * Return: $tablelabels {}
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $self->load_table_metadata();
+ $tablelabels = $rep->get_table_labels();
+ foreach (sort keys %$tablelabels) {
+ print "$_ => $tablelabels->{$_}\n";
+ }
-First it calls load_table_metadata_auto() in order for the repository
-itself to be consulted for any metadata information for the about the
-table.
-
-Then it initializes
-the repository metadata information for that table from the {config}
-information.
-
- * List of columns (+ displayable labels, types)
- * List of column types (+ displayable labels)
-
-Then it determines the set of required columns whenever selecting
-data from the table and clears the cache of selected rows
-for the table.
-
-=cut
-
-# load detailed metadata about a particular table, including
-# the details about each column
-sub load_table_metadata {
- my ($self, $table) = @_;
-
- # if it's already been loaded, don't do it again
- return if (defined $self->{table}{$table}{loaded});
- $self->{table}{$table}{loaded} = 1; # mark it as having been loaded
-
- my ($table_def, $columns, $column, $column_def, $idx, $native_column);
-
- $table_def = $self->{table}{$table};
- return if (!defined $table_def);
-
- $columns = $table_def->{columns};
- if (! defined $columns) {
- $columns = [];
- $table_def->{columns} = $columns;
- }
-
- # for each column named in the configuration, give it a number up front
- for ($idx = 0; $idx <= $#$columns; $idx++) {
- $column = $columns->[$idx];
- $table_def->{column}{$column}{idx} = $idx;
- }
-
- # load up all additional information from the native metadata
- $self->load_table_metadata_auto($table);
-
- # for each column in the hash (random order), add them to the end
- foreach $column (keys %{$table_def->{column}}) {
- $column_def = $table_def->{column}{$column};
- $column_def->{name} = $column;
- $column_def->{label} = $column if (! $column_def->{label});
-
- # column has not been added to the list and it's not explicitly "hidden",
so add it
- if (!defined $column_def->{idx} && ! $column_def->{hide}) {
- push(@$columns, $column);
- $idx = $#$columns;
- $column_def->{idx} = $idx;
- $column_def->{alias} = "c$idx" if (!defined $column_def->{alias});
-
- # we're not hiding physical columns and a native table was defined, so
make an entry
- if (! $self->{hide_physical}) {
- $native_column = $column_def->{native_column};
- if (defined $native_column &&
- $native_column ne $column &&
- !defined $table_def->{column}{$native_column}) {
- $table_def->{column}{$native_column} =
$table_def->{column}{$column};
- }
- }
- }
-
- $table_def->{column_labels}{$column} = $column_def->{label};
- }
-
- # if a primary key is not defined, assume it is the first column
- #if (!defined $table_def->{prikey}) {
- # $table_def->{prikey} = [ $table_def->{columns}[0] ];
- #}
-
- # predefine that certain required columns will be in the result set
- $self->set_required_columns_fetched($table);
- $self->clear_cache();
-}
-
-#############################################################################
-# load_table_metadata_auto()
-#############################################################################
-
-=head2 load_table_metadata_auto()
-
- * Signature: $repository->load_table_metadata_auto();
- * Param: void
- * Return: void
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $self->load_table_metadata_auto();
-
-Loads metadata for an individual table from the repository itself
-(to complement metadata in the configuration and perhaps
-override it).
-
-The default implementation does nothing.
-It is intended to be overridden in the subclass
-(if the repository has any sort of metadata).
-
-=cut
-
-sub load_table_metadata_auto { # OVERRIDE IN SUBCLASS (IF DESIRED)
- my ($self, $table) = @_;
-}
-
-#############################################################################
-# get_type_names()
-#############################################################################
-
-=head2 get_type_names()
-
- * Signature: $typenames = $repository->get_type_names();
- * Param: void
- * Return: $typenames []
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $typenames = $rep->get_type_names();
- print join(",", @$typenames), "\n";
-
-Returns the standard set of type names for columns in a repository.
-These are perl-friendly type names which are useful to do data validation.
-
- * string
- * text
- * integer
- * float
- * date
- * time
- * datetime
- * binary
-
-=cut
-
-sub get_type_names {
- my ($self) = @_;
- $self->{types};
-}
-
-#############################################################################
-# get_type_labels()
-#############################################################################
-
-=head2 get_type_labels()
-
- * Signature: $typelabels = $repository->get_type_labels();
- * Param: void
- * Return: $typelabels {}
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $typelabels = $rep->get_type_labels();
- foreach (sort keys %$typelabels) {
- print "$_ => $typelabels->{$_}\n";
- }
-
-Returns a hash of all of the repository types and the labels
-which should be used when displaying them to the user through
-the user interface.
-
- * string => "Characters"
- * text => "Paragraph"
- * integer => "Integer"
- * float => "Number"
- * date => "Date"
- * time => "Time"
- * datetime => "Date and Time"
- * binary => "Binary Data"
-
-=cut
-
-sub get_type_labels {
- my ($self) = @_;
- $self->{type_labels};
-}
-
-#############################################################################
-# get_type_def()
-#############################################################################
-
-=head2 get_type_def()
-
- * Signature: $typedef = $rep->get_type_def($typename);
- * Param: $typename string
- * Return: $typedef {}
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $typedef = $rep->get_type_def("string");
- print "$typedef->{name} $typedef->{label}\n";
-
-Gets a reference to a "type definition", which allows you to access all
-of the attributes of the requested type
-(currently only "name" and "label").
-
-=cut
-
-sub get_type_def {
- my ($self, $type) = @_;
- $self->{type}{$type};
-}
-
-#############################################################################
-# get_table_names()
-#############################################################################
-
-=head2 get_table_names()
-
- * Signature: $tablenames = $rep->get_table_names();
- * Param: void
- * Return: $tablenames []
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $tablenames = $rep->get_table_names();
- print join(",", @$tablenames), "\n";
-
-Returns the set of table names in the repository.
-
-=cut
-
-sub get_table_names {
- my ($self) = @_;
- $self->{tables};
-}
-
-#############################################################################
-# get_table_labels()
-#############################################################################
-
-=head2 get_table_labels()
-
- * Signature: $tablelabels = $rep->get_table_labels();
- * Param: void
- * Return: $tablelabels {}
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
-
- Sample Usage:
-
- $tablelabels = $rep->get_table_labels();
- foreach (sort keys %$tablelabels) {
- print "$_ => $tablelabels->{$_}\n";
- }
-
-Returns a hash of all of the tables and the labels
-which should be used when displaying them to the user through
-the user interface.
+Returns a hash of all of the tables and the labels
+which should be used when displaying them to the user through
+the user interface.
=cut
@@ -1952,12 +1650,254 @@
}
#############################################################################
-# get_related_keys()
+# get_related_keys()
+#############################################################################
+
+=head2 get_related_keys()
+
+ * Signature: $tbd_return = $repository->get_related_keys($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->get_related_keys($tbd_param);
+
+=cut
+
+# @keys = $rep->get_related_keys($table, $key, $related_table, $relation);
+# TODO:
+sub get_related_keys {
+ my ($self, $table, $key, $related_table, $relation) = @_;
+ my (@keys);
+}
+
+#############################################################################
+# PUBLIC METHODS
+#############################################################################
+
+=head1 Public Methods: Cache control
+
+=cut
+
+#############################################################################
+# load_cache()
+#############################################################################
+
+=head2 load_cache()
+
+ * Signature: $tbd_return = $repository->load_cache($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->load_cache($tbd_param);
+
+=cut
+
+# $rep->load_cache();
+sub load_cache {
+ my $self = shift;
+}
+
+#############################################################################
+# clear_cache()
+#############################################################################
+
+=head2 clear_cache()
+
+ * Signature: $tbd_return = $repository->clear_cache($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->clear_cache($tbd_param);
+
+=cut
+
+# $rep->clear_cache();
+sub clear_cache {
+ my ($self, $table) = @_;
+ my (@tables, $rows);
+ @tables = (defined $table) ? ($table) : @{$self->{tables}};
+
+ foreach $table (@tables) {
+ $rows = $self->{table}{$table}{cache}{rows};
+ if (!defined $rows || ref($rows) ne "ARRAY" || $#$rows > -1) {
+ $self->{table}{$table}{cache}{rows} = [];
+ $self->{table}{$table}{cache}{rowidx} = {};
+ }
+ }
+}
+
+#############################################################################
+# add_columns_fetched()
+#############################################################################
+
+=head2 add_columns_fetched()
+
+ * Signature: $tbd_return = $repository->add_columns_fetched($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->add_columns_fetched($tbd_param);
+
+=cut
+
+# $rep->add_columns_fetched ($table, \@cols);
+# $rep->add_columns_fetched ($table, \@cols, \@colidx);
+sub add_columns_fetched {
+ my ($self, $table, $colsref, $colidxref) = @_;
+ my ($colidx, $column, $colnum, $columns_added, $cachecolumns);
+
+ $colidx = $self->{table}{$table}{cache}{columnidx};
+ if (!defined $colidx) {
+ $colidx = {};
+ $self->{table}{$table}{cache}{columnidx} = $colidx;
+ }
+
+ $cachecolumns = $self->{table}{$table}{cache}{columns};
+ if (!defined $cachecolumns) {
+ $cachecolumns = [];
+ $self->{table}{$table}{cache}{columns} = $cachecolumns;
+ }
+
+ $columns_added = 0;
+ for ($colnum = 0; $colnum <= $#$colsref; $colnum++) {
+ $column = $colsref->[$colnum];
+ if (!defined $colidx->{$column}) {
+ push(@$cachecolumns, $column);
+ $colidx->{$column} = $#$cachecolumns;
+ $columns_added = 1;
+ }
+ $colidxref->[$colnum] = $colidx->{$column} if (ref($colidxref) eq "ARRAY");
+ }
+
+ if ($columns_added) { # clear the cache
+ $self->clear_cache($table);
+ }
+}
+
+#############################################################################
+# set_required_columns_fetched()
+#############################################################################
+
+=head2 set_required_columns_fetched()
+
+ * Signature: $tbd_return =
$repository->set_required_columns_fetched($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->set_required_columns_fetched($tbd_param);
+
+=cut
+
+# $rep->set_required_columns_fetched($table);
+sub set_required_columns_fetched {
+ my ($self, $table) = @_;
+ my ($prikeycolumns, @prikeyidx);
+ $prikeycolumns = $self->{table}{$table}{prikey};
+ $self->add_columns_fetched($table, $prikeycolumns, \@prikeyidx);
+ $self->{table}{$table}{prikeyidx} = \@prikeyidx;
+}
+
+#############################################################################
+# clear_columns_fetched()
+#############################################################################
+
+=head2 clear_columns_fetched()
+
+ * Signature: $tbd_return = $repository->clear_columns_fetched($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->clear_columns_fetched($tbd_param);
+
+=cut
+
+# $rep->clear_columns_fetched ($table);
+sub clear_columns_fetched {
+ my ($self, $table) = @_;
+ $self->{table}{$table}{cache}{columnidx} = {};
+ $self->{table}{$table}{cache}{columns} = [];
+ $self->set_required_columns_fetched($table);
+}
+
+#############################################################################
+# set_row_hint()
+#############################################################################
+
+=head2 set_row_hint()
+
+ * Signature: $tbd_return = $repository->set_row_hint($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->set_row_hint($tbd_param);
+
+=cut
+
+# $rep->set_row_hint ($table, \%paramvalues);
+sub set_row_hint {
+ my ($self, $table, $paramvalueshashref) = @_;
+ $self->{table}{$table}{cache}{paramvalues} = { %$paramvalueshashref };
+}
+
+#############################################################################
+# clear_row_hint()
+#############################################################################
+
+=head2 clear_row_hint()
+
+ * Signature: $tbd_return = $repository->clear_row_hint($tbd_param);
+ * Param: $tbd_param integer
+ * Return: $tbd_return integer
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $tbd_return = $repository->clear_row_hint($tbd_param);
+
+=cut
+
+# $rep->clear_row_hint ($table);
+sub clear_row_hint {
+ my ($self, $table) = @_;
+ $self->{table}{$table}{cache}{paramvalues} = {};
+}
+
+#############################################################################
+# get_required_columns()
#############################################################################
-=head2 get_related_keys()
+=head2 get_required_columns()
- * Signature: $tbd_return = $repository->get_related_keys($tbd_param);
+ * Signature: $tbd_return = $repository->get_required_columns($tbd_param);
* Param: $tbd_param integer
* Return: $tbd_return integer
* Throws: P5EEx::Blue::Exception::Repository
@@ -1965,32 +1905,31 @@
Sample Usage:
- $tbd_return = $repository->get_related_keys($tbd_param);
+ $tbd_return = $repository->get_required_columns($tbd_param);
=cut
-# @keys = $rep->get_related_keys($table, $key, $related_table, $relation);
-# TODO:
-sub get_related_keys {
- my ($self, $table, $key, $related_table, $relation) = @_;
- my (@keys);
+# @columns = $rep->get_required_columns($table);
+sub get_required_columns {
+ my ($self, $table) = @_;
+ my (@columns);
}
#############################################################################
# PUBLIC METHODS
#############################################################################
-=head1 Public Methods: Cache control
+=head1 Public Methods: Transaction Control
=cut
#############################################################################
-# load_cache()
+# commit()
#############################################################################
-=head2 load_cache()
+=head2 commit()
- * Signature: $tbd_return = $repository->load_cache($tbd_param);
+ * Signature: $tbd_return = $repository->commit($tbd_param);
* Param: $tbd_param integer
* Return: $tbd_return integer
* Throws: P5EEx::Blue::Exception::Repository
@@ -1998,22 +1937,43 @@
Sample Usage:
- $tbd_return = $repository->load_cache($tbd_param);
+ $tbd_return = $repository->commit($tbd_param);
=cut
-# $rep->load_cache();
-sub load_cache {
+# $rep->commit();
+sub commit {
my $self = shift;
+ my ($table, $rows, $rowidx, $rowchange, $change, $colref, $prikeyidx);
+ foreach $table (@{$self->{tables}}) {
+ $prikeyidx = $self->{table}{$table}{prikeyidx};
+ $rows = $self->{table}{$table}{cache}{rows};
+ $rowchange = $self->{table}{$table}{cache}{rowchange};
+ $colref = $self->{table}{$table}{cache}{columns};
+ if ($#$rowchange > -1) {
+ for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
+ $change = $rowchange->[$rowidx];
+ next if (!defined $change);
+ if ($change eq "U") {
+ $self->update_row($table, $colref, $rows->[$rowidx],
$prikeyidx);
+ $rowchange->[$rowidx] = "";
+ }
+ elsif ($change eq "I") {
+ $self->insert_row($table, $colref, $rows->[$rowidx]);
+ $rowchange->[$rowidx] = "";
+ }
+ }
+ }
+ }
}
#############################################################################
-# clear_cache()
+# rollback()
#############################################################################
-=head2 clear_cache()
+=head2 rollback()
- * Signature: $tbd_return = $repository->clear_cache($tbd_param);
+ * Signature: $tbd_return = $repository->rollback($tbd_param);
* Param: $tbd_param integer
* Return: $tbd_return integer
* Throws: P5EEx::Blue::Exception::Repository
@@ -2021,325 +1981,417 @@
Sample Usage:
- $tbd_return = $repository->clear_cache($tbd_param);
+ $tbd_return = $repository->rollback($tbd_param);
=cut
-# $rep->clear_cache();
-sub clear_cache {
- my ($self, $table) = @_;
- my (@tables, $rows);
- @tables = (defined $table) ? ($table) : @{$self->{tables}};
-
- foreach $table (@tables) {
- $rows = $self->{table}{$table}{cache}{rows};
- if (!defined $rows || ref($rows) ne "ARRAY" || $#$rows > -1) {
- $self->{table}{$table}{cache}{rows} = [];
- $self->{table}{$table}{cache}{rowidx} = {};
- }
- }
+# $rep->rollback();
+sub rollback {
+ my $self = shift;
}
#############################################################################
-# add_columns_fetched()
+# PUBLIC METHODS
#############################################################################
-=head2 add_columns_fetched()
+=head1 Public Methods: Miscellaneous
- * Signature: $tbd_return = $repository->add_columns_fetched($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
+=cut
+
+#############################################################################
+# serial()
+#############################################################################
+
+=head2 serial()
+
+ * Signature: $serial_num = $repository->serial($category);
+ * Param: $category string
+ * Return: $serial_num integer
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $tbd_return = $repository->add_columns_fetched($tbd_param);
+ $serial_num = $repository->serial($category);
=cut
-# $rep->add_columns_fetched ($table, \@cols);
-# $rep->add_columns_fetched ($table, \@cols, \@colidx);
-sub add_columns_fetched {
- my ($self, $table, $colsref, $colidxref) = @_;
- my ($colidx, $column, $colnum, $columns_added, $cachecolumns);
-
- $colidx = $self->{table}{$table}{cache}{columnidx};
- if (!defined $colidx) {
- $colidx = {};
- $self->{table}{$table}{cache}{columnidx} = $colidx;
- }
-
- $cachecolumns = $self->{table}{$table}{cache}{columns};
- if (!defined $cachecolumns) {
- $cachecolumns = [];
- $self->{table}{$table}{cache}{columns} = $cachecolumns;
+my %serial_number;
+sub serial {
+ my ($self, $category) = @_;
+ if (!defined $serial_number{$category}) {
+ $serial_number{$category} = 1;
+ return 1;
}
-
- $columns_added = 0;
- for ($colnum = 0; $colnum <= $#$colsref; $colnum++) {
- $column = $colsref->[$colnum];
- if (!defined $colidx->{$column}) {
- push(@$cachecolumns, $column);
- $colidx->{$column} = $#$cachecolumns;
- $columns_added = 1;
+ else {
+ return ++$serial_number{$category};
}
- $colidxref->[$colnum] = $colidx->{$column} if (ref($colidxref) eq "ARRAY");
}
- if ($columns_added) { # clear the cache
- $self->clear_cache($table);
- }
-}
+#############################################################################
+# PROTECTED METHODS
+#############################################################################
+
+=head1 Protected Methods: Metadata
+
+=cut
#############################################################################
-# set_required_columns_fetched()
+# load_rep_metadata()
#############################################################################
-=head2 set_required_columns_fetched()
+=head2 load_rep_metadata()
- * Signature: $tbd_return =
$repository->set_required_columns_fetched($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
+ * Signature: $repository->load_rep_metadata();
+ * Param: void
+ * Return: void
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $tbd_return = $repository->set_required_columns_fetched($tbd_param);
+ $self->load_rep_metadata();
+
+Initializes the repository metadata information from the config.
+
+ * List of tables (+ displayable labels)
+ * List of column types (+ displayable labels)
+
+Then it calls load_rep_metadata_auto() in order for the repository
+itself to be consulted for its metadata information.
=cut
-# $rep->set_required_columns_fetched($table);
-sub set_required_columns_fetched {
- my ($self, $table) = @_;
- my ($prikeycolumns, @prikeyidx);
- $prikeycolumns = $self->{table}{$table}{prikey};
- $self->add_columns_fetched($table, $prikeycolumns, \@prikeyidx);
- $self->{table}{$table}{prikeyidx} = \@prikeyidx;
+# load metadata about TYPES supported by the repository
+# and the list of TABLES in it.
+sub load_rep_metadata {
+ my ($self) = @_;
+
+ my ($table, $tables, $table_defs, $table_def, $native_table, $idx);
+
+ # start with the list of tables that was configured (or the empty list)
+ $tables = $self->{tables};
+ if (!defined $tables) {
+ $tables = [];
+ $self->{tables} = $tables;
}
-#############################################################################
-# clear_columns_fetched()
-#############################################################################
+ # start with the hash of tables defined (or the empty hash)
+ $table_defs = $self->{table};
+ if (!defined $table_defs) {
+ $table_defs = {};
+ $self->{table} = $table_defs;
+ }
-=head2 clear_columns_fetched()
+ # for each table named in the configuration, give it a number up front
+ for ($idx = 0; $idx <= $#$tables; $idx++) {
+ $table = $tables->[$idx];
+ $table_defs->{$table}{idx} = $idx;
+ }
- * Signature: $tbd_return = $repository->clear_columns_fetched($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
+ # for each table in the hash (random order), add them to the end
+ foreach $table (keys %$table_defs) {
+ $table_def = $table_defs->{$table};
+ $table_def->{name} = $table;
+ $table_def->{label} = $table if (! $table_def->{label});
- Sample Usage:
+ # table has not been added to the list and it's not explicitly "hidden", so
add it
+ if (!defined $table_def->{idx} && ! $table_def->{hide}) {
+ push(@$tables, $table);
+ $table_def->{idx} = $#$tables;
- $tbd_return = $repository->clear_columns_fetched($tbd_param);
+ # we're not hiding physical tables and a native table was defined, so
make an entry
+ if (! $self->{hide_physical}) {
+ $native_table = $table_def->{native_table};
+ if (defined $native_table) {
+ $table_defs->{$native_table} = $table_defs->{$table};
+ }
+ }
+ }
-=cut
+ $self->{table_labels}{$table} = $table_def->{label};
+ }
-# $rep->clear_columns_fetched ($table);
-sub clear_columns_fetched {
- my ($self, $table) = @_;
- $self->{table}{$table}{cache}{columnidx} = {};
- $self->{table}{$table}{cache}{columns} = [];
- $self->set_required_columns_fetched($table);
+ my ($type, $types, $type_defs);
+
+ # start with the hash of types defined (or the empty hash)
+ $type_defs = $self->{type};
+ if (!defined $type_defs) {
+ $type_defs = {};
+ $self->{type} = $type_defs;
+ }
+
+ # define the standard list of Repository types
+ $types = [ "string", "text", "integer", "float", "date", "time", "datetime",
"binary" ];
+ $self->{types} = $types;
+
+ # define the standard list of Repository labels
+ $self->{type_labels} = {
+ "string" => "Characters",
+ "text" => "Paragraph",
+ "integer" => "Integer",
+ "float" => "Number",
+ "date" => "Date",
+ "time" => "Time",
+ "datetime" => "Date and Time",
+ "binary" => "Binary Data",
+ };
+
+ # figure the index in the array of each type
+ for ($idx = 0; $idx <= $#$types; $idx++) {
+ $type = $types->[$idx];
+ $self->{type}{$type}{idx} = $idx;
+ }
+
+ # load up all additional information from the native metadata
+ $self->load_rep_metadata_auto();
}
#############################################################################
-# set_row_hint()
+# load_rep_metadata_auto()
#############################################################################
-=head2 set_row_hint()
+=head2 load_rep_metadata_auto()
- * Signature: $tbd_return = $repository->set_row_hint($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
+ * Signature: $repository->load_rep_metadata_auto();
+ * Param: void
+ * Return: void
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $tbd_return = $repository->set_row_hint($tbd_param);
+ $repository->load_rep_metadata_auto();
+
+Loads repository metadata from the repository itself
+(to complement metadata in the configuration and perhaps
+override it).
+
+The default implementation does nothing.
+It is intended to be overridden in the subclass
+(if the repository has any sort of metadata).
=cut
-# $rep->set_row_hint ($table, \%paramvalues);
-sub set_row_hint {
- my ($self, $table, $paramvalueshashref) = @_;
- $self->{table}{$table}{cache}{paramvalues} = { %$paramvalueshashref };
+sub load_rep_metadata_auto { # OVERRIDE IN SUBCLASS (IF DESIRED)
+ my ($self) = @_;
}
#############################################################################
-# clear_row_hint()
+# load_table_metadata()
#############################################################################
-=head2 clear_row_hint()
+=head2 load_table_metadata()
- * Signature: $tbd_return = $repository->clear_row_hint($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
+ * Signature: $self->load_table_metadata();
+ * Param: void
+ * Return: void
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $tbd_return = $repository->clear_row_hint($tbd_param);
-
-=cut
-
-# $rep->clear_row_hint ($table);
-sub clear_row_hint {
- my ($self, $table) = @_;
- $self->{table}{$table}{cache}{paramvalues} = {};
-}
-
-#############################################################################
-# get_required_columns()
-#############################################################################
+ $self->load_table_metadata();
-=head2 get_required_columns()
+First it calls load_table_metadata_auto() in order for the repository
+itself to be consulted for any metadata information for the about the
+table.
- * Signature: $tbd_return = $repository->get_required_columns($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
+Then it initializes
+the repository metadata information for that table from the config
+information.
- Sample Usage:
+ * List of columns (+ displayable labels, types)
+ * List of column types (+ displayable labels)
- $tbd_return = $repository->get_required_columns($tbd_param);
+Then it determines the set of required columns whenever selecting
+data from the table and clears the cache of selected rows
+for the table.
=cut
-# @columns = $rep->get_required_columns($table);
-sub get_required_columns {
+# load detailed metadata about a particular table, including
+# the details about each column
+sub load_table_metadata {
my ($self, $table) = @_;
- my (@columns);
-}
-
-#############################################################################
-# PUBLIC METHODS
-#############################################################################
-=head1 Public Methods: Transaction Control
+ # if it's already been loaded, don't do it again
+ return if (defined $self->{table}{$table}{loaded});
+ $self->{table}{$table}{loaded} = 1; # mark it as having been loaded
-=cut
+ my ($table_def, $columns, $column, $column_def, $idx, $native_column);
-#############################################################################
-# commit()
-#############################################################################
+ $table_def = $self->{table}{$table};
+ return if (!defined $table_def);
-=head2 commit()
+ $columns = $table_def->{columns};
+ if (! defined $columns) {
+ $columns = [];
+ $table_def->{columns} = $columns;
+ }
- * Signature: $tbd_return = $repository->commit($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
- * Throws: P5EEx::Blue::Exception::Repository
- * Since: 0.01
+ # for each column named in the configuration, give it a number up front
+ for ($idx = 0; $idx <= $#$columns; $idx++) {
+ $column = $columns->[$idx];
+ $table_def->{column}{$column}{idx} = $idx;
+ }
- Sample Usage:
+ # load up all additional information from the native metadata
+ $self->load_table_metadata_auto($table);
- $tbd_return = $repository->commit($tbd_param);
+ # for each column in the hash (random order), add them to the end
+ foreach $column (keys %{$table_def->{column}}) {
+ $column_def = $table_def->{column}{$column};
+ $column_def->{name} = $column;
+ $column_def->{label} = $column if (! $column_def->{label});
-=cut
+ # column has not been added to the list and it's not explicitly "hidden",
so add it
+ if (!defined $column_def->{idx} && ! $column_def->{hide}) {
+ push(@$columns, $column);
+ $idx = $#$columns;
+ $column_def->{idx} = $idx;
+ $column_def->{alias} = "c$idx" if (!defined $column_def->{alias});
-# $rep->commit();
-sub commit {
- my $self = shift;
- my ($table, $rows, $rowidx, $rowchange, $change, $colref, $prikeyidx);
- foreach $table (@{$self->{tables}}) {
- $prikeyidx = $self->{table}{$table}{prikeyidx};
- $rows = $self->{table}{$table}{cache}{rows};
- $rowchange = $self->{table}{$table}{cache}{rowchange};
- $colref = $self->{table}{$table}{cache}{columns};
- if ($#$rowchange > -1) {
- for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
- $change = $rowchange->[$rowidx];
- next if (!defined $change);
- if ($change eq "U") {
- $self->update_row($table, $colref, $rows->[$rowidx],
$prikeyidx);
- $rowchange->[$rowidx] = "";
- }
- elsif ($change eq "I") {
- $self->insert_row($table, $colref, $rows->[$rowidx]);
- $rowchange->[$rowidx] = "";
+ # we're not hiding physical columns and a native table was defined, so
make an entry
+ if (! $self->{hide_physical}) {
+ $native_column = $column_def->{native_column};
+ if (defined $native_column &&
+ $native_column ne $column &&
+ !defined $table_def->{column}{$native_column}) {
+ $table_def->{column}{$native_column} =
$table_def->{column}{$column};
}
}
}
+
+ $table_def->{column_labels}{$column} = $column_def->{label};
}
+
+ # if a primary key is not defined, assume it is the first column
+ #if (!defined $table_def->{prikey}) {
+ # $table_def->{prikey} = [ $table_def->{columns}[0] ];
+ #}
+
+ # predefine that certain required columns will be in the result set
+ $self->set_required_columns_fetched($table);
+ $self->clear_cache();
}
#############################################################################
-# rollback()
+# load_table_metadata_auto()
#############################################################################
-=head2 rollback()
+=head2 load_table_metadata_auto()
- * Signature: $tbd_return = $repository->rollback($tbd_param);
- * Param: $tbd_param integer
- * Return: $tbd_return integer
+ * Signature: $repository->load_table_metadata_auto();
+ * Param: void
+ * Return: void
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $tbd_return = $repository->rollback($tbd_param);
+ $self->load_table_metadata_auto();
+
+Loads metadata for an individual table from the repository itself
+(to complement metadata in the configuration and perhaps
+override it).
+
+The default implementation does nothing.
+It is intended to be overridden in the subclass
+(if the repository has any sort of metadata).
=cut
-# $rep->rollback();
-sub rollback {
- my $self = shift;
+sub load_table_metadata_auto { # OVERRIDE IN SUBCLASS (IF DESIRED)
+ my ($self, $table) = @_;
}
#############################################################################
-# PUBLIC METHODS
+# PROTECTED METHODS
#############################################################################
-=head1 Public Methods: Miscellaneous
+=head1 Protected Methods: Miscellaneous
=cut
-#############################################################################
-# serial()
-#############################################################################
+#####################################################################
+# init()
+#####################################################################
-=head2 serial()
+=head2 init()
- * Signature: $serial_num = $repository->serial($category);
- * Param: $category string
- * Return: $serial_num integer
+ * Signature: $repository->init();
+ * Signature: $repository->init($named);
+ * Param: deferConnection integer
+ * Return: void
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
Sample Usage:
- $serial_num = $repository->serial($category);
+ $self->init();
+
+Every Service constructor (Repository is derived from Service) will
+invoke the init() method near the end of object construction.
+
+The standard behavior for repositories (implemented here) in init() is
+to initialize the "numrows" and "error" attributes,
+call init2(), connect to the repository,
+and load the repository metadata.
=cut
-my %serial_number;
-sub serial {
- my ($self, $category) = @_;
- if (!defined $serial_number{$category}) {
- $serial_number{$category} = 1;
- return 1;
+sub init {
+ my ($self, $args) = @_;
+ my ($dbidriver, $dbname, $dbuser, $dbpass, $dbioptions, $dbschema);
+ my ($name);
+
+ $self->{numrows} = 0;
+ $self->{error} = "";
+
+ $self->init2($args);
+
+ if (!$self->{deferConnection} && !$self->connect()) {
+ print STDERR "Error on connect():";
+ foreach (keys %$self) {
+ print STDERR " $_=[", $self->{$_}, "]";
}
- else {
- return ++$serial_number{$category};
+ print STDERR "\n";
+ return(undef);
}
+
+ $self->load_rep_metadata();
}
#############################################################################
-# PROTECTED METHODS
+# init2()
#############################################################################
-=head1 Protected Methods:
+=head2 init2()
+
+ * Signature: $repository->init2();
+ * Signature: $repository->init2($named);
+ * Param: deferConnection integer
+ * Return: void
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $self->init2();
+
+The default behavior of init2() does nothing
+and is intended to be overridden (if necessary) in the subclass which
+implements the details of access to the physical data store.
=cut
+sub init2 { # OVERRIDE IN SUBCLASS TO GET NON-DEFAULT CAPABILITIES
+ my $self = shift;
+}
+
#############################################################################
-# Method: service_type()
+# service_type()
#############################################################################
=head2 service_type()