=pod

=head1 NAME

UR::DataSource - manage the the relationship between objects and a specific storage system 

=head1 SYNOPSIS

  package MyApp::DataSource::DB;
   
  class MyApp::DataSource::DB {
      is => ['UR::DataSource::Oracle','UR::Singleton'],
  };
  sub server { 'main_db_server' }
  sub login  { 'db_user' }
  sub auth   { 'db_passwd' }
  sub owner  { 'db_owner' }
  1;

=head1 DESCRIPTION

Data source instances represent a logical source of data to the application.
Most of them are likely to be some kind of relational database, but not all
are.  UR::DataSource is an abstract base class inherited by other data
sources.

In normal use, your data sources will probably inherit from an abstract
data source class such as L<UR::DataSource::Oracle> or
L<UR::DataSource::File>, as well as L<UR::Singleton>.  This makes it easy
to link classes to this data source, since the class name will be the
same as its ID, and the module autoloader will instantiate it automatically.

=head1 INHERITANCE

L<UR::Object>

=head1 Methods

User applications will seldom interact with data sources directly.

=over 4

=item autogenerate_new_object_id_for_class_name_and_rule

  my $id = $datasource->autogenerate_new_object_id_for_class_name_and_rule($class,$boolexpr);

L<UR::Object::Type> calls this when the application calls create() on a
class to create a new instance, but does not specify a value for the ID
property.  The default implementation throws an exception with C<die>,
but L<UR::DataSource::RDBMS> is able to query a sequence in the database
to generate unique IDs.  A developer implementing a new data source will
need to override this method and provide a sensible implementation.

=item next_dummy_autogenerated_id

  my $int = $datasource->next_dummy_autogenerated_id()

In a testing situation, is often preferable to avoid using the database's
sequence for ID autogeneration but still make ID values that are unique.
L<UR::DataSource::RDBMS> calls this method if the
L</use_dummy_autogenerated_ids> (see below) flag is true.  The IDs generated
by this method are unique during the life of the process.  In addition,
objects with dummy-generated IDs will never be saved to a real data source
during UR::Context::commit().

=item use_dummy_autogenerated_ids

  $bool = $datasource->use_dummy_autogenerated_ids();
  $datasource->use_dummy_autogenerated_ids($bool);

Get or set a flag controlling how object IDs are autogenerated.  Data source
child classes should look at the value of this flag inside their
implementation of C<autogenerate_new_object_id_for_class_name_and_rule>.  If
true, they should call C<next_dummy_autogenerated_id> and return that value
instead of attempting to generate an ID on their own.  This flag is also 
tied to the UR_USE_DUMMY_AUTOGENERATED_IDS environment variable.

=item resolve_data_sources_for_rule

  $possibly_other_data_source = $data_source->resolve_data_sources_for_rule($boolexpr);

When L<UR::Context> is determining which data source to use to process a
get() request, it looks at the class metadata for its data source, and then
calls C<resolve_data_sources_for_rule> to give that data source a chance to
defer to another data source.

=item create_iterator_closure_for_rule_template_and_values

  $subref = $datasource->create_iterator_closure_for_rule_template_and_values(
                             $boolexpr_tmpl,
                             @values
                         );

A front-end for the more widely used L</create_iterator_closure_for_rule>

=item create_iterator_closure_for_rule

  $subref = $datasource->create_iterator_closure_for_rule($boolexpr);

This is the main entry point L<UR::Context> uses to get data from its
underlying data sources.  There is no default implementation; each subclass
implementing specific data source types must supply its own code.

The method must accept a L<UR::BoolExpr> $boolexpr (rule), and return a
subref.  Each time the subref is called it must return one arrayref of data
satisfying the rule, and undef when there is no more data to return.

=item _sync_database

  $bool = $datasource->_sync_database(changed_objects => $listref);

Called by L<UR::Context> commit().  $listref will contain all the changed
objects that should be saved to that data source.  The default implementation
prints a warning message and returns true without saving anything.
L<UR::DataSource::RDBMS> has a functioning _sync_database() capable of
generating SQL to update, insert and delete rows from the database's tables.

The data source should return true if all the changes were successfully 
made, false if there were problems.  

=item commit

  $bool = $datasource->commit()

