The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
0.57

ENHANCEMENTS:

- When MethodMaker creates 'row_column' methods, these are now get/set
methods.

- Added lookup_columns to MethodMaker option (like lookup_tables but
more flexible).  This replaces the now deprecated lookup_tables
option.  See DEPRECATIONS and INCOMPATIBILITIES for more details.

- Added the ability to make any storage cache module an LRU.  Simply
pass an lru_size parameter to Alzabo::ObjectCache when using it and
the storage module will be an LRU cache.

- Documented Alzabo's referential integrity rules in Alzabo.pm
(perldoc Alzabo).

- Added section on optimizing memory usage to Alzabo::FAQ.

- Alzabo::Runtime::Schema->join now takes a parameter called
'distinct'.  This is useful in situations where you are joining
between several tables but don't want rows back from all of them.  In
that case, it is possible that you could end up getting more
duplicates than you need.  This parameter can help you eliminate
those.

- Add the following Alzabo::Schema methods: start_transaction,
rollback, finish_transaction, run_in_transaction.

- If you have GraphViz installed the schema creator can now use it to
show you a graph of your schema.

BUG FIXES:

- Fix handling of binary attribute for MySQL columns.  Generated SQL
for creating/altering these columns may have been invalid previously.

- The rules were not catching an attempt to create a CHAR/VARCHAR
column with no length (MySQL).

- Fixed bug that caused limit to not work when there was a where
clause or order_by clause.  Reported by Ilya Martynov.

- Documented row_column option for MethodMaker.

- order_by was ignored when given to the Alzabo::Runtime::Schema->join
method.  Reported by Martin Ertl.

- When viewing an existing column in the schema creator, the three
checkboxes at the bottom were always unchecked.

- The test suite has been revamped to use Test::More.  In the process
some new tests were added and some (gulp) false positives were caught.

- The default column value wasn't being escaped in the schema creator.

DEPRECATIONS

- The Alzabo::MethodMaker option 'lookup_tables' has been deprecated.
Use the new 'lookup_columns' option instead.

INCOMPATIBILITIES:

- Alzabo::ObjectCache::Store modules now expect an object id instead
of an object for their delete_from_cache method.

- If you specify give the 'all' parameter to MethodMaker,
'lookup_tables' is no longer included.

0.56

Had to become 0.57 cause I was too hasty in uploading to CPAN.  Doh!

0.55

UPGRADE INSTRUCTIONS:

Because of changes to the internal data structures for some objects,
the saved schema files from older versions of Alzabo will no longer
work with this new version.

In the eg/ directory of this distribution, there is a script called
convert.pl that can be used to convert your schemas.

It is _crucial_ that this script be run while you still have your
_current_ version of Alzabo installed.

To repeat, DO NOT INSTALL THE NEWEST VERSION OF Alzabo BEFORE RUNNING
THIS SCRIPT!

Now that we've got that straightened out...

What this script does is read an existing schema and generate code
that you can run after installing the new version of Alzabo.  This
code will recreate your schema from scratch.

It should be noted that this script _will_ reverse the cardinalities
of the relationships in your schema.  See the entries in BUG FIXES
about this.

If you don't like this and want it the old broken way, you can run the
reverse_cardinality.pl script in the eg/ directory on your schemas.
However, you can only do this _after_ installing this new version of
Alzabo.

So the steps you should take are:

1. Backup all of your schema files (by default, these are stored under
/usr/local/alzabo).

2. Run convert.pl against each schema you have created by doing:

  perl convert.pl <schema name>

This will create a file named <schema name>_schema.pl

3. After doing this for _all_ of your schemas, install this version
Alzabo.

4. Simply run each file created by the convert.pl script.  This will
overwrite the old schema files.

If you are creating your schemas via a script, then you can use the
code generated by convert.pl to replace the code that does this.  Do
note that the cardinalities will be reversed in the generated code.
Those who are doing this will notice that the generated code seems to
contain everything twice.  This has to do with how Alzabo keeps track
of changes from one generation of a schema to the next.  Simply use
the code up to right before the generated code contains the comment
"Previous generation of schema".

ENHANCEMENTS:

- Greatly improved the flexibility of the join and *_outer_join
methods for the schema class.  It is now possible to construct
arbitrary joins between any set of tables in any manner.

- Eliminate use of transactions where not needed and shorten their
length in other places.  Also make sure failed commit triggers a
rollback.

- Get rid of silly min/max language in favor of cardinality and
dependencies.

BUG FIXES:

- Fixed a problem with syncing after the Unix time rollover to 10
digits.

- Alzabo::ForeignKey->is_many_to_one always returned false.

