Skip to content

Commit d7e0e0e

Browse files
committed
Introspect view definitions
Supported on PostgreSQL, MySQL, Oracle, Firebird, and InterBase.
1 parent 5be6067 commit d7e0e0e

File tree

11 files changed

+104
-10
lines changed

11 files changed

+104
-10
lines changed

Changes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
Revision history for Perl extension DBIx::Class::Schema::Loader
22

3+
- Introspect view definitions for PostgreSQL, MySQL, Oracle,
4+
Firebird, and InterBase.
5+
36
0.07045 2016-01-22
47
- Regenerate tarball without author-mode test dependencies
58

lib/DBIx/Class/Schema/Loader/Base.pm

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2570,6 +2570,8 @@ sub _table_is_view {
25702570
return 0;
25712571
}
25722572

2573+
sub _view_definition { undef }
2574+
25732575
# Set up metadata (cols, pks, etc)
25742576
sub _setup_src_meta {
25752577
my ($self, $table) = @_;
@@ -2580,11 +2582,17 @@ sub _setup_src_meta {
25802582
my $table_class = $self->classes->{$table->sql_name};
25812583
my $table_moniker = $self->monikers->{$table->sql_name};
25822584

2585+
# Must come before ->table
25832586
$self->_dbic_stmt($table_class, 'table_class', 'DBIx::Class::ResultSource::View')
2584-
if $self->_table_is_view($table);
2587+
if my $is_view = $self->_table_is_view($table);
25852588

25862589
$self->_dbic_stmt($table_class, 'table', $table->dbic_name);
25872590

2591+
# Must come after ->table
2592+
if ($is_view and my $view_def = $self->_view_definition($table)) {
2593+
$self->_dbic_stmt($table_class, 'result_source_instance->view_definition', $view_def);
2594+
}
2595+
25882596
my $cols = $self->_table_columns($table);
25892597
my $col_info = $self->__columns_info_for($table);
25902598

lib/DBIx/Class/Schema/Loader/DBI/InterBase.pm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,16 @@ EOF
310310
return $result;
311311
}
312312

313+
sub _view_definition {
314+
my ($self, $view) = @_;
315+
316+
return scalar $self->schema->storage->dbh->selectrow_array(<<'EOF', {}, $view->name);
317+
SELECT rdb$view_source
318+
FROM rdb$relations
319+
WHERE rdb$relation_name = ?
320+
EOF
321+
}
322+
313323
=head1 SEE ALSO
314324
315325
L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,

lib/DBIx/Class/Schema/Loader/DBI/Oracle.pm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,16 @@ sub _dbh_column_info {
409409
return $self->next::method(@_);
410410
}
411411

412+
sub _view_definition {
413+
my ($self, $view) = @_;
414+
415+
return scalar $self->schema->storage->dbh->selectrow_array(<<'EOF', {}, $view->schema, $view->name);
416+
SELECT text
417+
FROM all_views
418+
WHERE owner = ? AND view_name = ?
419+
EOF
420+
}
421+
412422
=head1 SEE ALSO
413423
414424
L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,

lib/DBIx/Class/Schema/Loader/DBI/Pg.pm

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,22 @@ EOF
342342
return $result;
343343
}
344344

345+
sub _view_definition {
346+
my ($self, $view) = @_;
347+
348+
my $def = $self->schema->storage->dbh->selectrow_array(<<'EOF', {}, $view->schema, $view->name);
349+
SELECT pg_catalog.pg_get_viewdef(oid)
350+
FROM pg_catalog.pg_class
351+
WHERE relnamespace = (SELECT OID FROM pg_catalog.pg_namespace WHERE nspname = ?)
352+
AND relname = ?
353+
EOF
354+
# The definition is returned as a complete statement including the
355+
# trailing semicolon, but that's not allowed in CREATE VIEW, so
356+
# strip it out
357+
$def =~ s/\s*;\s*\z//;
358+
return $def;
359+
}
360+
345361
=head1 SEE ALSO
346362
347363
L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,

lib/DBIx/Class/Schema/Loader/DBI/mysql.pm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,18 @@ sub _column_comment {
363363
return $comment;
364364
}
365365

366+
sub _view_definition {
367+
my ($self, $view) = @_;
368+
369+
return scalar $self->schema->storage->dbh->selectrow_array(
370+
q{SELECT view_definition
371+
FROM information_schema.views
372+
WHERE table_schema = schema()
373+
AND table_name = ?
374+
}, undef, $view->name,
375+
);
376+
}
377+
366378
=head1 SEE ALSO
367379
368380
L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,