Called by L<UR::Context> commit().  After all data sources return true from
_sync_database(), C<commit> must make those changes permanent.  For
RDBMS-type data sources, this commits the transaction.  

Return true if the commit is successful, false otherwise.

=item rollback

  $bool = $datasource->rollback()

Called by L<UR::Context/commit> if any data sources has problems during 
_sync_database or commit.  It is also called by L<UR::Context/rollback>.
Data sources should reverse any changes applied during a prior
C<_sync_database> that has not been made permanent by C<commit>.

=item get_default_handle

  $scalar = $datasource->get_default_handle();

Should return the "handle" associated with any underlying logical data.  For
an RDBMS data source, this is the L<DBI> database handle.  For a file-based
data source, this is the <IO::File> file handle.

=item create_from_inline_class_data

  $datasource = $data_source_class_name->create_from_inline_class_data(
                                             $class_data_hashref,
                                             $datasource_data_hashref
                                         );

Called by the class initializer when a class definition contains an in-line 
data source definition.  See
L<UR::Object::Type::Initializer/Inline Data Sources>.

=item _ignore_table

  $bool = $datasource->_ignore_table($table_name);

Used to indicate whether the C<ur update classes> command should create a
class for the named table or not.  If _ignore_table() returns true, then
it will not create a class.

=back

=head1 Internal API Methods

=over 4

=item _get_class_data_for_loading

=item _generate_class_data_for_loading

  $hashref = $datasource->_resolve_query_plan($class_meta);

These two methods are called by L<UR::Context> as part of the object loading
process.  C<_generate_class_data_for_loading> collects information about a
class and its metadata, such as property names, subclassing information and
tables connected to the class, and stores that data inside the class's
metadata object.

C<_get_class_data_for_loading> is the main entry point; it calls 
C<_generate_class_data_for_loading> if the data has not been generated and
cached yet, and caches the data in the class metadata object.

=item _resolve_query_plan

=item _generate_template_data_for_loading

  $hashref = $datasource->_resolve_query_plan($boolexpr_tmpl);

These two methods are called by L<UR::Context> as part of the object loading
process.  C<_generate_template_data_for_loading> collects information from 
the L<UR::BoolExpr::Template> $boolexpr_tmpl (rule template) and returns a
hashref used later by the data source.  This hashref includes hints about
what classes will be involved in loading the resulting data, how those
classes are joined together and how columns in the underlying query against
the data source will map to properties of the class.

C<_resolve_query_plan> is the main entry point; it calls
C<_generate_template_data_for_loading> if the data has not been generated and
cached yet, and caches the data in the rule template object.

=item _generate_loading_templates_arrayref

  my $listref = $datasource->_generate_loading_templates_arrayref($listref);

Called by _generate_template_data_for_loading().  The input is a listref of
listrefs about properties involved in a query.  The second-level data is
sets of quads:

=over

=item 1.
The class object for this property

=item 2.
The property metadata object

=item 3.
The database table name the data will come from

=item 4
The "object number", starting with 0.  This is used in
inheritance or delegation where a table join will be required.

=back

It returns a listref of hashrefs, one hashref for every class involved in
the request; usually just 1, but can be more than one if inheritance or
delegation is involved.  The data includes information about the class's
properties, ID properties, and which columns of the result set the 
values will be found.

=back

=head1 MetaDB

Each Namespace created through C<ur define namespace> will have a data source
called the MetaDB.  For example, the MyApp namespace's MetaDB is called
MyApp::DataSource::Meta.  The MetaDB is used to store information about the
schemas of other data sources in the database.  UR itself has a MetaDB with
information about the MetaDB's schema, called L<UR::DataSource::Meta>.


=head1 SEE ALSO

=over 4

=item L<UR::DataSource::RDBMS>

The base class for relational database Data Sources, such as
L<UR::DataSource::Oracle>, L<UR::DataSoure::Pg>, L<UR::DataSource::MySQL>
and L<UR::DataSource::SQLite>

=item L<UR::DataSource::File>,

The base class for comma/tab delimited files

=item L<UR::DataSource::FileMux>

The base class for file multiplexor data sources.

=back

L<UR::Context>, L<UR::DataSource::Meta>