- Alzabo::MethodMaker was interpreting foreign key cardinality
incorrectly (backwards).  This meant it was treating one-to-many
relationships as many-to-one.  Reported by Martin Ertl.

NOTE: This fix will break code that depended on this behavior.  See
the UPGRADE INSTRUCTIONS above.

- This was also broken in Alzabo::Create::Schema->add_relation.  I
took this opportunity to rewrite the code get rid of the use of
min_max_* and replace it with cardinality and dependency, which is
easier to understand.

NOTE: This fix will break old code that created schemas
programmatically.  See the UPGRADE INSTRUCTIONS above.

DEPRECATIONS:

- The Alzabo::Runtime::RowCursor->next_row,
Alzabo::Runtime::JoinCursor->next_rows, and
Alzabo::Runtime::OuterJoinCursor->next_rows methods have all been
deprecated.  Instead, simply use the ->next method for all of them.

INCOMPATIBILITIES:

- The Alzabo::Column->null and Alzabo::Create::Column->set_null
methods (deprecated in 0.20) are gone.  Use ->nullable and
->set_nullable instead.

0.51

BUG FIXES:

- Accidentally broke foreign key display for schema creation interface
in 0.50. -- In retrospect, the bug was fixing this.  Oh well, live and
learn.

ENHANCEMENTS:

- Add ->handle method to Alzabo::Driver class, which lets you set and
get the current database handle.  Suggested by Ilya Martynov.

0.50

ENHANCEMENTS:

- There is now support for left and right outer joins.  The interface
to this may change a bit in future releases.

- Added the following methods to foreign key objects:
from_is_dependent, to_is_dependent, is_one_to_one, is_one_to_many,
is_many_to_one.

- Improved and fixed the Alzabo::MethodMaker documentation.

DEPRECATIONS:

- In some future release all references to the concept 'min_max_from'
and 'min_max_to' will go away.  Instead, relationships will be
described by their cardinality and dependencies.  This was changed in
the schema creation interface a while ago but the APIs have not yet
completely switched over (there are accessors for the new way, but the
set methods still use the old concepts).  I'll make sure that there is
a time when using these methods issues a warning about their
deprecation.

BUG FIXES:

- Fix pod merging, which broke a while back (this merges superclass
documentation into subclasses for things like Alzabo::Runtime::Table).

- The code was accidentally serializing a DBI handle, which generates
lots of useless warnings.  This wasn't affecting Alzabo's operations
as it never attempted to use the thawed handle.

- Fix handling of ENUM and SET column types for MySQL.  These were not
being allowed through properly.

- Attempting to insert a value into a column that was related to a
non-primary key column were not allowed if the value being inserted
did not match the related column in the other table, even when the
columns were not dependent on each other.  Now this is only disallowed
when the foreign key is a primary key in its own table.

0.49

BUG FIXES:

- Found out even more missing files from the MANIFEST (all related to
the schema creation interface).  Fortunately, I just discovered Perl's
"make distcheck" so this shouldn't happen in the future.

- One link each in the schema creator and data browser were using a
hard-coded .mhtml extension instead of calling
Alzabo::Config::mason_extension().  Reported by Barry Hoggard.

0.48

BUG FIXES:

- I was missing yet another file from the MANIFEST.  Thanks to Barry
Hoggard for helping me out with this.

- Fix a bug in the test number for 03-runtime.t.

0.47

ENHANCEMENTS:

- Make several of the config values settable via the Alzabo::Config
module.  Suggested by Jared Rhine.

- Transactions should now work under MySQL.  Whether it does anything
or not depends on the table type you are using.  This needs testing
though.

BUG FIXES:

- Make sure that index names are not too long.

- Added a missing file to the MANIFEST.  0.46 was missing a needed
file from the tarball.

0.46

ENHANCEMENTS:

- Column types are now canonized to be all upper case.  When multiple
keywords specify the same type ('INT' and 'INTEGER', for example), one
will be chosen.  This improves the quality of the reverse engineering
and the usability of the schema creation interface.

- You can now use SQL functions pretty much anywhere you would want
(in inserts, updates, where clauses, etc).  See the "Using SQL
Functions" section in the Alzabo.pm docs for more details.

- As a corollary to the above, the Alzabo::Runtime::Table->function
method has been created to replace the old
Alzabo::Runtime::Table->func method.  This new method takes advantage
of the new system for using SQL functions and is simpler and more
flexible.  It allows you to perform all sorts of aggregate selects.

- Added the Alzabo::Runtime::Row->select_hash method.  Requested by
Dana Powers.

DEPRECATIONS:

