[Bast-commits] r4955 - in DBIx-Class/0.08/branches/view_support: .
lib/DBIx lib/DBIx/Class lib/DBIx/Class/InflateColumn
lib/DBIx/Class/Manual lib/DBIx/Class/Storage/DBI maint t
t/examples/Schema t/lib t/lib/DBICTest/Schema
matthewt at dev.catalyst.perl.org
matthewt at dev.catalyst.perl.org
Thu Oct 23 14:37:14 BST 2008
Author: matthewt
Date: 2008-10-23 14:37:14 +0100 (Thu, 23 Oct 2008)
New Revision: 4955
Modified:
DBIx-Class/0.08/branches/view_support/
DBIx-Class/0.08/branches/view_support/Changes
DBIx-Class/0.08/branches/view_support/Makefile.PL
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/InflateColumn/File.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Example.pod
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Schema.pm
DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/SQLite.pm
DBIx-Class/0.08/branches/view_support/maint/gen-schema.pl
DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t
DBIx-Class/0.08/branches/view_support/t/47bind_attribute.t
DBIx-Class/0.08/branches/view_support/t/54taint.t
DBIx-Class/0.08/branches/view_support/t/63register_class.t
DBIx-Class/0.08/branches/view_support/t/64db.t
DBIx-Class/0.08/branches/view_support/t/71mysql.t
DBIx-Class/0.08/branches/view_support/t/72pg.t
DBIx-Class/0.08/branches/view_support/t/746mssql.t
DBIx-Class/0.08/branches/view_support/t/74mssql.t
DBIx-Class/0.08/branches/view_support/t/77prefetch.t
DBIx-Class/0.08/branches/view_support/t/81transactions.t
DBIx-Class/0.08/branches/view_support/t/93nobindvars.t
DBIx-Class/0.08/branches/view_support/t/93storage_replication.t
DBIx-Class/0.08/branches/view_support/t/94versioning.t
DBIx-Class/0.08/branches/view_support/t/96multi_create.t
DBIx-Class/0.08/branches/view_support/t/98savepoints.t
DBIx-Class/0.08/branches/view_support/t/bindtype_columns.t
DBIx-Class/0.08/branches/view_support/t/examples/Schema/testdb.pl
DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm
DBIx-Class/0.08/branches/view_support/t/lib/DBICTest/Schema/Artist.pm
DBIx-Class/0.08/branches/view_support/t/lib/sqlite.sql
Log:
r24683 at agaton (orig r4900): ribasushi | 2008-10-07 11:25:36 +0100
Schema::Versioned test cleanups:
- Add a test exposing a lapse in design resulting in intermittent test failures
- Add a number of tests to trap expected warnings
- Cleanup the temp dir after the test, set DBICTEST_KEEP_VERSIONING_DDL to override
r24684 at agaton (orig r4901): ribasushi | 2008-10-07 13:51:09 +0100
duh
r24685 at agaton (orig r4902): ribasushi | 2008-10-07 15:02:04 +0100
Another round of warning-squashing:
Fix source registration/unregistration in several places
Accomodate postgres being really load on CREATE
Move the taint tests to a non-mainstream schema - hopefully this one will not be disturbed for a while
Fix warning due to File::Copy being sloppy
Test for TxnScopeGuard warnings
Test for multiple register_class warnings
Blindly silence a weird warning within a TODO in t/47bind_attribute.t. Hopefully when the TODO is resolved, it will be obvious what was causing it
r24686 at agaton (orig r4903): ribasushi | 2008-10-07 15:15:03 +0100
Silence SQLite ->disconnect warnings
r24689 at agaton (orig r4906): matthewt | 2008-10-07 18:32:00 +0100
increase Test::Warn dependency
r24717 at agaton (orig r4908): castaway | 2008-10-07 23:17:14 +0100
Add documentation to indicate that calling find, find_or_new, find_or_create or update_or_create with primary key values of undef, is a bad idea.
r24718 at agaton (orig r4909): ribasushi | 2008-10-08 10:46:18 +0100
Minor documentation patch by Flavio Poletti - remove useless prefetch from examples
r24719 at agaton (orig r4910): ribasushi | 2008-10-09 12:19:28 +0100
Regenerate (finally\!) t/lib/sqlite.sql
Fix maint/gen-schema to work correctly with newer SQL::Translators
r24720 at agaton (orig r4911): ribasushi | 2008-10-09 12:47:39 +0100
Add new column with a default to Artist, adjust tests as necessary (no functional changes)
r24721 at agaton (orig r4912): castaway | 2008-10-11 15:56:14 +0100
Modernise docs
r24722 at agaton (orig r4913): castaway | 2008-10-11 18:07:00 +0100
Modernised and rearranged docs massively into a saner order.
r24727 at agaton (orig r4918): ribasushi | 2008-10-12 22:26:54 +0100
TODOify the 'upgrade twice within a second' problem in Schema::Versioned
r24728 at agaton (orig r4919): ribasushi | 2008-10-12 22:54:53 +0100
Downgrading multi-prefetch exception to a warning as per Moritz Onken, adjusting tests
r24729 at agaton (orig r4920): ribasushi | 2008-10-12 22:56:50 +0100
Fix omission in pg test
r24888 at agaton (orig r4923): purge | 2008-10-16 14:41:18 +0100
patch ->delete to die if args
r24889 at agaton (orig r4924): ribasushi | 2008-10-16 19:29:38 +0100
Failing tests for multicreate over m2m (passes with 0.08010)
Property changes on: DBIx-Class/0.08/branches/view_support
___________________________________________________________________
Name: svk:merge
- 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:1639
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:4895
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
+ 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:1639
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:4924
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
Modified: DBIx-Class/0.08/branches/view_support/Changes
===================================================================
--- DBIx-Class/0.08/branches/view_support/Changes 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/Changes 2008-10-23 13:37:14 UTC (rev 4955)
@@ -1,5 +1,5 @@
Revision history for DBIx::Class
-
+ - delete throws exception if passed arguments to prevent drunken mishaps. (purge)
- Fix storage to copy scalar conds before regexping to avoid
trying to modify a constant in odd edge cases
- Related resultsets on uninserted objects are now empty
Modified: DBIx-Class/0.08/branches/view_support/Makefile.PL
===================================================================
--- DBIx-Class/0.08/branches/view_support/Makefile.PL 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/Makefile.PL 2008-10-23 13:37:14 UTC (rev 4955)
@@ -31,7 +31,7 @@
test_requires 'DBD::SQLite' => 1.13;
test_requires 'Test::Builder' => 0.33;
-test_requires 'Test::Warn' => 0.08;
+test_requires 'Test::Warn' => 0.11;
test_requires 'Test::NoWarnings' => 0.08;
test_requires 'Test::Exception' => 0;
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/InflateColumn/File.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/InflateColumn/File.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/InflateColumn/File.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -95,9 +95,11 @@
my $fs_file = $self->_file_column_file($column, $value->{filename});
mkpath [$fs_file->dir];
-
- File::Copy::copy($value->{handle}, $fs_file);
+ # File::Copy doesn't like Path::Class (or any for that matter) objects,
+ # thus ->stringify (http://rt.perl.org/rt3/Public/Bug/Display.html?id=59650)
+ File::Copy::copy($value->{handle}, $fs_file->stringify);
+
$self->_file_column_callback($value, $self, $column);
return $value->{filename};
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Example.pod
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Example.pod 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Manual/Example.pod 2008-10-23 13:37:14 UTC (rev 4955)
@@ -220,7 +220,6 @@
},
{
join => [qw/ cd /],
- prefetch => [qw/ cd /]
}
);
while (my $track = $rs->next) {
@@ -273,7 +272,6 @@
},
{
join => [qw/ artist /],
- prefetch => [qw/ artist /]
}
);
while (my $cd = $rs->next) {
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSet.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -307,7 +307,7 @@
=item Arguments: @values | \%cols, \%attrs?
-=item Return Value: $row_object
+=item Return Value: $row_object | undef
=back
@@ -1297,7 +1297,8 @@
sub delete {
my ($self) = @_;
-
+ $self->throw_exception("Delete should not be passed any arguments")
+ if $_[1];
my $cond = $self->_cond_for_update_delete;
$self->result_source->storage->delete($self->result_source, $cond);
@@ -1512,7 +1513,7 @@
=item Arguments: \%vals
-=item Return Value: $object
+=item Return Value: $rowobject
=back
@@ -1649,16 +1650,33 @@
=item Arguments: \%vals, \%attrs?
-=item Return Value: $object
+=item Return Value: $rowobject
=back
-Find an existing record from this resultset. If none exists, instantiate a new
-result object and return it. The object will not be saved into your storage
+ my $artist = $schema->resultset('Artist')->find_or_new(
+ { artist => 'fred' }, { key => 'artists' });
+
+ $cd->cd_to_producer->find_or_new({ producer => $producer },
+ { key => 'primary });
+
+Find an existing record from this resultset, based on it's primary
+key, or a unique constraint. If none exists, instantiate a new result
+object and return it. The object will not be saved into your storage
until you call L<DBIx::Class::Row/insert> on it.
+You most likely want this method when looking for existing rows using
+a unique constraint that is not the primary key, or looking for
+related rows.
+
If you want objects to be saved immediately, use L</find_or_create> instead.
+B<Note>: C<find_or_new> is probably not what you want when creating a
+new row in a table that uses primary keys supplied by the
+database. Passing in a primary key column with a value of I<undef>
+will cause L</find> to attempt to search for a row with a value of
+I<NULL>.
+
=cut
sub find_or_new {
@@ -1747,13 +1765,14 @@
=item Arguments: \%vals, \%attrs?
-=item Return Value: $object
+=item Return Value: $rowobject
=back
- $class->find_or_create({ key => $val, ... });
+ $cd->cd_to_producer->find_or_create({ producer => $producer },
+ { key => 'primary });
-Tries to find a record based on its primary key or unique constraint; if none
+Tries to find a record based on its primary key or unique constraints; if none
is found, creates one and returns that instead.
my $cd = $schema->resultset('CD')->find_or_create({
@@ -1774,12 +1793,18 @@
{ key => 'cd_artist_title' }
);
-Note: Because find_or_create() reads from the database and then
+B<Note>: Because find_or_create() reads from the database and then
possibly inserts based on the result, this method is subject to a race
condition. Another process could create a record in the table after
the find has completed and before the create has started. To avoid
this problem, use find_or_create() inside a transaction.
+B<Note>: C<find_or_create> is probably not what you want when creating
+a new row in a table that uses primary keys supplied by the
+database. Passing in a primary key column with a value of I<undef>
+will cause L</find> to attempt to search for a row with a value of
+I<NULL>.
+
See also L</find> and L</update_or_create>. For information on how to declare
unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
@@ -1799,11 +1824,11 @@
=item Arguments: \%col_values, { key => $unique_constraint }?
-=item Return Value: $object
+=item Return Value: $rowobject
=back
- $class->update_or_create({ col => $val, ... });
+ $resultset->update_or_create({ col => $val, ... });
First, searches for an existing row matching one of the unique constraints
(including the primary key) on the source of this resultset. If a row is
@@ -1823,6 +1848,14 @@
{ key => 'cd_artist_title' }
);
+ $cd->cd_to_producer->update_or_create({
+ producer => $producer,
+ name => 'harry',
+ }, {
+ key => 'primary,
+ });
+
+
If no C<key> is specified, it searches on all unique constraints defined on the
source, including the primary key.
@@ -1831,6 +1864,12 @@
See also L</find> and L</find_or_create>. For information on how to declare
unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
+B<Note>: C<update_or_create> is probably not what you want when
+looking for a row in a table that uses primary keys supplied by the
+database, unless you actually have a key value. Passing in a primary
+key column with a value of I<undef> will cause L</find> to attempt to
+search for a row with a value of I<NULL>.
+
=cut
sub update_or_create {
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/ResultSource.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -973,11 +973,16 @@
if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
keys %{$collapse}) {
my ($last) = ($fail =~ /([^\.]+)$/);
- $self->throw_exception(
- "Can't prefetch multiple has_many rels ${last} and ${pre}"
- .(length($as_prefix) ? "at the same level (${as_prefix})"
- : "at top level"
- ));
+ carp (
+ "Prefetching multiple has_many rels ${last} and ${pre} "
+ .(length($as_prefix)
+ ? "at the same level (${as_prefix}) "
+ : "at top level "
+ )
+ . 'will currently disrupt both the functionality of $rs->count(), '
+ . 'and the amount of objects retrievable via $rs->next(). '
+ . 'Use at your own risk.'
+ );
}
#my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
# values %{$rel_info->{cond}};
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Schema.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Schema.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Schema.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -29,12 +29,12 @@
package Library::Schema;
use base qw/DBIx::Class::Schema/;
- # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
- __PACKAGE__->load_classes(qw/CD Book DVD/);
+ # load all Result classes in Library/Schema/Result/
+ __PACKAGE__->load_namespaces();
- package Library::Schema::CD;
+ package Library::Schema::Result::CD;
use base qw/DBIx::Class/;
- __PACKAGE__->load_components(qw/PK::Auto Core/); # for example
+ __PACKAGE__->load_components(qw/Core/); # for example
__PACKAGE__->table('cd');
# Elsewhere in your code:
@@ -47,7 +47,7 @@
my $schema2 = Library::Schema->connect($coderef_returning_dbh);
- # fetch objects using Library::Schema::DVD
+ # fetch objects using Library::Schema::Result::DVD
my $resultset = $schema1->resultset('DVD')->search( ... );
my @dvd_objects = $schema2->resultset('DVD')->search( ... );
@@ -61,195 +61,186 @@
carefully, as DBIx::Class does things a little differently. Note in
particular which module inherits off which.
-=head1 METHODS
+=head1 SETUP METHODS
-=head2 register_class
+=head2 load_namespaces
=over 4
-=item Arguments: $moniker, $component_class
+=item Arguments: %options?
=back
-Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
-calling:
+ __PACKAGE__->load_namespaces();
- $schema->register_source($moniker, $component_class->result_source_instance);
+ __PACKAGE__->load_namespaces(
+ result_namespace => 'Res',
+ resultset_namespace => 'RSet',
+ default_resultset_class => '+MyDB::Othernamespace::RSet',
+ );
-=cut
+With no arguments, this method uses L<Module::Find> to load all your
+Result classes from a sub-namespace F<Result> under your Schema class'
+namespace. Eg. With a Schema of I<MyDB::Schema> all files in
+I<MyDB::Schema::Result> are assumed to be Result classes.
-sub register_class {
- my ($self, $moniker, $to_register) = @_;
- $self->register_source($moniker => $to_register->result_source_instance);
-}
+It also finds all ResultSet classes in the namespace F<ResultSet> and
+loads them into the appropriate Result classes using for you. The
+matching is done by assuming the package name of the ResultSet class
+is the same as that of the Result class.
-=head2 register_source
+You will be warned if ResulSet classes are discovered for which there
+are no matching Result classes like this:
-=over 4
+ load_namespaces found ResultSet class $classname with no corresponding Result class
-=item Arguments: $moniker, $result_source
+If a Result class is found to already have a ResultSet class set using
+L</resultset_class> to some other class, you will be warned like this:
-=back
+ We found ResultSet class '$rs_class' for '$result', but it seems
+ that you had already set '$result' to use '$rs_set' instead
-Registers the L<DBIx::Class::ResultSource> in the schema with the given
-moniker.
+Both of the sub-namespaces are configurable if you don't like the defaults,
+via the options C<result_namespace> and C<resultset_namespace>.
-=cut
+If (and only if) you specify the option C<default_resultset_class>, any found
+Result classes for which we do not find a corresponding
+ResultSet class will have their C<resultset_class> set to
+C<default_resultset_class>.
-sub register_source {
- my $self = shift;
+All of the namespace and classname options to this method are relative to
+the schema classname by default. To specify a fully-qualified name, prefix
+it with a literal C<+>.
- $self->_register_source(@_);
-}
+Examples:
-=head2 register_extra_source
+ # load My::Schema::Result::CD, My::Schema::Result::Artist,
+ # My::Schema::ResultSet::CD, etc...
+ My::Schema->load_namespaces;
-=over 4
+ # Override everything to use ugly names.
+ # In this example, if there is a My::Schema::Res::Foo, but no matching
+ # My::Schema::RSets::Foo, then Foo will have its
+ # resultset_class set to My::Schema::RSetBase
+ My::Schema->load_namespaces(
+ result_namespace => 'Res',
+ resultset_namespace => 'RSets',
+ default_resultset_class => 'RSetBase',
+ );
-=item Arguments: $moniker, $result_source
+ # Put things in other namespaces
+ My::Schema->load_namespaces(
+ result_namespace => '+Some::Place::Results',
+ resultset_namespace => '+Another::Place::RSets',
+ );
-=back
+If you'd like to use multiple namespaces of each type, simply use an arrayref
+of namespaces for that option. In the case that the same result
+(or resultset) class exists in multiple namespaces, the latter entries in
+your list of namespaces will override earlier ones.
-As L</register_source> but should be used if the result class already
-has a source and you want to register an extra one.
+ My::Schema->load_namespaces(
+ # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
+ result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
+ resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
+ );
=cut
-sub register_extra_source {
- my $self = shift;
-
- $self->_register_source(@_, { extra => 1 });
+# Pre-pends our classname to the given relative classname or
+# class namespace, unless there is a '+' prefix, which will
+# be stripped.
+sub _expand_relative_name {
+ my ($class, $name) = @_;
+ return if !$name;
+ $name = $class . '::' . $name if ! ($name =~ s/^\+//);
+ return $name;
}
-sub _register_source {
- my ($self, $moniker, $source, $params) = @_;
+# returns a hash of $shortname => $fullname for every package
+# found in the given namespaces ($shortname is with the $fullname's
+# namespace stripped off)
+sub _map_namespaces {
+ my ($class, @namespaces) = @_;
- %$source = %{ $source->new( { %$source, source_name => $moniker }) };
-
- my %reg = %{$self->source_registrations};
- $reg{$moniker} = $source;
- $self->source_registrations(\%reg);
-
- $source->schema($self);
- weaken($source->{schema}) if ref($self);
- return if ($params->{extra});
-
- if ($source->result_class) {
- my %map = %{$self->class_mappings};
- if (exists $map{$source->result_class}) {
- warn $source->result_class . ' already has a source, use register_extra_source for additional sources';
- }
- $map{$source->result_class} = $moniker;
- $self->class_mappings(\%map);
+ my @results_hash;
+ foreach my $namespace (@namespaces) {
+ push(
+ @results_hash,
+ map { (substr($_, length "${namespace}::"), $_) }
+ Module::Find::findallmod($namespace)
+ );
}
-}
-sub _unregister_source {
- my ($self, $moniker) = @_;
- my %reg = %{$self->source_registrations};
-
- my $source = delete $reg{$moniker};
- $self->source_registrations(\%reg);
- if ($source->result_class) {
- my %map = %{$self->class_mappings};
- delete $map{$source->result_class};
- $self->class_mappings(\%map);
- }
+ @results_hash;
}
-=head2 class
+sub load_namespaces {
+ my ($class, %args) = @_;
-=over 4
+ my $result_namespace = delete $args{result_namespace} || 'Result';
+ my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
+ my $default_resultset_class = delete $args{default_resultset_class};
-=item Arguments: $moniker
+ $class->throw_exception('load_namespaces: unknown option(s): '
+ . join(q{,}, map { qq{'$_'} } keys %args))
+ if scalar keys %args;
-=item Return Value: $classname
+ $default_resultset_class
+ = $class->_expand_relative_name($default_resultset_class);
-=back
+ for my $arg ($result_namespace, $resultset_namespace) {
+ $arg = [ $arg ] if !ref($arg) && $arg;
-Retrieves the result class name for the given moniker. For example:
+ $class->throw_exception('load_namespaces: namespace arguments must be '
+ . 'a simple string or an arrayref')
+ if ref($arg) ne 'ARRAY';
- my $class = $schema->class('CD');
+ $_ = $class->_expand_relative_name($_) for (@$arg);
+ }
-=cut
+ my %results = $class->_map_namespaces(@$result_namespace);
+ my %resultsets = $class->_map_namespaces(@$resultset_namespace);
-sub class {
- my ($self, $moniker) = @_;
- return $self->source($moniker)->result_class;
-}
+ my @to_register;
+ {
+ no warnings 'redefine';
+ local *Class::C3::reinitialize = sub { };
+ use warnings 'redefine';
-=head2 source
+ foreach my $result (keys %results) {
+ my $result_class = $results{$result};
+ $class->ensure_class_loaded($result_class);
+ $result_class->source_name($result) unless $result_class->source_name;
-=over 4
+ my $rs_class = delete $resultsets{$result};
+ my $rs_set = $result_class->resultset_class;
+ if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
+ if($rs_class && $rs_class ne $rs_set) {
+ warn "We found ResultSet class '$rs_class' for '$result', but it seems "
+ . "that you had already set '$result' to use '$rs_set' instead";
+ }
+ }
+ elsif($rs_class ||= $default_resultset_class) {
+ $class->ensure_class_loaded($rs_class);
+ $result_class->resultset_class($rs_class);
+ }
-=item Arguments: $moniker
+ push(@to_register, [ $result_class->source_name, $result_class ]);
+ }
+ }
-=item Return Value: $result_source
+ foreach (sort keys %resultsets) {
+ warn "load_namespaces found ResultSet class $_ with no "
+ . 'corresponding Result class';
+ }
-=back
+ Class::C3->reinitialize;
+ $class->register_class(@$_) for (@to_register);
- my $source = $schema->source('Book');
-
-Returns the L<DBIx::Class::ResultSource> object for the registered moniker.
-
-=cut
-
-sub source {
- my ($self, $moniker) = @_;
- my $sreg = $self->source_registrations;
- return $sreg->{$moniker} if exists $sreg->{$moniker};
-
- # if we got here, they probably passed a full class name
- my $mapped = $self->class_mappings->{$moniker};
- $self->throw_exception("Can't find source for ${moniker}")
- unless $mapped && exists $sreg->{$mapped};
- return $sreg->{$mapped};
+ return;
}
-=head2 sources
-
-=over 4
-
-=item Return Value: @source_monikers
-
-=back
-
-Returns the source monikers of all source registrations on this schema.
-For example:
-
- my @source_monikers = $schema->sources;
-
-=cut
-
-sub sources { return keys %{shift->source_registrations}; }
-
-=head2 storage
-
- my $storage = $schema->storage;
-
-Returns the L<DBIx::Class::Storage> object for this Schema.
-
-=head2 resultset
-
-=over 4
-
-=item Arguments: $moniker
-
-=item Return Value: $result_set
-
-=back
-
- my $rs = $schema->resultset('DVD');
-
-Returns the L<DBIx::Class::ResultSet> object for the registered moniker.
-
-=cut
-
-sub resultset {
- my ($self, $moniker) = @_;
- return $self->source($moniker)->resultset;
-}
-
=head2 load_classes
=over 4
@@ -258,6 +249,9 @@
=back
+Alternative method to L</load_namespaces> which you should look at
+using if you can.
+
With no arguments, this method uses L<Module::Find> to find all classes under
the schema's namespace. Otherwise, this method loads the classes you specify
(using L<use>), and registers them (using L</"register_class">).
@@ -266,6 +260,13 @@
will think it's a mistake (trying to use a comment in a qw list), so you'll
need to add C<no warnings 'qw';> before your load_classes call.
+If any classes found do not appear to be Result class files, you will
+get the following warning:
+
+ Failed to load $comp_class. Can't find source_name method. Is
+ $comp_class really a full DBIC result class? Fix it, move it elsewhere,
+ or make your load_classes call more specific.
+
Example:
My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
@@ -347,428 +348,208 @@
}
}
-=head2 load_namespaces
+=head2 storage_type
=over 4
-=item Arguments: %options?
+=item Arguments: $storage_type|{$storage_type, \%args}
-=back
+=item Return value: $storage_type|{$storage_type, \%args}
-This is an alternative to L</load_classes> above which assumes an alternative
-layout for automatic class loading. It assumes that all result
-classes are underneath a sub-namespace of the schema called C<Result>, any
-corresponding ResultSet classes are underneath a sub-namespace of the schema
-called C<ResultSet>.
+=item Default value: DBIx::Class::Storage::DBI
-Both of the sub-namespaces are configurable if you don't like the defaults,
-via the options C<result_namespace> and C<resultset_namespace>.
+=back
-If (and only if) you specify the option C<default_resultset_class>, any found
-Result classes for which we do not find a corresponding
-ResultSet class will have their C<resultset_class> set to
-C<default_resultset_class>.
+Set the storage class that will be instantiated when L</connect> is called.
+If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
+assumed by L</connect>.
-C<load_namespaces> takes care of calling C<resultset_class> for you where
-neccessary if you didn't do it for yourself.
+You want to use this to set subclasses of L<DBIx::Class::Storage::DBI>
+in cases where the appropriate subclass is not autodetected, such as
+when dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it
+to C<::DBI::Sybase::MSSQL>.
-All of the namespace and classname options to this method are relative to
-the schema classname by default. To specify a fully-qualified name, prefix
-it with a literal C<+>.
+If your storage type requires instantiation arguments, those are
+defined as a second argument in the form of a hashref and the entire
+value needs to be wrapped into an arrayref or a hashref. We support
+both types of refs here in order to play nice with your
+Config::[class] or your choice. See
+L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
-Examples:
+=head2 exception_action
- # load My::Schema::Result::CD, My::Schema::Result::Artist,
- # My::Schema::ResultSet::CD, etc...
- My::Schema->load_namespaces;
+=over 4
- # Override everything to use ugly names.
- # In this example, if there is a My::Schema::Res::Foo, but no matching
- # My::Schema::RSets::Foo, then Foo will have its
- # resultset_class set to My::Schema::RSetBase
- My::Schema->load_namespaces(
- result_namespace => 'Res',
- resultset_namespace => 'RSets',
- default_resultset_class => 'RSetBase',
- );
+=item Arguments: $code_reference
- # Put things in other namespaces
- My::Schema->load_namespaces(
- result_namespace => '+Some::Place::Results',
- resultset_namespace => '+Another::Place::RSets',
- );
+=item Return value: $code_reference
-If you'd like to use multiple namespaces of each type, simply use an arrayref
-of namespaces for that option. In the case that the same result
-(or resultset) class exists in multiple namespaces, the latter entries in
-your list of namespaces will override earlier ones.
+=item Default value: None
- My::Schema->load_namespaces(
- # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
- result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
- resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
- );
+=back
-=cut
+If C<exception_action> is set for this class/object, L</throw_exception>
+will prefer to call this code reference with the exception as an argument,
+rather than L<DBIx::Class::Exception/throw>.
-# Pre-pends our classname to the given relative classname or
-# class namespace, unless there is a '+' prefix, which will
-# be stripped.
-sub _expand_relative_name {
- my ($class, $name) = @_;
- return if !$name;
- $name = $class . '::' . $name if ! ($name =~ s/^\+//);
- return $name;
-}
+Your subroutine should probably just wrap the error in the exception
+object/class of your choosing and rethrow. If, against all sage advice,
+you'd like your C<exception_action> to suppress a particular exception
+completely, simply have it return true.
-# returns a hash of $shortname => $fullname for every package
-# found in the given namespaces ($shortname is with the $fullname's
-# namespace stripped off)
-sub _map_namespaces {
- my ($class, @namespaces) = @_;
+Example:
- my @results_hash;
- foreach my $namespace (@namespaces) {
- push(
- @results_hash,
- map { (substr($_, length "${namespace}::"), $_) }
- Module::Find::findallmod($namespace)
- );
- }
+ package My::Schema;
+ use base qw/DBIx::Class::Schema/;
+ use My::ExceptionClass;
+ __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
+ __PACKAGE__->load_classes;
- @results_hash;
-}
+ # or:
+ my $schema_obj = My::Schema->connect( .... );
+ $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
-sub load_namespaces {
- my ($class, %args) = @_;
+ # suppress all exceptions, like a moron:
+ $schema_obj->exception_action(sub { 1 });
- my $result_namespace = delete $args{result_namespace} || 'Result';
- my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
- my $default_resultset_class = delete $args{default_resultset_class};
+=head2 stacktrace
- $class->throw_exception('load_namespaces: unknown option(s): '
- . join(q{,}, map { qq{'$_'} } keys %args))
- if scalar keys %args;
+=over 4
- $default_resultset_class
- = $class->_expand_relative_name($default_resultset_class);
+=item Arguments: boolean
- for my $arg ($result_namespace, $resultset_namespace) {
- $arg = [ $arg ] if !ref($arg) && $arg;
+=back
- $class->throw_exception('load_namespaces: namespace arguments must be '
- . 'a simple string or an arrayref')
- if ref($arg) ne 'ARRAY';
+Whether L</throw_exception> should include stack trace information.
+Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
+is true.
- $_ = $class->_expand_relative_name($_) for (@$arg);
- }
+=head2 sqlt_deploy_hook
- my %results = $class->_map_namespaces(@$result_namespace);
- my %resultsets = $class->_map_namespaces(@$resultset_namespace);
+=over
- my @to_register;
- {
- no warnings 'redefine';
- local *Class::C3::reinitialize = sub { };
- use warnings 'redefine';
+=item Arguments: $sqlt_schema
- foreach my $result (keys %results) {
- my $result_class = $results{$result};
- $class->ensure_class_loaded($result_class);
- $result_class->source_name($result) unless $result_class->source_name;
+=back
- my $rs_class = delete $resultsets{$result};
- my $rs_set = $result_class->resultset_class;
- if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
- if($rs_class && $rs_class ne $rs_set) {
- warn "We found ResultSet class '$rs_class' for '$result', but it seems "
- . "that you had already set '$result' to use '$rs_set' instead";
- }
- }
- elsif($rs_class ||= $default_resultset_class) {
- $class->ensure_class_loaded($rs_class);
- $result_class->resultset_class($rs_class);
- }
+An optional sub which you can declare in your own Schema class that will get
+passed the L<SQL::Translator::Schema> object when you deploy the schema via
+L</create_ddl_dir> or L</deploy>.
- push(@to_register, [ $result_class->source_name, $result_class ]);
- }
- }
+For an example of what you can do with this, see
+L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
- foreach (sort keys %resultsets) {
- warn "load_namespaces found ResultSet class $_ with no "
- . 'corresponding Result class';
- }
+=head1 METHODS
- Class::C3->reinitialize;
- $class->register_class(@$_) for (@to_register);
+=head2 connect
- return;
-}
-
-=head2 compose_connection (DEPRECATED)
-
=over 4
-=item Arguments: $target_namespace, @db_info
+=item Arguments: @connectinfo
=item Return Value: $new_schema
=back
-DEPRECATED. You probably wanted compose_namespace.
+Creates and returns a new Schema object. The connection info set on it
+is used to create a new instance of the storage backend and set it on
+the Schema object.
-Actually, you probably just wanted to call connect.
+See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific
+syntax on the C>@connectinfo> argument, or L<DBIx::Class::Storage> in
+general.
-=begin hidden
-
-(hidden due to deprecation)
-
-Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
-calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
-then injects the L<DBix::Class::ResultSetProxy> component and a
-resultset_instance classdata entry on all the new classes, in order to support
-$target_namespaces::$class->search(...) method calls.
-
-This is primarily useful when you have a specific need for class method access
-to a connection. In normal usage it is preferred to call
-L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
-on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
-more information.
-
-=end hidden
-
=cut
-{
- my $warn;
+sub connect { shift->clone->connection(@_) }
- sub compose_connection {
- my ($self, $target, @info) = @_;
+=head2 resultset
- warn "compose_connection deprecated as of 0.08000"
- unless ($INC{"DBIx/Class/CDBICompat.pm"} || $warn++);
-
- my $base = 'DBIx::Class::ResultSetProxy';
- eval "require ${base};";
- $self->throw_exception
- ("No arguments to load_classes and couldn't load ${base} ($@)")
- if $@;
-
- if ($self eq $target) {
- # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
- foreach my $moniker ($self->sources) {
- my $source = $self->source($moniker);
- my $class = $source->result_class;
- $self->inject_base($class, $base);
- $class->mk_classdata(resultset_instance => $source->resultset);
- $class->mk_classdata(class_resolver => $self);
- }
- $self->connection(@info);
- return $self;
- }
-
- my $schema = $self->compose_namespace($target, $base);
- {
- no strict 'refs';
- my $name = join '::', $target, 'schema';
- *$name = Sub::Name::subname $name, sub { $schema };
- }
-
- $schema->connection(@info);
- foreach my $moniker ($schema->sources) {
- my $source = $schema->source($moniker);
- my $class = $source->result_class;
- #warn "$moniker $class $source ".$source->storage;
- $class->mk_classdata(result_source_instance => $source);
- $class->mk_classdata(resultset_instance => $source->resultset);
- $class->mk_classdata(class_resolver => $schema);
- }
- return $schema;
- }
-}
-
-=head2 compose_namespace
-
=over 4
-=item Arguments: $target_namespace, $additional_base_class?
+=item Arguments: $source_name
-=item Return Value: $new_schema
+=item Return Value: $resultset
=back
-For each L<DBIx::Class::ResultSource> in the schema, this method creates a
-class in the target namespace (e.g. $target_namespace::CD,
-$target_namespace::Artist) that inherits from the corresponding classes
-attached to the current schema.
+ my $rs = $schema->resultset('DVD');
-It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
-new $schema object. If C<$additional_base_class> is given, the new composed
-classes will inherit from first the corresponding classe from the current
-schema then the base class.
+Returns the L<DBIx::Class::ResultSet> object for the registered source
+name.
-For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
-
- $schema->compose_namespace('My::DB', 'Base::Class');
- print join (', ', @My::DB::CD::ISA) . "\n";
- print join (', ', @My::DB::Artist::ISA) ."\n";
-
-will produce the output
-
- My::Schema::CD, Base::Class
- My::Schema::Artist, Base::Class
-
=cut
-# this might be oversimplified
-# sub compose_namespace {
-# my ($self, $target, $base) = @_;
-
-# my $schema = $self->clone;
-# foreach my $moniker ($schema->sources) {
-# my $source = $schema->source($moniker);
-# my $target_class = "${target}::${moniker}";
-# $self->inject_base(
-# $target_class => $source->result_class, ($base ? $base : ())
-# );
-# $source->result_class($target_class);
-# $target_class->result_source_instance($source)
-# if $target_class->can('result_source_instance');
-# $schema->register_source($moniker, $source);
-# }
-# return $schema;
-# }
-
-sub compose_namespace {
- my ($self, $target, $base) = @_;
- my $schema = $self->clone;
- {
- no warnings qw/redefine/;
-# local *Class::C3::reinitialize = sub { };
- foreach my $moniker ($schema->sources) {
- my $source = $schema->source($moniker);
- my $target_class = "${target}::${moniker}";
- $self->inject_base(
- $target_class => $source->result_class, ($base ? $base : ())
- );
- $source->result_class($target_class);
- $target_class->result_source_instance($source)
- if $target_class->can('result_source_instance');
- $schema->register_source($moniker, $source);
- }
- }
-# Class::C3->reinitialize();
- {
- no strict 'refs';
- no warnings 'redefine';
- foreach my $meth (qw/class source resultset/) {
- *{"${target}::${meth}"} =
- sub { shift->schema->$meth(@_) };
- }
- }
- return $schema;
+sub resultset {
+ my ($self, $moniker) = @_;
+ return $self->source($moniker)->resultset;
}
-sub setup_connection_class {
- my ($class, $target, @info) = @_;
- $class->inject_base($target => 'DBIx::Class::DB');
- #$target->load_components('DB');
- $target->connection(@info);
-}
+=head2 sources
-=head2 storage_type
-
=over 4
-=item Arguments: $storage_type|{$storage_type, \%args}
+=item Return Value: @source_names
-=item Return Value: $storage_type|{$storage_type, \%args}
-
=back
-Set the storage class that will be instantiated when L</connect> is called.
-If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
-assumed by L</connect>. Defaults to C<::DBI>,
-which is L<DBIx::Class::Storage::DBI>.
+ my @source_names = $schema->sources;
-You want to use this to hardcoded subclasses of L<DBIx::Class::Storage::DBI>
-in cases where the appropriate subclass is not autodetected, such as when
-dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it to
-C<::DBI::Sybase::MSSQL>.
+Lists names of all the sources registered on this Schema object.
-If your storage type requires instantiation arguments, those are defined as a
-second argument in the form of a hashref and the entire value needs to be
-wrapped into an arrayref or a hashref. We support both types of refs here in
-order to play nice with your Config::[class] or your choice.
+=cut
-See L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
+sub sources { return keys %{shift->source_registrations}; }
-=head2 connection
+=head2 source
=over 4
-=item Arguments: @args
+=item Arguments: $source_name
-=item Return Value: $new_schema
+=item Return Value: $result_source
=back
-Instantiates a new Storage object of type
-L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
-$storage->connect_info. Sets the connection in-place on the schema.
+ my $source = $schema->source('Book');
-See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
-or L<DBIx::Class::Storage> in general.
+Returns the L<DBIx::Class::ResultSource> object for the registered
+source name.
=cut
-sub connection {
- my ($self, @info) = @_;
- return $self if !@info && $self->storage;
-
- my ($storage_class, $args) = ref $self->storage_type ?
- ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {});
-
- $storage_class = 'DBIx::Class::Storage'.$storage_class
- if $storage_class =~ m/^::/;
- eval "require ${storage_class};";
- $self->throw_exception(
- "No arguments to load_classes and couldn't load ${storage_class} ($@)"
- ) if $@;
- my $storage = $storage_class->new($self=>$args);
- $storage->connect_info(\@info);
- $self->storage($storage);
- return $self;
-}
+sub source {
+ my ($self, $moniker) = @_;
+ my $sreg = $self->source_registrations;
+ return $sreg->{$moniker} if exists $sreg->{$moniker};
-sub _normalize_storage_type {
- my ($self, $storage_type) = @_;
- if(ref $storage_type eq 'ARRAY') {
- return @$storage_type;
- } elsif(ref $storage_type eq 'HASH') {
- return %$storage_type;
- } else {
- $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
- }
+ # if we got here, they probably passed a full class name
+ my $mapped = $self->class_mappings->{$moniker};
+ $self->throw_exception("Can't find source for ${moniker}")
+ unless $mapped && exists $sreg->{$mapped};
+ return $sreg->{$mapped};
}
-=head2 connect
+=head2 class
=over 4
-=item Arguments: @info
+=item Arguments: $source_name
-=item Return Value: $new_schema
+=item Return Value: $classname
=back
-This is a convenience method. It is equivalent to calling
-$schema->clone->connection(@info). See L</connection> and L</clone> for more
-information.
+ my $class = $schema->class('CD');
+Retrieves the Result class name for the given source name.
+
=cut
-sub connect { shift->clone->connection(@_) }
+sub class {
+ my ($self, $moniker) = @_;
+ return $self->source($moniker)->result_class;
+}
=head2 txn_do
@@ -865,94 +646,23 @@
$self->storage->txn_rollback;
}
-=head2 svp_begin
+=head2 storage
-Creates a new savepoint (does nothing outside a transaction).
-Equivalent to calling $schema->storage->svp_begin. See
-L<DBIx::Class::Storage::DBI/"svp_begin"> for more information.
+ my $storage = $schema->storage;
-=cut
+Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
+if you want to turn on SQL statement debugging at runtime, or set the
+quote character. For the default storage, the documentation can be
+found in L<DBIx::Class::Storage::DBI>.
-sub svp_begin {
- my ($self, $name) = @_;
-
- $self->storage or $self->throw_exception
- ('svp_begin called on $schema without storage');
-
- $self->storage->svp_begin($name);
-}
-
-=head2 svp_release
-
-Releases a savepoint (does nothing outside a transaction).
-Equivalent to calling $schema->storage->svp_release. See
-L<DBIx::Class::Storage::DBI/"svp_release"> for more information.
-
-=cut
-
-sub svp_release {
- my ($self, $name) = @_;
-
- $self->storage or $self->throw_exception
- ('svp_release called on $schema without storage');
-
- $self->storage->svp_release($name);
-}
-
-=head2 svp_rollback
-
-Rollback to a savepoint (does nothing outside a transaction).
-Equivalent to calling $schema->storage->svp_rollback. See
-L<DBIx::Class::Storage::DBI/"svp_rollback"> for more information.
-
-=cut
-
-sub svp_rollback {
- my ($self, $name) = @_;
-
- $self->storage or $self->throw_exception
- ('svp_rollback called on $schema without storage');
-
- $self->storage->svp_rollback($name);
-}
-
-=head2 clone
-
-=over 4
-
-=item Return Value: $new_schema
-
-=back
-
-Clones the schema and its associated result_source objects and returns the
-copy.
-
-=cut
-
-sub clone {
- my ($self) = @_;
- my $clone = { (ref $self ? %$self : ()) };
- bless $clone, (ref $self || $self);
-
- $clone->class_mappings({ %{$clone->class_mappings} });
- $clone->source_registrations({ %{$clone->source_registrations} });
- foreach my $moniker ($self->sources) {
- my $source = $self->source($moniker);
- my $new = $source->new($source);
- # we use extra here as we want to leave the class_mappings as they are
- # but overwrite the source_registrations entry with the new source
- $clone->register_extra_source($moniker => $new);
- }
- $clone->storage->set_schema($clone) if $clone->storage;
- return $clone;
-}
-
=head2 populate
=over 4
=item Arguments: $source_name, \@data;
+=item Return value: \@$objects | nothing
+
=back
Pass this method a resultsource name, and an arrayref of
@@ -1015,50 +725,224 @@
$rs->populate(\@results_to_create);
}
-=head2 exception_action
+=head2 connection
=over 4
-=item Arguments: $code_reference
+=item Arguments: @args
+=item Return Value: $new_schema
+
=back
-If C<exception_action> is set for this class/object, L</throw_exception>
-will prefer to call this code reference with the exception as an argument,
-rather than its normal C<croak> or C<confess> action.
+Similar to L</connect> except sets the storage object and connection
+data in-place on the Schema class. You should probably be calling
+L</connect> to get a proper Schema object instead.
-Your subroutine should probably just wrap the error in the exception
-object/class of your choosing and rethrow. If, against all sage advice,
-you'd like your C<exception_action> to suppress a particular exception
-completely, simply have it return true.
-Example:
+=cut
- package My::Schema;
- use base qw/DBIx::Class::Schema/;
- use My::ExceptionClass;
- __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
- __PACKAGE__->load_classes;
+sub connection {
+ my ($self, @info) = @_;
+ return $self if !@info && $self->storage;
+
+ my ($storage_class, $args) = ref $self->storage_type ?
+ ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {});
+
+ $storage_class = 'DBIx::Class::Storage'.$storage_class
+ if $storage_class =~ m/^::/;
+ eval "require ${storage_class};";
+ $self->throw_exception(
+ "No arguments to load_classes and couldn't load ${storage_class} ($@)"
+ ) if $@;
+ my $storage = $storage_class->new($self=>$args);
+ $storage->connect_info(\@info);
+ $self->storage($storage);
+ return $self;
+}
- # or:
- my $schema_obj = My::Schema->connect( .... );
- $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
+sub _normalize_storage_type {
+ my ($self, $storage_type) = @_;
+ if(ref $storage_type eq 'ARRAY') {
+ return @$storage_type;
+ } elsif(ref $storage_type eq 'HASH') {
+ return %$storage_type;
+ } else {
+ $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
+ }
+}
- # suppress all exceptions, like a moron:
- $schema_obj->exception_action(sub { 1 });
+=head2 compose_namespace
-=head2 stacktrace
+=over 4
+=item Arguments: $target_namespace, $additional_base_class?
+
+=item Retur Value: $new_schema
+
+=back
+
+For each L<DBIx::Class::ResultSource> in the schema, this method creates a
+class in the target namespace (e.g. $target_namespace::CD,
+$target_namespace::Artist) that inherits from the corresponding classes
+attached to the current schema.
+
+It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
+new $schema object. If C<$additional_base_class> is given, the new composed
+classes will inherit from first the corresponding classe from the current
+schema then the base class.
+
+For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
+
+ $schema->compose_namespace('My::DB', 'Base::Class');
+ print join (', ', @My::DB::CD::ISA) . "\n";
+ print join (', ', @My::DB::Artist::ISA) ."\n";
+
+will produce the output
+
+ My::Schema::CD, Base::Class
+ My::Schema::Artist, Base::Class
+
+=cut
+
+# this might be oversimplified
+# sub compose_namespace {
+# my ($self, $target, $base) = @_;
+
+# my $schema = $self->clone;
+# foreach my $moniker ($schema->sources) {
+# my $source = $schema->source($moniker);
+# my $target_class = "${target}::${moniker}";
+# $self->inject_base(
+# $target_class => $source->result_class, ($base ? $base : ())
+# );
+# $source->result_class($target_class);
+# $target_class->result_source_instance($source)
+# if $target_class->can('result_source_instance');
+# $schema->register_source($moniker, $source);
+# }
+# return $schema;
+# }
+
+sub compose_namespace {
+ my ($self, $target, $base) = @_;
+ my $schema = $self->clone;
+ {
+ no warnings qw/redefine/;
+# local *Class::C3::reinitialize = sub { };
+ foreach my $moniker ($schema->sources) {
+ my $source = $schema->source($moniker);
+ my $target_class = "${target}::${moniker}";
+ $self->inject_base(
+ $target_class => $source->result_class, ($base ? $base : ())
+ );
+ $source->result_class($target_class);
+ $target_class->result_source_instance($source)
+ if $target_class->can('result_source_instance');
+ $schema->register_source($moniker, $source);
+ }
+ }
+# Class::C3->reinitialize();
+ {
+ no strict 'refs';
+ no warnings 'redefine';
+ foreach my $meth (qw/class source resultset/) {
+ *{"${target}::${meth}"} =
+ sub { shift->schema->$meth(@_) };
+ }
+ }
+ return $schema;
+}
+
+sub setup_connection_class {
+ my ($class, $target, @info) = @_;
+ $class->inject_base($target => 'DBIx::Class::DB');
+ #$target->load_components('DB');
+ $target->connection(@info);
+}
+
+=head2 svp_begin
+
+Creates a new savepoint (does nothing outside a transaction).
+Equivalent to calling $schema->storage->svp_begin. See
+L<DBIx::Class::Storage::DBI/"svp_begin"> for more information.
+
+=cut
+
+sub svp_begin {
+ my ($self, $name) = @_;
+
+ $self->storage or $self->throw_exception
+ ('svp_begin called on $schema without storage');
+
+ $self->storage->svp_begin($name);
+}
+
+=head2 svp_release
+
+Releases a savepoint (does nothing outside a transaction).
+Equivalent to calling $schema->storage->svp_release. See
+L<DBIx::Class::Storage::DBI/"svp_release"> for more information.
+
+=cut
+
+sub svp_release {
+ my ($self, $name) = @_;
+
+ $self->storage or $self->throw_exception
+ ('svp_release called on $schema without storage');
+
+ $self->storage->svp_release($name);
+}
+
+=head2 svp_rollback
+
+Rollback to a savepoint (does nothing outside a transaction).
+Equivalent to calling $schema->storage->svp_rollback. See
+L<DBIx::Class::Storage::DBI/"svp_rollback"> for more information.
+
+=cut
+
+sub svp_rollback {
+ my ($self, $name) = @_;
+
+ $self->storage or $self->throw_exception
+ ('svp_rollback called on $schema without storage');
+
+ $self->storage->svp_rollback($name);
+}
+
+=head2 clone
+
=over 4
-=item Arguments: boolean
+=item Return Value: $new_schema
=back
-Whether L</throw_exception> should include stack trace information.
-Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
-is true.
+Clones the schema and its associated result_source objects and returns the
+copy.
+=cut
+
+sub clone {
+ my ($self) = @_;
+ my $clone = { (ref $self ? %$self : ()) };
+ bless $clone, (ref $self || $self);
+
+ $clone->class_mappings({ %{$clone->class_mappings} });
+ $clone->source_registrations({ %{$clone->source_registrations} });
+ foreach my $moniker ($self->sources) {
+ my $source = $self->source($moniker);
+ my $new = $source->new($source);
+ # we use extra here as we want to leave the class_mappings as they are
+ # but overwrite the source_registrations entry with the new source
+ $clone->register_extra_source($moniker => $new);
+ }
+ $clone->storage->set_schema($clone) if $clone->storage;
+ return $clone;
+}
+
=head2 throw_exception
=over 4
@@ -1115,13 +999,17 @@
=item Arguments: $rdbms_type, $sqlt_args, $dir
+=item Return value: $listofstatements
+
=back
-A convenient shortcut to storage->deployment_statements(). Returns the SQL statements
-used by L</deploy> and L<DBIx::Class::Schema::Storage/deploy>. C<$rdbms_type> provides
-the (optional) SQLT (not DBI) database driver name for which the SQL statements are produced.
-If not supplied, the type is determined by interrogating the current connection.
-The other two arguments are identical to those of L</deploy>.
+A convenient shortcut to storage->deployment_statements(). Returns the
+SQL statements used by L</deploy> and
+L<DBIx::Class::Schema::Storage/deploy>. C<$rdbms_type> provides the
+(optional) SQLT (not DBI) database driver name for which the SQL
+statements are produced. If not supplied, the type is determined by
+interrogating the current connection. The other two arguments are
+identical to those of L</deploy>.
=cut
@@ -1190,6 +1078,8 @@
=item Arguments: $database-type, $version, $directory, $preversion
+=item Return value: $normalised_filename
+
=back
my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
@@ -1214,18 +1104,9 @@
return $filename;
}
-=head2 sqlt_deploy_hook($sqlt_schema)
-
-An optional sub which you can declare in your own Schema class that will get
-passed the L<SQL::Translator::Schema> object when you deploy the schema via
-L</create_ddl_dir> or L</deploy>.
-
-For an example of what you can do with this, see
-L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
-
=head2 thaw
-Provided as the recommened way of thawing schema objects. You can call
+Provided as the recommended way of thawing schema objects. You can call
C<Storable::thaw> directly if you wish, but the thawed objects will not have a
reference to any schema, so are rather useless
@@ -1263,7 +1144,7 @@
=head2 schema_version
-Returns the current schema class' $VERSION
+Returns the current schema class' $VERSION in a normalised way.
=cut
@@ -1284,6 +1165,192 @@
return $version;
}
+
+=head2 register_class
+
+=over 4
+
+=item Arguments: $moniker, $component_class
+
+=back
+
+This method is called by L</load_namespaces> and L</load_classes> to install the found classes into your Schema. You should be using those instead of this one.
+
+You will only need this method if you have your Result classes in
+files which are not named after the packages (or all in the same
+file). You may also need it to register classes at runtime.
+
+Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
+calling:
+
+ $schema->register_source($moniker, $component_class->result_source_instance);
+
+=cut
+
+sub register_class {
+ my ($self, $moniker, $to_register) = @_;
+ $self->register_source($moniker => $to_register->result_source_instance);
+}
+
+=head2 register_source
+
+=over 4
+
+=item Arguments: $moniker, $result_source
+
+=back
+
+This method is called by L</register_class>.
+
+Registers the L<DBIx::Class::ResultSource> in the schema with the given
+moniker.
+
+=cut
+
+sub register_source {
+ my $self = shift;
+
+ $self->_register_source(@_);
+}
+
+=head2 register_extra_source
+
+=over 4
+
+=item Arguments: $moniker, $result_source
+
+=back
+
+As L</register_source> but should be used if the result class already
+has a source and you want to register an extra one.
+
+=cut
+
+sub register_extra_source {
+ my $self = shift;
+
+ $self->_register_source(@_, { extra => 1 });
+}
+
+sub _register_source {
+ my ($self, $moniker, $source, $params) = @_;
+
+ %$source = %{ $source->new( { %$source, source_name => $moniker }) };
+
+ my %reg = %{$self->source_registrations};
+ $reg{$moniker} = $source;
+ $self->source_registrations(\%reg);
+
+ $source->schema($self);
+ weaken($source->{schema}) if ref($self);
+ return if ($params->{extra});
+
+ if ($source->result_class) {
+ my %map = %{$self->class_mappings};
+ if (exists $map{$source->result_class}) {
+ warn $source->result_class . ' already has a source, use register_extra_source for additional sources';
+ }
+ $map{$source->result_class} = $moniker;
+ $self->class_mappings(\%map);
+ }
+}
+
+sub _unregister_source {
+ my ($self, $moniker) = @_;
+ my %reg = %{$self->source_registrations};
+
+ my $source = delete $reg{$moniker};
+ $self->source_registrations(\%reg);
+ if ($source->result_class) {
+ my %map = %{$self->class_mappings};
+ delete $map{$source->result_class};
+ $self->class_mappings(\%map);
+ }
+}
+
+
+=head2 compose_connection (DEPRECATED)
+
+=over 4
+
+=item Arguments: $target_namespace, @db_info
+
+=item Return Value: $new_schema
+
+=back
+
+DEPRECATED. You probably wanted compose_namespace.
+
+Actually, you probably just wanted to call connect.
+
+=begin hidden
+
+(hidden due to deprecation)
+
+Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
+calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
+then injects the L<DBix::Class::ResultSetProxy> component and a
+resultset_instance classdata entry on all the new classes, in order to support
+$target_namespaces::$class->search(...) method calls.
+
+This is primarily useful when you have a specific need for class method access
+to a connection. In normal usage it is preferred to call
+L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
+on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
+more information.
+
+=end hidden
+
+=cut
+
+{
+ my $warn;
+
+ sub compose_connection {
+ my ($self, $target, @info) = @_;
+
+ warn "compose_connection deprecated as of 0.08000"
+ unless ($INC{"DBIx/Class/CDBICompat.pm"} || $warn++);
+
+ my $base = 'DBIx::Class::ResultSetProxy';
+ eval "require ${base};";
+ $self->throw_exception
+ ("No arguments to load_classes and couldn't load ${base} ($@)")
+ if $@;
+
+ if ($self eq $target) {
+ # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
+ foreach my $moniker ($self->sources) {
+ my $source = $self->source($moniker);
+ my $class = $source->result_class;
+ $self->inject_base($class, $base);
+ $class->mk_classdata(resultset_instance => $source->resultset);
+ $class->mk_classdata(class_resolver => $self);
+ }
+ $self->connection(@info);
+ return $self;
+ }
+
+ my $schema = $self->compose_namespace($target, $base);
+ {
+ no strict 'refs';
+ my $name = join '::', $target, 'schema';
+ *$name = Sub::Name::subname $name, sub { $schema };
+ }
+
+ $schema->connection(@info);
+ foreach my $moniker ($schema->sources) {
+ my $source = $schema->source($moniker);
+ my $class = $source->result_class;
+ #warn "$moniker $class $source ".$source->storage;
+ $class->mk_classdata(result_source_instance => $source);
+ $class->mk_classdata(resultset_instance => $source->resultset);
+ $class->mk_classdata(class_resolver => $schema);
+ }
+ return $schema;
+ }
+}
+
1;
=head1 AUTHORS
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/SQLite.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/SQLite.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class/Storage/DBI/SQLite.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -45,7 +45,21 @@
return $backupfile;
}
+sub disconnect {
+ # As described in this node http://www.perlmonks.org/?node_id=666210
+ # there seems to be no sane way to ->disconnect a SQLite database with
+ # cached statement handles. As per mst we just zap the cache and
+ # proceed as normal.
+
+ my $self = shift;
+ if ($self->connected) {
+ $self->_dbh->{CachedKids} = {};
+ $self->next::method (@_);
+ }
+}
+
+
1;
=head1 NAME
Modified: DBIx-Class/0.08/branches/view_support/lib/DBIx/Class.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/lib/DBIx/Class.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/lib/DBIx/Class.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -68,28 +68,28 @@
package MyDB::Schema;
use base qw/DBIx::Class::Schema/;
- __PACKAGE__->load_classes();
+ __PACKAGE__->load_namespaces();
1;
Create a table class to represent artists, who have many CDs, in
-MyDB/Schema/Artist.pm:
+MyDB/Schema/Result/Artist.pm:
- package MyDB::Schema::Artist;
+ package MyDB::Schema::Result::Artist;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/Core/);
__PACKAGE__->table('artist');
__PACKAGE__->add_columns(qw/ artistid name /);
__PACKAGE__->set_primary_key('artistid');
- __PACKAGE__->has_many(cds => 'MyDB::Schema::CD');
+ __PACKAGE__->has_many(cds => 'MyDB::Schema::Result::CD');
1;
A table class to represent a CD, which belongs to an artist, in
-MyDB/Schema/CD.pm:
+MyDB/Schema/Result/CD.pm:
- package MyDB::Schema::CD;
+ package MyDB::Schema::Result::CD;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/Core/);
@@ -121,7 +121,7 @@
# Execute a joined query to get the cds.
my @all_john_cds = $johns_rs->search_related('cds')->all;
- # Fetch only the next row.
+ # Fetch the next available row.
my $first_john = $johns_rs->next;
# Specify ORDER BY on the query.
Modified: DBIx-Class/0.08/branches/view_support/maint/gen-schema.pl
===================================================================
--- DBIx-Class/0.08/branches/view_support/maint/gen-schema.pl 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/maint/gen-schema.pl 2008-10-23 13:37:14 UTC (rev 4955)
@@ -5,7 +5,15 @@
use lib qw(lib t/lib);
use DBICTest::Schema;
+use SQL::Translator;
+my $sql_join_str = '';
+if (SQL::Translator->VERSION >= 0.09001) {
+ $sql_join_str .= ";";
+}
+if (SQL::Translator->VERSION >= 0.09) {
+ $sql_join_str .= "\n";
+}
+
my $schema = DBICTest::Schema->connect;
-
-print $schema->storage->deployment_statements($schema, 'SQLite');
+print join ($sql_join_str,$schema->storage->deployment_statements($schema, 'SQLite') );
Modified: DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/33storage_reconnect.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -7,7 +7,7 @@
use lib qw(t/lib);
use DBICTest;
-plan tests => 5;
+plan tests => 6;
my $db_orig = "$FindBin::Bin/var/DBIxClass.db";
my $db_tmp = "$db_orig.tmp";
@@ -20,7 +20,14 @@
cmp_ok(@art, '==', 3, "Three artists returned");
# Disconnect the dbh, and be sneaky about it
-$schema->storage->_dbh->disconnect;
+# Also test if DBD::SQLite finaly knows how to ->disconnect properly
+TODO: {
+ local $TODO = 'SQLite is evil/braindead. Once this test starts passing, remove the related atrocity from DBIx::Class::Storage::DBI::SQLite';
+ my $w;
+ local $SIG{__WARN__} = sub { $w = shift };
+ $schema->storage->_dbh->disconnect;
+ ok ($w !~ /active statement handles/, 'SQLite can disconnect properly \o/');
+}
# Try the operation again - What should happen here is:
# 1. S::DBI blindly attempts the SELECT, which throws an exception
@@ -40,10 +47,14 @@
chmod 0000, $db_orig;
### Try the operation again... it should fail, since there's no db
-eval {
- my @art_three = $schema->resultset("Artist")->search( {}, { order_by => 'name DESC' } );
-};
-ok( $@, 'The operation failed' );
+{
+ # Catch the DBI connection error
+ local $SIG{__WARN__} = sub {};
+ eval {
+ my @art_three = $schema->resultset("Artist")->search( {}, { order_by => 'name DESC' } );
+ };
+ ok( $@, 'The operation failed' );
+}
### Now, move the db file back to the correct name
unlink($db_orig);
Modified: DBIx-Class/0.08/branches/view_support/t/47bind_attribute.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/47bind_attribute.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/47bind_attribute.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -73,6 +73,10 @@
is ( $rs->count, 1, '...cookbook (bind first) + chained search' );
TODO: {
+ # not sure what causes an uninit warning here, please remove when the TODO starts to pass,
+ # so the real reason for the warning can be found and fixed
+ local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /uninitialized/ };
+
local $TODO = 'bind args order needs fixing (semifor)';
$rs = $schema->resultset('Complex')->search({}, { bind => [ 1999 ] })
->search({ 'artistid' => 1 }, {
Modified: DBIx-Class/0.08/branches/view_support/t/54taint.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/54taint.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/54taint.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -13,11 +13,11 @@
: ( tests => 2 );
}
-package DBICTest::Schema;
+package DBICTest::Plain;
-# Use the default test class namespace to avoid the need for a
+# Use the Plain test class namespace to avoid the need for a
# new test infrastructure. If invalid classes will be introduced to
-# 't/lib/DBICTest/Schema/' someday, this has to be reworked.
+# 't/lib/DBICTest/Plain/' someday, this has to be reworked.
use lib qw(t/lib);
@@ -28,6 +28,6 @@
eval{ __PACKAGE__->load_classes() };
cmp_ok( $@, 'eq', '',
'Loading classes with Module::Find worked in taint mode' );
-ok( __PACKAGE__->sources(), 'At least on source has been registered' );
+ok( __PACKAGE__->source('Test'), 'The Plain::Test source has been registered' );
1;
Modified: DBIx-Class/0.08/branches/view_support/t/63register_class.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/63register_class.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/63register_class.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -1,17 +1,25 @@
use strict;
use warnings;
-use Test::More tests => 2;
+use Test::More tests => 3;
use lib qw(t/lib);
use DBICTest;
use DBICTest::Schema;
use DBICTest::Schema::Artist;
DBICTest::Schema::Artist->source_name('MyArtist');
-DBICTest::Schema->register_class('FooA', 'DBICTest::Schema::Artist');
+{
+ my $w;
+ local $SIG{__WARN__} = sub { $w = shift };
+ DBICTest::Schema->register_class('FooA', 'DBICTest::Schema::Artist');
+ like ($w, qr/use register_extra_source/, 'Complain about using register_class on an already-registered class');
+}
my $schema = DBICTest->init_schema();
my $a = $schema->resultset('FooA')->search;
is($a->count, 3, 'have 3 artists');
is($schema->class('FooA'), 'DBICTest::FooA', 'Correct artist class');
+
+# clean up
+DBICTest::Schema->_unregister_source('FooA');
Modified: DBIx-Class/0.08/branches/view_support/t/64db.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/64db.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/64db.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -39,9 +39,9 @@
# I know this is gross but SQLite reports the size differently from release
# to release. At least this way the test still passes.
-delete $type_info->{artistid}{size};
-delete $type_info->{name}{size};
+delete $type_info->{$_}{size} for keys %$type_info;
+
my $test_type_info = {
'artistid' => {
'data_type' => 'INTEGER',
@@ -51,6 +51,10 @@
'data_type' => 'varchar',
'is_nullable' => 0,
},
+ 'rank' => {
+ 'data_type' => 'integer',
+ 'is_nullable' => 0,
+ },
};
is_deeply($type_info, $test_type_info, 'columns_info_for - column data types');
Modified: DBIx-Class/0.08/branches/view_support/t/71mysql.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/71mysql.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/71mysql.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -21,7 +21,7 @@
$dbh->do("DROP TABLE IF EXISTS artist;");
-$dbh->do("CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), charfield CHAR(10));");
+$dbh->do("CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10));");
#'dbi:mysql:host=localhost;database=dbic_test', 'dbic_test', '');
@@ -60,6 +60,12 @@
'size' => 255,
'default_value' => undef,
},
+ 'rank' => {
+ 'data_type' => 'INT',
+ 'is_nullable' => 0,
+ 'size' => 11,
+ 'default_value' => 13,
+ },
'charfield' => {
'data_type' => 'CHAR',
'is_nullable' => 1,
Modified: DBIx-Class/0.08/branches/view_support/t/72pg.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/72pg.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/72pg.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -47,13 +47,16 @@
my $dbh = $schema->storage->dbh;
$schema->source("Artist")->name("testschema.artist");
$schema->source("SequenceTest")->name("testschema.sequence_test");
-$dbh->do("CREATE SCHEMA testschema;");
-$dbh->do("CREATE TABLE testschema.artist (artistid serial PRIMARY KEY, name VARCHAR(100), charfield CHAR(10));");
-$dbh->do("CREATE TABLE testschema.sequence_test (pkid1 integer, pkid2 integer, nonpkid integer, name VARCHAR(100), CONSTRAINT pk PRIMARY KEY(pkid1, pkid2));");
-$dbh->do("CREATE SEQUENCE pkid1_seq START 1 MAXVALUE 999999 MINVALUE 0");
-$dbh->do("CREATE SEQUENCE pkid2_seq START 10 MAXVALUE 999999 MINVALUE 0");
-$dbh->do("CREATE SEQUENCE nonpkid_seq START 20 MAXVALUE 999999 MINVALUE 0");
-ok ( $dbh->do('CREATE TABLE testschema.casecheck (id serial PRIMARY KEY, "name" VARCHAR(1), "NAME" VARCHAR(2), "UC_NAME" VARCHAR(3));'), 'Creation of casecheck table');
+{
+ local $SIG{__WARN__} = sub {};
+ $dbh->do("CREATE SCHEMA testschema;");
+ $dbh->do("CREATE TABLE testschema.artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10));");
+ $dbh->do("CREATE TABLE testschema.sequence_test (pkid1 integer, pkid2 integer, nonpkid integer, name VARCHAR(100), CONSTRAINT pk PRIMARY KEY(pkid1, pkid2));");
+ $dbh->do("CREATE SEQUENCE pkid1_seq START 1 MAXVALUE 999999 MINVALUE 0");
+ $dbh->do("CREATE SEQUENCE pkid2_seq START 10 MAXVALUE 999999 MINVALUE 0");
+ $dbh->do("CREATE SEQUENCE nonpkid_seq START 20 MAXVALUE 999999 MINVALUE 0");
+ ok ( $dbh->do('CREATE TABLE testschema.casecheck (id serial PRIMARY KEY, "name" VARCHAR(1), "NAME" VARCHAR(2), "UC_NAME" VARCHAR(3));'), 'Creation of casecheck table');
+}
# This is in Core now, but it's here just to test that it doesn't break
$schema->class('Artist')->load_components('PK::Auto');
@@ -78,6 +81,13 @@
'size' => 100,
'default_value' => undef,
},
+ 'rank' => {
+ 'data_type' => 'integer',
+ 'is_nullable' => 0,
+ 'size' => 4,
+ 'default_value' => 13,
+
+ },
'charfield' => {
'data_type' => 'character',
'is_nullable' => 1,
Modified: DBIx-Class/0.08/branches/view_support/t/746mssql.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/746mssql.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/746mssql.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -25,6 +25,7 @@
CREATE TABLE artist (
artistid INT IDENTITY NOT NULL,
name VARCHAR(255),
+ rank INT NOT NULL DEFAULT '13',
charfield CHAR(10) NULL,
primary key(artistid)
)
Modified: DBIx-Class/0.08/branches/view_support/t/74mssql.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/74mssql.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/74mssql.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -29,7 +29,7 @@
$dbh->do("IF OBJECT_ID('cd', 'U') IS NOT NULL
DROP TABLE cd");
-$dbh->do("CREATE TABLE artist (artistid INT IDENTITY PRIMARY KEY, name VARCHAR(255));");
+$dbh->do("CREATE TABLE artist (artistid INT IDENTITY PRIMARY KEY, name VARCHAR(255), rank INT DEFAULT '13');");
$dbh->do("CREATE TABLE cd (cdid INT IDENTITY PRIMARY KEY, artist INT, title VARCHAR(100), year VARCHAR(100), genreid INT NULL);");
# Just to test compat shim, Auto is in Core
$schema->class('Artist')->load_components('PK::Auto::MSSQL');
Modified: DBIx-Class/0.08/branches/view_support/t/77prefetch.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/77prefetch.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/77prefetch.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -344,10 +344,10 @@
is($queries, 0, 'chained search_related after has_many->has_many prefetch ran no queries');
-# once the following TODO is complete, remove the 2 stop-gap tests immediately after the TODO block
-# (the TODO block itself contains tests ensuring that the stop-gaps are removed)
+# once the following TODO is complete, remove the 2 warning tests immediately after the TODO block
+# (the TODO block itself contains tests ensuring that the warns are removed)
TODO: {
- local $TODO = 'Prefetch of multiple has_many rels at the same level (currently must die to protect the clueless git)';
+ local $TODO = 'Prefetch of multiple has_many rels at the same level (currently warn to protect the clueless git)';
use DBIx::Class::ResultClass::HashRefInflator;
#( 1 -> M + M )
@@ -364,26 +364,24 @@
$queries = 0;
$schema->storage->debugcb(sub { $queries++ });
$schema->storage->debug(1);
- eval {
+
+ my $o_mm_warn;
+ {
+ local $SIG{__WARN__} = sub { $o_mm_warn = shift };
$pr_tracks_rs = $pr_cd_rs->first->tracks;
- $pr_tracks_count = $pr_tracks_rs->count;
};
+ $pr_tracks_count = $pr_tracks_rs->count;
- my $o_mm_exc = $@;
- ok(! $o_mm_exc, 'exception on attempt to prefetch several same level has_many\'s (1 -> M + M)');
+ ok(! $o_mm_warn, 'no warning on attempt to prefetch several same level has_many\'s (1 -> M + M)');
- SKIP: {
- skip "1 -> M + M prefetch died", 3 if $o_mm_exc;
-
- is($queries, 1, 'prefetch one->(has_many,has_many) ran exactly 1 query');
- is($pr_tracks_count, $tracks_count, 'equal count of prefetched relations over several same level has_many\'s (1 -> M + M)');
+ is($queries, 1, 'prefetch one->(has_many,has_many) ran exactly 1 query');
+ is($pr_tracks_count, $tracks_count, 'equal count of prefetched relations over several same level has_many\'s (1 -> M + M)');
- for ($pr_tracks_rs, $tracks_rs) {
- $_->result_class ('DBIx::Class::ResultClass::HashRefInflator');
- }
+ for ($pr_tracks_rs, $tracks_rs) {
+ $_->result_class ('DBIx::Class::ResultClass::HashRefInflator');
+ }
- is_deeply ([$pr_tracks_rs->all], [$tracks_rs->all], 'same structure returned with and without prefetch over several same level has_many\'s (1 -> M + M)');
- };
+ is_deeply ([$pr_tracks_rs->all], [$tracks_rs->all], 'same structure returned with and without prefetch over several same level has_many\'s (1 -> M + M)');
#( M -> 1 -> M + M )
my $note_rs = $schema->resultset('LinerNotes')->search ({ notes => 'Buy Whiskey!' });
@@ -401,30 +399,36 @@
$queries = 0;
$schema->storage->debugcb(sub { $queries++ });
$schema->storage->debug(1);
- eval {
+
+ my $m_o_mm_warn;
+ {
+ local $SIG{__WARN__} = sub { $m_o_mm_warn = shift };
$pr_tags_rs = $pr_note_rs->first->cd->tags;
- $pr_tags_count = $pr_tags_rs->count;
};
+ $pr_tags_count = $pr_tags_rs->count;
- my $m_o_mm_exc = $@;
- ok(! $m_o_mm_exc, 'exception on attempt to prefetch several same level has_many\'s (M -> 1 -> M + M)');
+ ok(! $m_o_mm_warn, 'no warning on attempt to prefetch several same level has_many\'s (M -> 1 -> M + M)');
- SKIP: {
- skip "M -> 1 -> M + M prefetch died", 3 if $m_o_mm_exc;
-
- is($queries, 1, 'prefetch one->(has_many,has_many) ran exactly 1 query');
+ is($queries, 1, 'prefetch one->(has_many,has_many) ran exactly 1 query');
- is($pr_tags_count, $tags_count, 'equal count of prefetched relations over several same level has_many\'s (M -> 1 -> M + M)');
+ is($pr_tags_count, $tags_count, 'equal count of prefetched relations over several same level has_many\'s (M -> 1 -> M + M)');
- for ($pr_tags_rs, $tags_rs) {
- $_->result_class ('DBIx::Class::ResultClass::HashRefInflator');
- }
+ for ($pr_tags_rs, $tags_rs) {
+ $_->result_class ('DBIx::Class::ResultClass::HashRefInflator');
+ }
- is_deeply ([$pr_tags_rs->all], [$tags_rs->all], 'same structure returned with and without prefetch over several same level has_many\'s (M -> 1 -> M + M)');
- };
+ is_deeply ([$pr_tags_rs->all], [$tags_rs->all], 'same structure returned with and without prefetch over several same level has_many\'s (M -> 1 -> M + M)');
};
-eval { my $track = $schema->resultset('CD')->search ({ 'me.title' => 'Forkful of bees' }, { prefetch => [qw/tracks tags/] })->first->tracks->first };
-ok ($@, 'exception on attempt to prefetch several same level has_many\'s (1 -> M + M)');
-eval { my $tag = $schema->resultset('LinerNotes')->search ({ notes => 'Buy Whiskey!' }, { prefetch => { cd => [qw/tags tracks/] } })->first->cd->tags->first };
-ok ($@, 'exception on attempt to prefetch several same level has_many\'s (M -> 1 -> M + M)');
+# remove this closure once the TODO above is working
+my $w;
+{
+ local $SIG{__WARN__} = sub { $w = shift };
+
+ my $track = $schema->resultset('CD')->search ({ 'me.title' => 'Forkful of bees' }, { prefetch => [qw/tracks tags/] })->first->tracks->first;
+ like ($w, qr/will currently disrupt both the functionality of .rs->count\(\), and the amount of objects retrievable via .rs->next\(\)/,
+ 'warning on attempt to prefetch several same level has_many\'s (1 -> M + M)');
+ my $tag = $schema->resultset('LinerNotes')->search ({ notes => 'Buy Whiskey!' }, { prefetch => { cd => [qw/tags tracks/] } })->first->cd->tags->first;
+ like ($w, qr/will currently disrupt both the functionality of .rs->count\(\), and the amount of objects retrievable via .rs->next\(\)/,
+ 'warning on attempt to prefetch several same level has_many\'s (M -> 1 -> M + M)');
+}
Modified: DBIx-Class/0.08/branches/view_support/t/81transactions.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/81transactions.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/81transactions.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -8,7 +8,7 @@
my $schema = DBICTest->init_schema();
-plan tests => 63;
+plan tests => 64;
my $code = sub {
my ($artist, @cd_titles) = @_;
@@ -235,7 +235,11 @@
$schema2->txn_begin();
};
my $err = $@;
- ok(($err eq ''), 'Pre-connection nested transactions.');
+ ok(! $err, 'Pre-connection nested transactions.');
+
+ # although not connected DBI would still warn about rolling back at disconnect
+ $schema2->txn_rollback;
+ $schema2->txn_rollback;
$schema2->storage->disconnect;
}
$schema->storage->disconnect;
@@ -268,12 +272,17 @@
ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
+ eval {
+ my $w;
+ local $SIG{__WARN__} = sub { $w = shift };
- eval {
- # The 0 arg says done die, just let the scope guard go out of scope
+ # The 0 arg says don't die, just let the scope guard go out of scope
# forcing a txn_rollback to happen
outer($schema, 0);
+
+ like ($w, qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or an error/, 'Out of scope warning detected');
};
+
local $TODO = "Work out how this should work";
is($@, "Not sure what we want here, but something", "Rollback okay");
Modified: DBIx-Class/0.08/branches/view_support/t/93nobindvars.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/93nobindvars.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/93nobindvars.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -40,7 +40,7 @@
$dbh->do("DROP TABLE IF EXISTS artist;");
-$dbh->do("CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), charfield CHAR(10));");
+$dbh->do("CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10));");
$schema->class('Artist')->load_components('PK::Auto');
Modified: DBIx-Class/0.08/branches/view_support/t/93storage_replication.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/93storage_replication.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/93storage_replication.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -59,8 +59,11 @@
## Get the Schema and set the replication storage type
sub init_schema {
+ # current SQLT SQLite producer does not handle DROP TABLE IF EXISTS, trap warnings here
+ local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /no such table.+DROP TABLE/ };
+
my $class = shift @_;
-
+
my $schema = DBICTest->init_schema(
sqlite_use_file => 1,
storage_type=>{
Modified: DBIx-Class/0.08/branches/view_support/t/94versioning.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/94versioning.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/94versioning.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -4,6 +4,7 @@
use Test::More;
use File::Spec;
use File::Copy;
+use Time::HiRes qw/time sleep/;
#warn "$dsn $user $pass";
my ($dsn, $user, $pass);
@@ -18,12 +19,19 @@
eval "use DBD::mysql; use SQL::Translator 0.09;";
plan $@
? ( skip_all => 'needs DBD::mysql and SQL::Translator 0.09 for testing' )
- : ( tests => 17 );
+ : ( tests => 22 );
}
my $version_table_name = 'dbix_class_schema_versions';
my $old_table_name = 'SchemaVersions';
+my $ddl_dir = File::Spec->catdir ('t', 'var');
+my $fn = {
+ v1 => File::Spec->catfile($ddl_dir, 'DBICVersion-Schema-1.0-MySQL.sql'),
+ v2 => File::Spec->catfile($ddl_dir, 'DBICVersion-Schema-2.0-MySQL.sql'),
+ trans => File::Spec->catfile($ddl_dir, 'DBICVersion-Schema-1.0-2.0-MySQL.sql'),
+};
+
use lib qw(t/lib);
use_ok('DBICVersionOrig');
@@ -31,27 +39,40 @@
eval { $schema_orig->storage->dbh->do('drop table ' . $version_table_name) };
eval { $schema_orig->storage->dbh->do('drop table ' . $old_table_name) };
-is($schema_orig->ddl_filename('MySQL', '1.0', 't/var'), File::Spec->catfile('t', 'var', 'DBICVersion-Schema-1.0-MySQL.sql'), 'Filename creation working');
-unlink('t/var/DBICVersion-Schema-1.0-MySQL.sql') if (-e 't/var/DBICVersion-Schema-1.0-MySQL.sql');
-$schema_orig->create_ddl_dir('MySQL', undef, 't/var');
+is($schema_orig->ddl_filename('MySQL', '1.0', $ddl_dir), $fn->{v1}, 'Filename creation working');
+unlink( $fn->{v1} ) if ( -e $fn->{v1} );
+$schema_orig->create_ddl_dir('MySQL', undef, $ddl_dir);
-ok(-f 't/var/DBICVersion-Schema-1.0-MySQL.sql', 'Created DDL file');
+ok(-f $fn->{v1}, 'Created DDL file');
$schema_orig->deploy({ add_drop_table => 1 });
my $tvrs = $schema_orig->{vschema}->resultset('Table');
is($schema_orig->_source_exists($tvrs), 1, 'Created schema from DDL file');
+# loading a new module defining a new version of the same table
+DBICVersion::Schema->_unregister_source ('Table');
eval "use DBICVersionNew";
+
+my $schema_upgrade = DBICVersion::Schema->connect($dsn, $user, $pass, { ignore_version => 1 });
{
- unlink('t/var/DBICVersion-Schema-2.0-MySQL.sql');
- unlink('t/var/DBICVersion-Schema-1.0-2.0-MySQL.sql');
+ unlink($fn->{v2});
+ unlink($fn->{trans});
- my $schema_upgrade = DBICVersion::Schema->connect($dsn, $user, $pass, { ignore_version => 1 });
is($schema_upgrade->get_db_version(), '1.0', 'get_db_version ok');
is($schema_upgrade->schema_version, '2.0', 'schema version ok');
- $schema_upgrade->create_ddl_dir('MySQL', '2.0', 't/var', '1.0');
- ok(-f 't/var/DBICVersion-Schema-1.0-2.0-MySQL.sql', 'Created DDL file');
- $schema_upgrade->upgrade();
+ $schema_upgrade->create_ddl_dir('MySQL', '2.0', $ddl_dir, '1.0');
+ ok(-f $fn->{trans}, 'Created DDL file');
+
+ {
+ my $w;
+ local $SIG{__WARN__} = sub { $w = shift };
+
+ sleep 1; # remove this when TODO below is completed
+
+ $schema_upgrade->upgrade();
+ like ($w, qr/Attempting upgrade\.$/, 'Warn before upgrade');
+ }
+
is($schema_upgrade->get_db_version(), '2.0', 'db version number upgraded');
eval {
@@ -59,8 +80,14 @@
};
is($@, '', 'new column created');
- # should overwrite files
- $schema_upgrade->create_ddl_dir('MySQL', '2.0', 't/var', '1.0');
+ # should overwrite files and warn about it
+ my @w;
+ local $SIG{__WARN__} = sub { push @w, shift };
+ $schema_upgrade->create_ddl_dir('MySQL', '2.0', $ddl_dir, '1.0');
+
+ is (2, @w, 'A warning generated for both the DDL and the diff');
+ like ($w[0], qr/^Overwriting existing DDL file - $fn->{v2}/, 'New version DDL overwrite warning');
+ like ($w[1], qr/^Overwriting existing diff file - $fn->{trans}/, 'Upgrade diff overwrite warning');
}
{
@@ -106,7 +133,7 @@
is($warn, '', 'warning not detected with attr set');
# should not warn
- $ENV{DBIC_NO_VERSION_CHECK} = 1;
+ local $ENV{DBIC_NO_VERSION_CHECK} = 1;
$warn = '';
$schema_version = DBICVersion::Schema->connect($dsn, $user, $pass);
is($warn, '', 'warning not detected with env var set');
@@ -117,3 +144,32 @@
like($warn, qr/Your DB is currently unversioned/, 'warning detected without env var or attr');
# should warn
}
+
+# attempt a deploy/upgrade cycle within one second
+TODO: {
+
+ local $TODO = 'To fix this properly the table must be extended with an autoinc column, mst will not accept anything less';
+
+ eval { $schema_orig->storage->dbh->do('drop table ' . $version_table_name) };
+ eval { $schema_orig->storage->dbh->do('drop table ' . $old_table_name) };
+ eval { $schema_orig->storage->dbh->do('drop table TestVersion') };
+
+ # this attempts to sleep until the turn of the second
+ my $t = time();
+ sleep (int ($t) + 1 - $t);
+ diag ('Fast deploy/upgrade start: ', time() );
+
+ {
+ local $DBICVersion::Schema::VERSION = '1.0';
+ $schema_orig->deploy;
+ }
+
+ local $SIG{__WARN__} = sub { warn if $_[0] !~ /Attempting upgrade\.$/ };
+ $schema_upgrade->upgrade();
+
+ is($schema_upgrade->get_db_version(), '2.0', 'Fast deploy/upgrade');
+};
+
+unless ($ENV{DBICTEST_KEEP_VERSIONING_DDL}) {
+ unlink $_ for (values %$fn);
+}
Modified: DBIx-Class/0.08/branches/view_support/t/96multi_create.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/96multi_create.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/96multi_create.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -217,3 +217,21 @@
$t->insert;
};
like($@, qr/cd.artist may not be NULL/, "Exception propogated properly");
+
+# Test multi create over many_to_many
+eval {
+ $schema->resultset('CD')->create ({
+ artist => $new_artist,
+ title => 'Warble Marble',
+ year => '2009',
+ cd_to_producer => [
+ { producer => { name => 'Cowboy Neal' } },
+ ],
+ });
+
+ my $m2m_cd = $schema->resultset('CD')->search ({ title => 'Warble Marble'});
+ is ($m2m_cd->count, 1, 'One CD object created via M2M create');
+ is ($m2m_cd->first->producers->count, 1, 'CD object created with one producer');
+ is ($m2m_cd->first->producers->first->name, 'Cowboy Neal', 'Correct producer object created');
+};
+ok (! $@, 'No exceptions on m2m create');
Modified: DBIx-Class/0.08/branches/view_support/t/98savepoints.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/98savepoints.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/98savepoints.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -11,11 +11,11 @@
if (exists $ENV{DBICTEST_PG_DSN}) {
($dsn, $user, $pass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/};
- $create_sql = "CREATE TABLE artist (artistid serial PRIMARY KEY, name VARCHAR(100), charfield CHAR(10))";
+ $create_sql = "CREATE TABLE artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10))";
} elsif (exists $ENV{DBICTEST_MYSQL_DSN}) {
($dsn, $user, $pass) = @ENV{map { "DBICTEST_MYSQL_${_}" } qw/DSN USER PASS/};
- $create_sql = "CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), charfield CHAR(10)) ENGINE=InnoDB";
+ $create_sql = "CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10)) ENGINE=InnoDB";
} else {
plan skip_all => 'Set DBICTEST_(PG|MYSQL)_DSN _USER and _PASS if you want to run savepoint tests';
}
@@ -30,7 +30,11 @@
$schema->storage->debug(1);
-$schema->storage->dbh->do ($create_sql);
+{
+ local $SIG{__WARN__} = sub {};
+ $schema->storage->dbh->do ('DROP TABLE IF EXISTS artist');
+ $schema->storage->dbh->do ($create_sql);
+}
$schema->resultset('Artist')->create({ name => 'foo' });
Modified: DBIx-Class/0.08/branches/view_support/t/bindtype_columns.t
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/bindtype_columns.t 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/bindtype_columns.t 2008-10-23 13:37:14 UTC (rev 4955)
@@ -16,17 +16,20 @@
my $dbh = $schema->storage->dbh;
-$dbh->do(qq[
+{
+ local $SIG{__WARN__} = sub {};
+ $dbh->do('DROP TABLE IF EXISTS artist');
+ $dbh->do(qq[
+ CREATE TABLE artist
+ (
+ artistid serial NOT NULL PRIMARY KEY,
+ media bytea NOT NULL,
+ name varchar NULL,
+ rank integer NOT NULL DEFAULT '13'
+ );
+ ],{ RaiseError => 1, PrintError => 1 });
+}
- CREATE TABLE artist
- (
- artistid serial NOT NULL PRIMARY KEY,
- media bytea NOT NULL,
- name varchar NULL
- );
-],{ RaiseError => 1, PrintError => 1 });
-
-
$schema->class('Artist')->load_components(qw/
PK::Auto
Modified: DBIx-Class/0.08/branches/view_support/t/examples/Schema/testdb.pl
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/examples/Schema/testdb.pl 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/examples/Schema/testdb.pl 2008-10-23 13:37:14 UTC (rev 4955)
@@ -26,7 +26,6 @@
},
{
join => [qw/ cd /],
- prefetch => [qw/ cd /]
}
);
while (my $track = $rs->next) {
@@ -79,7 +78,6 @@
},
{
join => [qw/ artist /],
- prefetch => [qw/ artist /]
}
);
while (my $cd = $rs->next) {
Modified: DBIx-Class/0.08/branches/view_support/t/lib/DBICTest/Schema/Artist.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/lib/DBICTest/Schema/Artist.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/lib/DBICTest/Schema/Artist.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -19,6 +19,10 @@
size => 100,
is_nullable => 1,
},
+ rank => {
+ data_type => 'integer',
+ default_value => 13,
+ },
);
__PACKAGE__->set_primary_key('artistid');
Modified: DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/lib/DBICTest.pm 2008-10-23 13:37:14 UTC (rev 4955)
@@ -132,7 +132,11 @@
my $sql;
{ local $/ = undef; $sql = <IN>; }
close IN;
- ($schema->storage->dbh->do($_) || print "Error on SQL: $_\n") for split(/;\n/, $sql);
+ for my $chunk ( split (/;\s*\n+/, $sql) ) {
+ if ( $chunk =~ / ^ (?! --\s* ) \S /xm ) { # there is some real sql in the chunk - a non-space at the start of the string which is not a comment
+ $schema->storage->dbh->do($chunk) or print "Error on SQL: $chunk\n";
+ }
+ }
}
return;
}
Modified: DBIx-Class/0.08/branches/view_support/t/lib/sqlite.sql
===================================================================
--- DBIx-Class/0.08/branches/view_support/t/lib/sqlite.sql 2008-10-22 22:09:49 UTC (rev 4954)
+++ DBIx-Class/0.08/branches/view_support/t/lib/sqlite.sql 2008-10-23 13:37:14 UTC (rev 4955)
@@ -1,88 +1,53 @@
--
-- Created by SQL::Translator::Producer::SQLite
--- Created on Tue Aug 8 01:53:20 2006
+-- Created on Thu Oct 9 13:44:56 2008
--
BEGIN TRANSACTION;
---
--- Table: employee
---
-CREATE TABLE employee (
- employee_id INTEGER PRIMARY KEY NOT NULL,
- position integer NOT NULL,
- group_id integer,
- group_id_2 integer,
- name varchar(100)
-);
--
--- Table: serialized
---
-CREATE TABLE serialized (
- id INTEGER PRIMARY KEY NOT NULL,
- serialized text NOT NULL
-);
-
---
--- Table: liner_notes
---
-CREATE TABLE liner_notes (
- liner_id INTEGER PRIMARY KEY NOT NULL,
- notes varchar(100) NOT NULL
-);
-
---
--- Table: cd_to_producer
---
-CREATE TABLE cd_to_producer (
- cd integer NOT NULL,
- producer integer NOT NULL,
- PRIMARY KEY (cd, producer)
-);
-
---
-- Table: artist
--
CREATE TABLE artist (
artistid INTEGER PRIMARY KEY NOT NULL,
- name varchar(100)
+ name varchar(100),
+ rank integer NOT NULL DEFAULT '13'
);
+
--
--- Table: twokeytreelike
+-- Table: artist_undirected_map
--
-CREATE TABLE twokeytreelike (
+CREATE TABLE artist_undirected_map (
id1 integer NOT NULL,
id2 integer NOT NULL,
- parent1 integer NOT NULL,
- parent2 integer NOT NULL,
- name varchar(100) NOT NULL,
PRIMARY KEY (id1, id2)
);
+CREATE INDEX artist_undirected_map_idx_id1_ ON artist_undirected_map (id1);
+CREATE INDEX artist_undirected_map_idx_id2_ ON artist_undirected_map (id2);
+
--
--- Table: fourkeys_to_twokeys
+-- Table: bookmark
--
-CREATE TABLE fourkeys_to_twokeys (
- f_foo integer NOT NULL,
- f_bar integer NOT NULL,
- f_hello integer NOT NULL,
- f_goodbye integer NOT NULL,
- t_artist integer NOT NULL,
- t_cd integer NOT NULL,
- autopilot character NOT NULL,
- PRIMARY KEY (f_foo, f_bar, f_hello, f_goodbye, t_artist, t_cd)
+CREATE TABLE bookmark (
+ id INTEGER PRIMARY KEY NOT NULL,
+ link integer NOT NULL
);
+CREATE INDEX bookmark_idx_link_bookmark ON bookmark (link);
+
--
--- Table: self_ref_alias
+-- Table: books
--
-CREATE TABLE self_ref_alias (
- self_ref integer NOT NULL,
- alias integer NOT NULL,
- PRIMARY KEY (self_ref, alias)
+CREATE TABLE books (
+ id INTEGER PRIMARY KEY NOT NULL,
+ source varchar(100) NOT NULL,
+ owner integer NOT NULL,
+ title varchar(100) NOT NULL
);
+
--
-- Table: cd
--
@@ -94,95 +59,144 @@
genreid integer
);
+CREATE INDEX cd_idx_artist_cd ON cd (artist);
+CREATE INDEX cd_idx_genreid_cd ON cd (genreid);
+CREATE UNIQUE INDEX cd_artist_title_cd ON cd (artist, title);
+
--
--- Table: genre
+-- Table: cd_to_producer
--
-CREATE TABLE genre (
- genreid INTEGER PRIMARY KEY NOT NULL,
- name varchar(100) NOT NULL
+CREATE TABLE cd_to_producer (
+ cd integer NOT NULL,
+ producer integer NOT NULL,
+ PRIMARY KEY (cd, producer)
);
+CREATE INDEX cd_to_producer_idx_cd_cd_to_pr ON cd_to_producer (cd);
+CREATE INDEX cd_to_producer_idx_producer_cd ON cd_to_producer (producer);
+
--
--- Table: bookmark
+-- Table: collection
--
-CREATE TABLE bookmark (
- id INTEGER PRIMARY KEY NOT NULL,
- link integer NOT NULL
+CREATE TABLE collection (
+ collectionid INTEGER PRIMARY KEY NOT NULL,
+ name varchar(100) NOT NULL
);
+
--
--- Table: track
+-- Table: collection_object
--
-CREATE TABLE track (
- trackid INTEGER PRIMARY KEY NOT NULL,
- cd integer NOT NULL,
- position integer NOT NULL,
- title varchar(100) NOT NULL,
- last_updated_on datetime NULL
+CREATE TABLE collection_object (
+ collection integer NOT NULL,
+ object integer NOT NULL,
+ PRIMARY KEY (collection, object)
);
+CREATE INDEX collection_object_idx_collection_collection_obj ON collection_object (collection);
+CREATE INDEX collection_object_idx_object_c ON collection_object (object);
+
--
--- Table: self_ref
+-- Table: employee
--
-CREATE TABLE self_ref (
- id INTEGER PRIMARY KEY NOT NULL,
- name varchar(100) NOT NULL
+CREATE TABLE employee (
+ employee_id INTEGER PRIMARY KEY NOT NULL,
+ position integer NOT NULL,
+ group_id integer,
+ group_id_2 integer,
+ name varchar(100)
);
+
--
--- Table: link
+-- Table: event
--
-CREATE TABLE link (
+CREATE TABLE event (
id INTEGER PRIMARY KEY NOT NULL,
- url varchar(100),
- title varchar(100)
+ starts_at datetime NOT NULL,
+ created_on timestamp NOT NULL
);
+
--
-- Table: file_columns
--
CREATE TABLE file_columns (
id INTEGER PRIMARY KEY NOT NULL,
- file varchar(255)
+ file varchar(255) NOT NULL
);
+
--
--- Table: tags
+-- Table: forceforeign
--
-CREATE TABLE tags (
- tagid INTEGER PRIMARY KEY NOT NULL,
- cd integer NOT NULL,
- tag varchar(100) NOT NULL
+CREATE TABLE forceforeign (
+ artist INTEGER PRIMARY KEY NOT NULL,
+ cd integer NOT NULL
);
+CREATE INDEX forceforeign_idx_artist_forcef ON forceforeign (artist);
+
--
--- Table: treelike
+-- Table: fourkeys
--
-CREATE TABLE treelike (
- id INTEGER PRIMARY KEY NOT NULL,
- parent integer NULL,
- name varchar(100) NOT NULL
+CREATE TABLE fourkeys (
+ foo integer NOT NULL,
+ bar integer NOT NULL,
+ hello integer NOT NULL,
+ goodbye integer NOT NULL,
+ sensors character NOT NULL,
+ PRIMARY KEY (foo, bar, hello, goodbye)
);
+
--
--- Table: event
+-- Table: fourkeys_to_twokeys
--
-CREATE TABLE event (
- id INTEGER PRIMARY KEY NOT NULL,
- starts_at datetime NOT NULL,
- created_on timestamp NOT NULL
+CREATE TABLE fourkeys_to_twokeys (
+ f_foo integer NOT NULL,
+ f_bar integer NOT NULL,
+ f_hello integer NOT NULL,
+ f_goodbye integer NOT NULL,
+ t_artist integer NOT NULL,
+ t_cd integer NOT NULL,
+ autopilot character NOT NULL,
+ PRIMARY KEY (f_foo, f_bar, f_hello, f_goodbye, t_artist, t_cd)
);
+CREATE INDEX fourkeys_to_twokeys_idx_f_foo_f_bar_f_hello_f_goodbye_ ON fourkeys_to_twokeys (f_foo, f_bar, f_hello, f_goodbye);
+CREATE INDEX fourkeys_to_twokeys_idx_t_artist_t_cd_fourkeys_to ON fourkeys_to_twokeys (t_artist, t_cd);
+
--
--- Table: twokeys
+-- Table: genre
--
-CREATE TABLE twokeys (
- artist integer NOT NULL,
- cd integer NOT NULL,
- PRIMARY KEY (artist, cd)
+CREATE TABLE genre (
+ genreid NOT NULL,
+ name NOT NULL,
+ PRIMARY KEY (genreid)
);
+
--
+-- Table: liner_notes
+--
+CREATE TABLE liner_notes (
+ liner_id INTEGER PRIMARY KEY NOT NULL,
+ notes varchar(100) NOT NULL
+);
+
+
+--
+-- Table: link
+--
+CREATE TABLE link (
+ id INTEGER PRIMARY KEY NOT NULL,
+ url varchar(100),
+ title varchar(100)
+);
+
+
+--
-- Table: noprimarykey
--
CREATE TABLE noprimarykey (
@@ -191,27 +205,27 @@
baz integer NOT NULL
);
+CREATE UNIQUE INDEX foo_bar_noprimarykey ON noprimarykey (foo, bar);
+
--
--- Table: fourkeys
+-- Table: onekey
--
-CREATE TABLE fourkeys (
- foo integer NOT NULL,
- bar integer NOT NULL,
- hello integer NOT NULL,
- goodbye integer NOT NULL,
- sensors character NOT NULL,
- PRIMARY KEY (foo, bar, hello, goodbye)
+CREATE TABLE onekey (
+ id INTEGER PRIMARY KEY NOT NULL,
+ artist integer NOT NULL,
+ cd integer NOT NULL
);
+
--
--- Table: artist_undirected_map
+-- Table: owners
--
-CREATE TABLE artist_undirected_map (
- id1 integer NOT NULL,
- id2 integer NOT NULL,
- PRIMARY KEY (id1, id2)
+CREATE TABLE owners (
+ ownerid INTEGER PRIMARY KEY NOT NULL,
+ name varchar(100) NOT NULL
);
+
--
-- Table: producer
--
@@ -220,63 +234,121 @@
name varchar(100) NOT NULL
);
+CREATE UNIQUE INDEX prod_name_producer ON producer (name);
+
--
--- Table: onekey
+-- Table: self_ref
--
-CREATE TABLE onekey (
+CREATE TABLE self_ref (
id INTEGER PRIMARY KEY NOT NULL,
- artist integer NOT NULL,
- cd integer NOT NULL
+ name varchar(100) NOT NULL
);
+
--
--- Table: typed_object
+-- Table: self_ref_alias
--
-CREATE TABLE typed_object (
- objectid INTEGER PRIMARY KEY NOT NULL,
- type VARCHAR(100) NOT NULL,
- value VARCHAR(100)
+CREATE TABLE self_ref_alias (
+ self_ref integer NOT NULL,
+ alias integer NOT NULL,
+ PRIMARY KEY (self_ref, alias)
);
+CREATE INDEX self_ref_alias_idx_alias_self_ ON self_ref_alias (alias);
+CREATE INDEX self_ref_alias_idx_self_ref_se ON self_ref_alias (self_ref);
+
--
--- Table: collection
+-- Table: sequence_test
--
-CREATE TABLE collection (
- collectionid INTEGER PRIMARY KEY NOT NULL,
- name VARCHAR(100)
+CREATE TABLE sequence_test (
+ pkid1 integer NOT NULL,
+ pkid2 integer NOT NULL,
+ nonpkid integer NOT NULL,
+ name varchar(100),
+ PRIMARY KEY (pkid1, pkid2)
);
+
--
--- Table: collection_object
+-- Table: serialized
--
-CREATE TABLE collection_object (
- collection INTEGER NOT NULL,
- object INTEGER NOT NULL
+CREATE TABLE serialized (
+ id INTEGER PRIMARY KEY NOT NULL,
+ serialized text NOT NULL
);
+
--
--- Table: owners
+-- Table: tags
--
-CREATE TABLE owners (
- ownerid INTEGER PRIMARY KEY NOT NULL,
- name varchar(100)
+CREATE TABLE tags (
+ tagid INTEGER PRIMARY KEY NOT NULL,
+ cd integer NOT NULL,
+ tag varchar(100) NOT NULL
);
+CREATE INDEX tags_idx_cd_tags ON tags (cd);
+
--
--- Table: books
+-- Table: track
--
-CREATE TABLE books (
+CREATE TABLE track (
+ trackid INTEGER PRIMARY KEY NOT NULL,
+ cd integer NOT NULL,
+ position integer NOT NULL,
+ title varchar(100) NOT NULL,
+ last_updated_on datetime
+);
+
+CREATE INDEX track_idx_cd_track ON track (cd);
+CREATE UNIQUE INDEX track_cd_position_track ON track (cd, position);
+CREATE UNIQUE INDEX track_cd_title_track ON track (cd, title);
+
+--
+-- Table: treelike
+--
+CREATE TABLE treelike (
id INTEGER PRIMARY KEY NOT NULL,
- owner INTEGER,
- source varchar(100),
- title varchar(100)
+ parent integer,
+ name varchar(100) NOT NULL
);
+CREATE INDEX treelike_idx_parent_treelike ON treelike (parent);
-CREATE UNIQUE INDEX tktlnameunique_twokeytreelike on twokeytreelike (name);
-CREATE UNIQUE INDEX cd_artist_title_cd on cd (artist, title);
-CREATE UNIQUE INDEX track_cd_position_track on track (cd, position);
-CREATE UNIQUE INDEX track_cd_title_track on track (cd, title);
-CREATE UNIQUE INDEX foo_bar_noprimarykey on noprimarykey (foo, bar);
-CREATE UNIQUE INDEX prod_name_producer on producer (name);
+--
+-- Table: twokeytreelike
+--
+CREATE TABLE twokeytreelike (
+ id1 integer NOT NULL,
+ id2 integer NOT NULL,
+ parent1 integer NOT NULL,
+ parent2 integer NOT NULL,
+ name varchar(100) NOT NULL,
+ PRIMARY KEY (id1, id2)
+);
+
+CREATE INDEX twokeytreelike_idx_parent1_parent2_twokeytre ON twokeytreelike (parent1, parent2);
+CREATE UNIQUE INDEX tktlnameunique_twokeytreelike ON twokeytreelike (name);
+
+--
+-- Table: twokeys
+--
+CREATE TABLE twokeys (
+ artist integer NOT NULL,
+ cd integer NOT NULL,
+ PRIMARY KEY (artist, cd)
+);
+
+CREATE INDEX twokeys_idx_artist_twokeys ON twokeys (artist);
+
+--
+-- Table: typed_object
+--
+CREATE TABLE typed_object (
+ objectid INTEGER PRIMARY KEY NOT NULL,
+ type varchar(100) NOT NULL,
+ value varchar(100) NOT NULL
+);
+
+
COMMIT;
More information about the Bast-commits
mailing list