t/10_01sqlite_common.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ my $tester = dbixcsl_common_tests->new(
173173

174174
# test that views are marked as such
175175
isa_ok $schema->resultset($monikers->{extra_loader_test5})->result_source, 'DBIx::Class::ResultSource::View',
176-
'views have table_class set correctly';
176+
'view result source';
177177

178178
isnt $schema->resultset($monikers->{extra_loader_test6})->result_source->column_info('id1')->{is_auto_increment}, 1,
179179
q{two integer PKs don't get marked autoinc};

t/10_02mysql_common.t

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ dbixcsl_common_tests->new(
205205
],
206206
pre_drop_ddl => [ 'DROP VIEW mysql_loader_test2', ],
207207
drop => [ 'mysql_loader-test1', 'mysql_loader_test3', 'mysql_loader_test11', 'mysql_loader_test12' ],
208-
count => 9 + 30 * 2,
208+
count => 10 + 30 * 2, # regular + multi-schema * 2
209209
run => sub {
210210
my ($monikers, $classes);
211211
($schema, $monikers, $classes) = @_;
@@ -219,8 +219,13 @@ dbixcsl_common_tests->new(
219219
'view introspected successfully';
220220

221221
# test that views are marked as such
222-
isa_ok $schema->resultset($monikers->{mysql_loader_test2})->result_source, 'DBIx::Class::ResultSource::View',
223-
'views have table_class set correctly';
222+
my $view_source = $schema->resultset($monikers->{mysql_loader_test2})->result_source;
223+
isa_ok $view_source, 'DBIx::Class::ResultSource::View',
224+
'view result source';
225+
226+
like $view_source->view_definition,
227+
qr/\A \s* select \b .* \b from \s+ `.*?` \. `mysql_loader-test1` \s* \z/imsx,
228+
'view defintion';
224229

225230
$rsrc = $schema->source('MysqlLoaderTest3');
226231

t/10_03pg_common.t

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ dbixcsl_common_tests->new(
294294
'DROP VIEW pg_loader_test11',
295295
],
296296
drop => [ qw/pg_loader_test1 pg_loader_test2 pg_loader_test9 pg_loader_test10 pg_loader_test12/ ],
297-
count => 10 + 30 * 2,
297+
count => 11 + 30 * 2, # regular + multi-schema * 2
298298
run => sub {
299299
my ($schema, $monikers, $classes) = @_;
300300

@@ -490,8 +490,13 @@ dbixcsl_common_tests->new(
490490
}
491491

492492
# test that views are marked as such
493-
isa_ok $schema->resultset($monikers->{pg_loader_test11})->result_source, 'DBIx::Class::ResultSource::View',
494-
'views have table_class set correctly';
493+
my $view_source = $schema->resultset($monikers->{pg_loader_test11})->result_source;
494+
isa_ok $view_source, 'DBIx::Class::ResultSource::View',
495+
'view result source';
496+
497+
like $view_source->view_definition,
498+
qr/\A \s* select\b .* \bfrom \s+ pg_loader_test1 \s* \z/imsx,
499+
'view definition';
495500

496501
is_deeply
497502
{ $schema->source($monikers->{pg_loader_test12})->unique_constraints },

t/10_05ora_common.t

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,13 @@ dbixcsl_common_tests->new(
192192
},
193193
$auto_inc_cb->('oracle_loader_test11', 'id'),
194194
'alter trigger oracle_loader_test11_id_trg disable',
195+
'CREATE VIEW oracle_loader_test12 AS SELECT * FROM oracle_loader_test1',
196+
],
197+
pre_drop_ddl => [
198+
'DROP VIEW oracle_loader_test12',
195199
],
196200
drop => [qw/oracle_loader_test1 oracle_loader_test9 oracle_loader_test10 oracle_loader_test11/],
197-
count => 10 + 31 * 2, # basic + cross-schema * 2
201+
count => 12 + 31 * 2, # basic + cross-schema * 2
198202
run => sub {
199203
my ($monikers, $classes);
200204
($schema, $monikers, $classes) = @_;
@@ -247,6 +251,14 @@ dbixcsl_common_tests->new(
247251
ok !$source11->column_info('id')->{is_auto_increment},
248252
'Disabled autoinc trigger not loaded';
249253

254+
my $view_source = $schema->resultset($monikers->{oracle_loader_test12})->result_source;
255+
isa_ok $view_source, 'DBIx::Class::ResultSource::View',
256+
'view result source';
257+
258+
like $view_source->view_definition,
259+
qr/\A \s* select\b .* \bfrom \s+ oracle_loader_test1 \s* \z/imsx,
260+
'view definition';
261+
250262
SKIP: {
251263
skip 'Set the DBICTEST_ORA_EXTRAUSER_DSN, _USER and _PASS environment variables to run the cross-schema relationship tests', 31 * 2
252264
unless $ENV{DBICTEST_ORA_EXTRAUSER_DSN};

0 commit comments

Comments
 (0)