- The Alzabo::Runtime::Table->func method has been deprecated.

BUG FIXES:

- When adding an AUTO_INCREMENT column to an existing MySQL table, the
SQL generated would cause an error.  This has been fixed.  However, if
the table already has more than row then chances are this still won't
work (because MySQL does not try to generate needed unique values for
the column when it is added).

0.45

INCOMPATIBILITIES:

- The 'dbm_file' parameter given when loading a syncing module that
used DBM files (such as Alzabo::ObjectCache::Sync::SDBM_File) has been
changed to 'sync_dbm_file', because this release includes a new cache
storage module that uses DBM files as well.

- The schema creator now requires HTTP::BrowserDetect.

- Fix what was arguably a bug in the caching/syncing code.
Previously, one process could update a row and another process could
then update that same row.  Now the second process will throw an
exception.

BUG FIXES:

- Accidentally left debugging turned on in Alzabo::Exceptions.

- The schema creator did not allow you to remove a length or precision
setting for a column once it had been made.

- Require a length for CHAR and VARCHAR columns with MySQL.

- Add error on setting precision for any column that doesn't allow
them with MySQL.

- The interaction of caching rows and Alzabo::MethodMaker was not
right.  Basically, it was determined at compile time whether or not to
use the cached row class but this needs to be determined at run time.
This has been fixed.

- Using the Alzabo::Runtime::Row->rows_by_foreign_key method would
fail when the column in one table did not have the same name as a
column in the other table.  Reported by Michael Graham (along with a
correct diagnosis, thanks!).

- Don't specify a database name when creating or dropping a database.
Reported and patched by Dana Powers.

ENHANCEMENTS:

- Rules violations error messages (bad table name, for example) in the
schema creator are now handled in a much friendlier manner.  Instead
of the big error dump exception page it returns you to the page you
submitted from with an error message.

- Add Alzabo::Create::Column->alter method which allows you to change
the column type, length, and precision all at once.  This is necessary
because some of the column type validation code will insist that a
column have a length setting.  If you try to change them in two
separate operations it will throw an exception.

- Add Alzabo::ObjectCache::Store::Null - This allows you to use any
multi-process syncing module without using up the memory that
Alzabo::ObjectCache::Store::Memory uses.

- Add Alzabo::ObjectCache::Store::BerkeleyDB - I'm not sure if storing
in a db file is really a performance win (vs. null storage) because of
the work needed to freeze & thaw the row objects.  Benchmarks are
needed.

- Add support for fulltext indexes (MySQL).

- Don't show fulltext or column prefix options when creating indexes
for databases that don't support these features.

- Use cardinality & dependency language for relations.

- Add some style to the schema creator (via stylesheets).  It looks a
little better now.

0.44

BUG FIXES:

- Bug fix in Alzabo::Runtime::Table->set_prefetch.  Reported by Bob
Gustafson.

- Don't try to make directories when running Makefile.PL.  Save it for
later after user does 'make install'.

- Fix handling of geometric types in Postgres (they were all being
rejected as invalid).

- Drop columns from a table before adding new ones.  Sometimes this
makes a difference.  For example, if you are using MySQL and drop an
existing AUTO_INCREMENT column and add a new one that is also
AUTO_INCREMENT.

- Only allow one sequenced column per table when using MySQL.

- Doc fixes.  Thanks to Ron Savage for pointing me towards some of
these.

- Fix a bug with the schema creator.  If you attempted to make a
change to a column with an extended type and you did not change the
type, an error occurred.

ENHANCEMENTS:

- Schema creator now shows you a list of possible column types instead
of having you type it in.  However, for complex types like MySQL's
ENUM or Postgres' POLYGON there is a text box to type it in.

0.43

ENHANCEMENTS:

- Allow passing of port when executing SQL from schema creator.

- Confirm schema deletion in schema creator.

BUG FIXES:

- Quick hack to fix a problem with Alzabo::MethodMaker when using
caching.  However, this requires that the caching modules be loaded
first, before Alzabo::MethodMaker.  A more palatable fix will be in a
future release.

- Fix a problem with prefetching rows that caused row objects to
contain undefined values for certain columns.  This only happened if
you were prefetching one column.

- Fix another problem that left the schema creator still broken.

0.42

BUG FIXES:

- The schema creator was broken (for lack of quotes around one string)

- Remove 255 char limit on prefix length (this needs more research).

0.41

BUG FIXES:

- 0.40 was missing a file in the distro
(lib/Alzabo/ObjectCache/Sync/DBM.pm).

0.40

INCOMPATIBILITIES:

