DBIx-VersionedSubs

 view release on metacpan or  search on metacpan

README.mkdn  view on Meta::CPAN


This module implements a minimal driver to load 
your application code from a database into a namespace
and to update that code whenever the database changes.

# TABLES USED

This module uses two tables in the database, `code_live` and `code_history`.
The `code_live` table stores the current version of the code and is used to
initialize the namespace. The `code_history` table stores all modifications
to the `code_live` table, that is, insertions, deletions and modifications
of rows in it. It is used to determine if the code has changed and what
changes to apply to the namespace to bring it up to par with the
database version.

The two tables are presumed to have a layout like the following:

    create table code_live (
        name varchar(256) not null primary key,
        code varchar(65536) not null
    );

    create table code_history (
        version integer primary key not null,
        timestamp varchar(15) not null,
        name varchar(256) not null,
        action varchar(1) not null, -- IUD, redundant with old_* and new_*
        old_code varchar(65536) not null,
        new_code varchar(65536) not null
    );

Additional columns are ignored by this code. It is likely prudent
to create an index on `code_history.version` as that will be used
for (descending) ordering of rows.

# CLASS METHODS

## `Package->setup`

Sets up the class data defaults:

    code_source  => {}
    code_live    => 'code_live',
    code_history => 'code_history',
    code_version => 0,
    verbose      => 0,

`code_source` contains the Perl source code for all loaded functions.
`code_live` and `code_history` are the names of the two tables
in which the live code and the history of changes to the live code
are stored. `code_version` is the version of the code when it
was last loaded from the database.

The `verbose` setting determines if progress gets output to
`STDERR`.
Likely, this package variable will get dropped in favour of
a method to output (or discard) the progress.

## `Package->connect DSN,User,Pass,Options`

Connects to the database with the credentials given.

If called in void context, stores the DBI handle in the
`dbh` accessor, otherwise returns the DBI handle.

If you already have an existing database handle, just
set the `dbh` accessor with it instead.

## `Package->create_sub NAME, CODE`

Creates a subroutine in the Package namespace.

If you want a code block to be run automatically
when loaded from the database, you can name it `BEGIN`.
The loader code basically uses

    package $package;
    *{"$package\::$name"} = eval "sub { $code }"

so you cannot stuff attributes and other whatnot 
into the name of your subroutine, not that you should.

One name is special cased - `BEGIN` will be immediately
executed instead of installed. This is most likely what you expect.
As the code elements are loaded by `init_code` in alphabetical
order on the name, your `Aardvark` and `AUTOLOAD` subroutines
will still be loaded before your `BEGIN` block runs.

The `BEGIN` block will be called with the package name in `@_`.

Also, names like `main::foo` or `Other::Package::foo` are possible
but get stuffed below `$package`. The practice doesn't get saner there.

## `Package->eval_sub PACKAGE, NAME, CODE`

Helper method to take a piece of code and to return
a code reference with the correct file/line information.

Raises a warning if code doesn't compile. Returns
the reference to the code or `undef` if there was an error.

## `Package->destroy_sub $name`

Destroy the subroutine named `$name`. For the default
implementation, this replaces the subroutine with a
dummy subroutine that `croak`s.

## `Package->live_code_version`

Returns the version number of the live code
in the database.

This is done with a ` SELECT max(version) FROM ... ` query,
so this might scale badly on MySQL which (I hear) is bad
with queries even against indexed tables. If this becomes
a problem, changing the layout to a single-row table which
stores the live version number is the best approach.

## `Package->init_code`

Adds / overwrites subroutines/methods in the Package namespace



( run in 0.865 second using v1.01-cache-2.11-cpan-39bf76dae61 )