=pod
=head1 NAME
UR::DataSource - manage the the relationship between objects and a specific storage
system
=head1 SYNOPSIS
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>