The classes in the ObjectCache hierarchy have been reorganized.  The
renaming is as follows:

 Alzabo::ObjectCache::MemoryStore => Alzabo::ObjectCache::Store::Memory
 Alzabo::ObjectCache::DBMSync     => Alzabo::ObjectCache::Sync::DB_File
 Alzabo::ObjectCache::IPCSync     => Alzabo::ObjectCache::Sync::IPC.pm
 Alzabo::ObjectCache::NullSync    => Alzabo::ObjectCache::Sync::Null.pm

ENHANCEMENTS:

- Document order by clauses for joins.

- Document limit clauses for joins and single table selects.

- Expand options for where clauses to allow 'OR' conditionals as well
as subgroupings of conditional clauses.

- If you set prefetch columns for a table, these are now fetched along
with other data for the table in a cursor, reducing the number of
database SELECTs being done.

- Added Alzabo::Create::Schema->clone method.  This allows you to
clone a schema object (except for the name, which must be changed as
part of the cloning process).

- Using the profiler, I have improved some of the hot spots in the
code.  I am not sure how noticeable these improvements are but I plan
to do a lot more of this type of work in the future.

- Added the Alzabo::ObjectCache::Sync::BerkeleyDB and
Alzabo::ObjectCache::Sync::SDBM_File modules.  These modules are much
faster than the old DBMSync or IPCSync modules and actually appear to
be faster than not syncing at all.  The NullSync (now Sync::Null)
module is still faster than all of them, however.

BUG FIXES:

- Reversing engineering a MySQL schema with ENUM or SET columns may
have caused an error if the values for the enum/set contained spaces.

- A bug in the schema creation interface made it impossible to create
an index without a prefix.  Reported by Sam Horrocks.

- When dropping a table in Postgres, the sequences for its columns (if
any), need to be dropped as well.  Adapted from a patch submitted by
Sam Horrocks.

- The modules needed by the schema creator and data browser are now
used by the components.  However, it is still better to load them at
server startup in order to maximize shared memory.

- Calling the object cache's clear method did not work when using the
IPCSync or NullSync modules.

- Reverse engineering a Postgres database was choking on char(n)
columns, which are converted internally by Postgres into bpchar(n)
columns.  This is now fixed (by converting them back during reverse
engineering).

- Reject column prefixes > 255 with MySQL.  I hesitate to call this a
bug fix since this appears to be undocumented in the MySQL docs.

- Using the DBMSync module in an environment which started as one user
and then became another (like Apache) may have caused permiission
problems with the dbm file.  This has been fixed.

MISC:

- Require DBD::Pg 0.97 (the latest version as of this writing) as it
fixes some bugs in earlier versions.

ARCHITECTURE:

- Split up Row object into Alzabo::Runtime::Row (base class for
standard uncached row) and Alzabo::Runtime::CachedRow (subclass for
rows that have to interact with a cache).  This simplifies the code,
particulary in terms of how it interacts with the caching system.

- Made Alzabo::Runtime::Row->get_data a private method.  This served
no purpose for end users anyway.

0.36

- Addition of Params::Validate broke several methods:
-- The Alzabo::Schema->tables method was broken when trying to
retrieve a subset of all the tables.
-- The Alzabo::Create::Schema->move_table method was broken (thus
breaking the ability to add a table at a specified place in the table
order).
-- Same problem for Alzabo::Create::Table->move_column.

- Added to the test suite to catch all this in the future.

- Attempting to dynamically generate component paths in the Mason
component was a bad idea, particularly since it was unnecessary
because I can find the component by doing '../common/foo'.  Thanks to
Bob Gustafson for suggesting this.

- Fix bug in Postgres rules that didn't allow length for CHAR columns.

- Fixed problems running multi-process tests with Postgres.

0.35

- Add ability to specify port parameter when connecting to DB for
reverse engineering/data browser.

- Fix support for host param in data browser.

- Added a new Alzabo/FAQ.pod file.  Its pretty skimpy but hopefully it
will become more useful over time.

- If your Mason component root was under your document then the links
to return to the top levels of the schema creator and data browser
were broken.  Note: if your component root is entirely outside your
document root then things may not work at all.

- Add support for extra MySQL connection params (like
mysql_default_file).  See the Alzabo::Driver::MySQL docs for more
details.

- Add support for Postgres connect params 'options' and 'tty'.

- Alzabo::Create::Schema->reverse_engineer was not passing the 'port'
parameter to the driver when attempting to make a driver.

- Attempting to pass in the port parameter to a connection would have
generated a bad DSN due to a type in the code.

- Started using Params::Validate so I can be even stricter about
argument checking.

- Fix bug introduced in 0.33.  Changing a column's type always removed
any length and precision setting for the column.  Now it is only
removed if the new column type does not allow a length or precision
setting.

- Fix some warnings in the Makefile.PL code.  Also require Pod::Man >=
1.14 to handle =head3 and =head4 directives.

- The Postgres code did not allow the ABSTIME, MACADDR, or RELTIME
column types.  These have been added.  Thanks to Bob Gustafson for
helping me find this problem.

- The Alzabo::Create::Schema->reverse_engineer method was not doing
anything with a host parameter.  Reported by Aaron Johnson.

- Fix bug in Alzabo::ObjectCache docs.  Reported by Robin Berjon.

- Include a first version of the quick method reference suggested by
Robin Berjon.  This Alzabo::QuickRef.  The HTML version is table-ized
and spiffed up a bit from the POD version.

0.34

- If you were trying to run the tests on a system without MySQL
installed, or without the DB_File or IPC::Shareable modules, you saw
lots of test failures, even if you said you did not plan to use the
parts of Alzabo that required these.  This has been fixed.  I can now
run the tests successfully using a Perl with only DBD::Pg and DBI
installed and it will skip any tests that it can't run.

- Fixed another caching bug related to objects that were deleted and
then another row was inserted with the same primary key.  Note to
self: premature optimization is the root of all evil.

0.33

- The linking table methods generated by Alzabo::MethodMaker were
broken.  Fixed this.

- Changed how order by clauses can be passed to select operations.
Also changed the docs, which were way out of sync with the changes in
this area.

- Attempting to update more than one value at once was broken.  Fixed
this.

- Added Alzabo::Runtime::Table->func method to allow arbitrary column
aggregate functions like MAX, MIN, AVG, etc.

- Fixed schema creator bug.  It was not possible to change a column's
NULLability after it was created.

- When changing a column's type, Alzabo now removes any column
attributes that are not valid for that column.  In addition, if the
existing length and precision parameters are not valid, they will be
set to undef.

- Fixed the code to get rid of weird error messages that came from DBI
with Perl 5.6.0+ when the Alzabo::Create::Schema->create or
Alzabo::Create::Schema->reverse_engineer methods were called.  For the
curious, this has to do with the DBI object passing through
Storable::dclone.

0.32

- Forgot to include data browser files in MANIFEST.  Caused weirdness
if you said you wanted it when asked during install.  Reported by Remi
Cohen-Scali.

0.31

Bug fixes only

- Fix bugs in Alzabo::MethodMaker.  The insert, update, lookup_table,
and self_relation (parent portion only) were broken.

- A bug in the SQL making code was causing some queries to appear as
if they failed when they didn't.

0.30

- The convert.pl script in eg/ has been updated to handle the new
release.  IMPORTANT: I forgot to include a mention of this in the last
release but you need to run the script _before_ installing a new
version of Alzabo.

- Many improvements and updates to Alzabo::MethodMaker.  Highlights
include fixing a bug that prevented the insert and update methods from
being created, a new callback system that allows you to specify all
the method names to be generated, and a new 'self_relations' option
for tables that have parent/child relationships with themself.

- Fix handling of NULL columns for inserts and updates.  Now, Alzabo
only throws an exception if the column is not nullable and has no
default.  If it has a default and is specified as NULL then it will
not be included in the INSERT clause (in which case the RDBMS should
insert the default value itself).

- Fix bugs in Postgres reverse engineering.  Defaults were not handled
properly, nor were numeric column type length and precision.

- The schema creator and data browser now allow you to enter the host
for database connections where needed.

- Foreign keys can now span multiple columns.  This means you can have
a relation from foo.foo_id and foo.index_id to bar.foo_id and
bar.index_id.  This required some changes to the interface for the
foreign key objects.  Notably, the Alzabo::ForeignKey->column_from and
Alzabo::ForeignKey->column_to methods are now
Alzabo::ForeignKey->columns_from and Alzabo::ForeignKey->columns_to.
In addition, the parameters given to the
Alazbo::Create::Schema->add_relation have changed.

- Major changes to caching architecture.  The caching code has been
split up.  There is now a 'storing' class, which holds onto the
objects (the cache).  Then there is a 'sync' class.  This class
handles expiration and deletion tracking.  These two classes can be
mixed and matched.  Right now there is only one storage class (which
stores the objects in memory).  There are 3 syncing classes.  One,
NullSync, doesn't actually sync objects.  It does track deletions, but
not expirations.  The others, IPCSync and DBMSync, use IPC or DBM
files to track expiration and deletion of objects.

- Doing this work highlighted some bugs in the caching/syncing code.
One oversight was that if you deleted an object and then inserted
another row with the exact same primary key, the cache continued to
think the object was deleted.  Other bugs also surfaced.  These have
been fixed and the test suite has been updated so caching should be
stable (if not, I'll have to cry).

- When viewing an existing column in the schema creator, defaults,
lengths, and precision of 0 were not being shown.

- Alzabo::Runtime::Table->row_count can now take a where clause.

- Fix bugs in Alzabo::Create::Table.  This was causing problems with
indexes when the table name was changed.

- Fixed a bug in Alzabo::Util that caused the test cases to fail if
Alzabo hadn't been previously installed.  Reported by Robert Goff.

- The SQLMaker class is now smarter about not letting you make bad
SQL.  For example, if you try to make a WHERE clause with tables not
mentioned in the FROM clause, it will throw an exception.  This will
hopefully help catch logic errors in your code a bit sooner.

- Removed use of prepare_cached in Alzabo::Driver.  This has the
potential to cause some strange errors under Alzabo.  Because of the
way Alzabo works, it is possible to have a Cursor object holding onto
a statement handle that needs to be used elsewhere (by a row object,
for example).  It is safer to let a new statement handle be created in
this case.

INCOMPATIBILITIES

- See the note above about the changes required to support
multi-column foreign keys.

- Because of the aforementioned changes to the caching architecture,
caching just does not work the way it used.

1. By default, there is no caching at all.

2. To get the old behavior, which defaulted to an in-process memory
cache with no inter-process syncing (meaning deletes are tracked but
there is no such thing as expiration), you can do this in your code:

  use Alzabo::ObjectCache( store => 'Alzabo::ObjectCache::MemoryStore',
                           sync  => 'Alzabo::ObjectCache::NullSync' );

or just:

  use Alzabo::ObjectCache;  # the above modules are the defaults

3. To get the behavior of the old Alzabo::ObjectCacheIPC module, do:

  use Alzabo::ObjectCache( store => 'Alzabo::ObjectCache::MemoryStore',
                           sync  => 'Alzabo::ObjectCache::IPCSync' );

However, the new DBMSync module will probably scale better, and
performance should be about the same for smaller applications.  To use
it, do:

  use Alzabo::ObjectCache( store => 'Alzabo::ObjectCache::MemoryStore',
                           sync  => 'Alzabo::ObjectCache::DBMSync' );

4. If you run without any caching at all then the Alzabo::Runtime::Row
class's behavior has changed somewhat.  In particular, selects or
updates against a deleted object will always throw an
Alzabo::Exception::NoSuchRow exception.  Before, the behavior wasn't
very well defined.

Please read the section on clearing the cache in the
Alzabo::ObjectCache module, as this is an important concept.  By
default, the caching and syncing modules will just grow unchecked.
You need to clear at the appropriate points (usually your
application's entry points) in order to keep them under control.


0.20

- Preliminary Postgres support.  There is no support yet for
constraints or foreign keys when reverse engineering or making SQL.
There is also no support for large objects (I'm hoping that 7.1 will
be released soon so I won't have to think about this).  Otherwise, the
support is about at the same level as MySQL support, though less
mature.

- Added Alzabo::MethodMaker module.  This can be used to auto-generate
useful methods for your schema/table/row objects based on the
properties of your objects themselves.

- Reworking/expanding/clarifying/editing of the docs.

- Add order_by and limit options whenever creating a cursor.

- Method documentation POD from the Alzabo::* modules is merged into
the relevant Alzabo::Create::* and Alzabo::Runtime::* modules during
install.  This should make it easier to find what you need since the
average user will only need to look at a few modules in
Alzabo::Runtime::*.

- Reworked exceptions so they are all now Alzabo::Exception::Something.

- Added default as a column attribute (thus there are now
Alzabo::Column->default and Alzabo::Create::Column->set_default
methods).

- Added length & precision attributes for columns.  Both are set
through the Alzabo::Create::Column->set_length method.

- This release includes a script in eg/ called convert.pl to convert
older schemas.

- Alzabo::Schema->tables & Alzabo::Table->columns now take an optional
list of tables/columns as an argument and return a list of matching
objects.

- Added Alzabo::Column->has_attribute method.

- The data browser has actually lost some functionality (the
filtering).  Making this more powerful is a fairly low priority at the
moment.

- Fix bugs where extra params passed to Alzabo::Runtime::Table->insert
were not making it to the Alzabo::Runtime::Row->new method.

- Fix for Alzabo::Runtime::Table->set_prefetch method.

- Fixed bug in handling of deleted object in Alzabo::ObjectCacheIPC
(they were never reported as deleted).

- Fix bug that caused schema to get bigger every time it was saved.

- Finally switched to regular hashes for objects.

- Added Alzabo::SQLMaker classes to handle generating SQL
in a cross-platform compatible way.

DEPRECATIONS:

- Parameters for Alzabo::Create::Column->new: 'null' parameter is now
'nullable'.  The use of the parameter 'null' is deprecated.

- Alzabo::Column->null & Alzabo::Column->set_null methods are now
Alzabo::Column->nullable & Alzabo::Column->set_nullable.  The old
methods are deprecated.

- Alzabo::Create::ForeignKey->new no longer requires table_from &
table_to params (it took me this long to realize I can get that from
the column passed in.  doh!)

INCOMPATIBILITIES:

- Alzabo::Runtime::Table->rows_where parameters have changed.  The
from parameter has been removed (use the Alzabo::Runtime::Schema->join
method instead).  The where parameter expects something different now.

- Alzabo::Runtime::Table->rows_by_where_clause method has been
removed.

- Alzabo::Runtime::Schema->join method's where parameter expects
something different.

0.10_5

- You can now specify a database name to be used for testing.  The
default is 'test_alzabo'.  This a good default for MySQL, at least.
Thanks to Randal Schwartz for the help.

- Make sure test file cleanup is done _before_ attempting tests so
that files from a test previously aborted are cleaned up (and no
errors are generated.  Thanks to Randal Schwartz for the bug report.

- Doesn't fail on install for Mason components if no Mason component
extension was given.  Thanks _again_ to Randal for working with me on
this in IRC late at night.

0.10_4

- Fix Makefile.PL bug

- Auto select a column when adding a relation (if there is a logical
one to select).

0.10_3

- Fix bug with deleting foreign key objects from tables.

0.10

**FIRST BETA VERSION**

- Doc bug fixes in Alzabo::Runtime::Schema.

- Fix fact that Alzabo::Runtime::Row rows_by_foreign_key method could
return either a Row _or_ RowCursor object.  Now it always returns a
cursor object.

- Fix fact that no_cache parameter was not propagated through the
RowCursor object to the rows it created.

- Add all all_rows method to Alzabo::Runtime::RowCursor.

- Add ability to reset instantiation flag in schema creation
interface.

- Updated INSTALL to mention how to get the schema creator and data
browser working.

- Finally make creating relations between tables _without_ specifying
the columns work.  This does some, IMHO, pretty cool DWIMmery.

- Added primary_key param to Alzabo::Runtime::Table make_column
method.

- Added set_host and host methods to Alzabo::Runtime::Schema.

- Added drop method to Alzabo::Create::Schema and necessary support in
driver modules.

- Changed 'id' param to 'pk' for Alzabo::Runtime::Table row_by_pk
method.  'id' still works, for now, but is deprecated.

- Fix problem where an insert could generate a referential integrity
exception but still end up in the database.  Note, without
transactions (in MySQL, for example), there's no way to make the all
of the referential integrity code work correctly 100% of the time.

- Added new class Alzabo::ObjectCache to make sure that objects stay
in sync after referential integrity operations happen.  This is now
the default caching class.  Please make sure to read the docs for this
new module, particularly if you're running Alzabo under a persistent
environment where this module can be quite the memory hog if not used
properly (clear the cache!).

- Fixed breakage in maintenance of referential integrity caused by
switch to cursors (and me not fixing all the code that expected row
objects).

- Added Alzabo::Runtime::Cursor base class.

- Added join method to Alzabo::Runtime::Schema.  *EXPERIMENTAL*

- Added Alzabo::Runtime::JoinCursor class.  *EXPERIMENTAL*

- Began conversion of all classes from pseudohash to hash.

- Both schema creator and data browser now respect user choice of
component extension.

0.09

- MAJOR CHANGE: All the Alzabo::Runtime::Row methods that used to
return lists of rows now return the new Alzabo::Runtime::RowCursor
object.  This change is a major speed and memory optimization.  It
does, however, break the old interface.  But its worth it.

- Set autohandlers for schema maker and data browser so that they
won't inherit from other autohandlers higher up the directory tree.

- Fix bug in Alzabo::Driver which made it so that the one_row_hash
method always returned a hash with keys.  This caused spurious row
object to be created in the Alzabo::Runtime::Row class.

- Fix bug in Alzabo::Table::rows_where method where it wasn't handling
the construct $table->rows_where( where => { foo => undef } )
properly.

0.08

- Lazy column evaluation had made it possible to create an
Alzabo::Runtime::Row object that did not correspond to any data in the
database if its table object did specify any rows to prefetch.  This
would have only been discovered later by calling the select method on
a non-primary key column.  This hole was plugged.

- As a corollary to the above change methods in Alzabo::Runtime::Table
that produce rows now always return an empty list or undef when the
rows cannot be made because the specified primary key doesn't exist.
Previously, the rows_by_where_clause method did this while others
would cause an exception either during the object creation or later,
depending upon the situation described above.

- GENERAL NOTE: I probably used exceptions too much, as in the above
case.  I will probably be making a few more changes like this in the
future.

- Bug fix in Alzabo::RDBMSRules when making SQL diffs.  Forgot to
account for new foreign key method names.

- Bug fix related to MySQL auto_increment column and
Alzabo::Runtime::Table insert method.  Basically, you couldn't insert
an to a table and use its auto_increment feature.

- Alzabo::Table::set_prefetch now makes sure that primary key columns
are not included.  It simply ignores them but they will not be
returned by the prefetch method.

- fix bug where some row retrieval methods would fail if not given a
'bind' parameter.

- Doc bug fix.  Docs for Alzabo::Runtime::Table listed group_by_column
as simply group.  Of course, this probably only needs to be used by
Alzabo::Runtime::Row anyway.

- Added Alzabo::Runtime::Table rows_where method.

- Added Alzabo::Runtime::Table all_rows method.

- Documented 'bind' parameter for Alzabo::Runtime::Table
rows_by_where_clause method.

0.07

- Fixed major bugs in Alzabo::Runtime::Table::insert method.

- Fixed bug in Alzabo::Runtime::Row::delete method related to API
change in 0.06

- Reduce amount of work done in Alzabo::Runtime::Row when referential
integrity maintenance is set to false.

- Added new method to Alzabo::Runtime::Row: rows_by_foreign_key.  A
row can now fetch the rows that are related to it automatically.

- Made all Alzabo::Table foreign key object returning methods
list/scalar context sensitive.  This is useful when you know that
there is only one foreign key that matches what you are looking for.

0.06

- change return value from Alzabo::Index id method to be something
that can be an actual index name.  This is a bug fix as previously
index SQL was not valid (at least not for MySQL).

- cosmetic fixes in schema creator

- moved exception component to common mason files so its shared by
schema creator and data browser.

- added Index attribute of unique (so we can make unique indexes).

- made SQL making code for MySQL aware of this.

- added ability to set this to schema creator.

- added ability to specify column order in an index in schema creator.

- made it possible for a table to have more than one foreign from a
given column.  documented how this changes API in Alzbo::Table.

- API: The Alzabo::Table foreign_keys() method name has been changed
to all_foreign_keys().  The foreign_key method (which returns keys by
table to and column from) is now the foreign_keys() method because it
can return more than one object.

- change schema creator, Alzabo::Create::Schema module, and
03/create.t test to handle this properly.

- added ability to move columns and tables to arbitrary new locations
after they've been created (without the arrows).

0.05

- bug fix for Alzabo::Runtime::Row calling wrong method from schema
object

- got rid of the locking stuff in the MySQL driver.  Since its not
possible to have more than 1 lock at a time with the GET_LOCK function
there's no way to have the right kinds of locks for cascading deletes.
It might be possible to do this kind of locking via some other
mechanism (semaphores, DBM files, whatever, but that's a hack for
another day.

0.04

- Switched to use Tie::IxHash object interface

- fixed stupid bug in Alzabo::RDBMSRules::MySQL

- changed the way Alzabo::ChangeTracker works.  it requires fewer
method calls to do its job now.

- added set_referential_integrity/referential_integrity methods to
Alzabo::Runtime::Schema.  The default is to not attempt to maintain
referential_integrity.

- It should no longer be possible for Alzabo::Runtime::ForeignKey
objects to create loops when maintaining referential integrity.  It
also should be a bit more efficient in the register_delete method.  If
no action needs to be taken, it won't loop through all the rows in the
related table before finding this out.

- fixed data browser bug when putting in a filter on any page that was
not the first page of results for a table.

- fixed data browser bug in paging with filters.

0.03

- Fixed bugs in Alzabo::ObjectCacheIPC so it now works.

- Added lazy column evaluation (see Alzabo::Runtime::Table) docs

- Added Alzabo::DriverStatement and Alzabo::Driver::Exception to Alzabo::Driver

- improved data browser memory efficiency

- minor bug fixes (bad links) in data browser and schema maker

- minor buglet fix in Alzabo::Driver::MySQL

- big fix to how Alzabo::Runtime::Schema is saved from
Alzabo::Create::Schema.  Previous implementation was accidentally
saving both the runtime and create versions at once.  The new version
fixes this.