递归遍历 DBIx::Class 关系

发布于 2024-10-20 13:48:06 字数 413 浏览 1 评论 0原文

获取具有外键依赖关系(直接和间接)到 DBIx::Class 子类 foo 的表的列表的最快方法是什么?我有一个基于 DBIx::Class::Schema 的 MySQL 数据库。可以直接使用 DBIx::Class 吗?或者 SQL::Translator 可以通过生成有向图来提供帮助吗?

给定以下类:

package MySchema::Foo;

...

package MySchema::Bar;

__PACKAGE__->belongs_to('foo', 'MySchema::Foo');

package MySchema::Baz;

__PACKAGE__->belongs_to('bar', 'MySchema::Bar');

对于输入 Foo,输出应为 [ Bar, Baz ]。

Which is the quickest way to get the list of tables that have foreign key dependencies, both direct and indirect, to DBIx::Class subclass foo? I have a MySQL database based on a DBIx::Class::Schema. Can DBIx::Class be used directly, or can SQL::Translator help by generating a digraph?

Given the following classes:

package MySchema::Foo;

...

package MySchema::Bar;

__PACKAGE__->belongs_to('foo', 'MySchema::Foo');

package MySchema::Baz;

__PACKAGE__->belongs_to('bar', 'MySchema::Bar');

For the input Foo, the output should be [ Bar, Baz ].

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独行侠 2024-10-27 13:48:06

使用 DBIx::Class::Schema::ResultSource 来完成此操作。首先构建引用类的哈希(ref),然后遍历它:

#!/usr/bin/perl

use strict;
use warnings;
use MySchema;
use Set::Scalar;

# add_sfk: adds a foreign key reference from $src to $dst
sub add_sfk {
    my ( $sfks, $src, $dst ) = @_;

    $sfks->{$src} ||= Set::Scalar->new;
    $sfks->{$src}->insert($dst);
}

my $conn = MySchema->connect(...);

my $scname = ref $conn;
my $sfks = {}; # the foreign key hash

# now we build the hash from sources relationships
foreach my $sname ($conn->sources) {
    my $s = $conn->source($sname);
    my $cname = $conn->class($sname);
    foreach my $rname ($s->relationships) {
        my $rel = $s->relationship_info($rname);
        my @conds = keys %{ $rel->{cond} };
        next if scalar @conds > 1; # reckon this should never happen
        (my $stgt = $rel->{source}) =~ s/^${scname}:://;
        foreach my $ckey (@conds) {
            add_sfk($sfks, $stgt, $sname) if ('foreign.id' eq $ckey); # belongs_to
            add_sfk($sfks, $sname, $stgt) if ('self.id' eq $rel->{cond}->{$ckey}); # has_(one|many)
        }
    }
}

my $sname = shift or die("No class given as input");

# time to traverse our hash to include indirect relationships
my $deps = $sfks->{$sname};
my $lastdeps = $deps;
my $newdeps;
do {
    $newdeps = Set::Scalar->new;
    foreach my $sn ($lastdeps->elements) {
        my $sdeps = $sfks->{$sn} or next;
        if ($sdeps -= $lastdeps) {
            $newdeps += $sdeps;
        }
    }
    $deps += $lastdeps;
    $lastdeps = $newdeps;
} while ($newdeps);

print "Dependencies of $sname:\n" . join("\n", map { $conn->source($_)->from } @$deps);

Cooked this with DBIx::Class's ::Schema and ::ResultSource. First builds a hash(ref) of referencing classes and then traverses it:

#!/usr/bin/perl

use strict;
use warnings;
use MySchema;
use Set::Scalar;

# add_sfk: adds a foreign key reference from $src to $dst
sub add_sfk {
    my ( $sfks, $src, $dst ) = @_;

    $sfks->{$src} ||= Set::Scalar->new;
    $sfks->{$src}->insert($dst);
}

my $conn = MySchema->connect(...);

my $scname = ref $conn;
my $sfks = {}; # the foreign key hash

# now we build the hash from sources relationships
foreach my $sname ($conn->sources) {
    my $s = $conn->source($sname);
    my $cname = $conn->class($sname);
    foreach my $rname ($s->relationships) {
        my $rel = $s->relationship_info($rname);
        my @conds = keys %{ $rel->{cond} };
        next if scalar @conds > 1; # reckon this should never happen
        (my $stgt = $rel->{source}) =~ s/^${scname}:://;
        foreach my $ckey (@conds) {
            add_sfk($sfks, $stgt, $sname) if ('foreign.id' eq $ckey); # belongs_to
            add_sfk($sfks, $sname, $stgt) if ('self.id' eq $rel->{cond}->{$ckey}); # has_(one|many)
        }
    }
}

my $sname = shift or die("No class given as input");

# time to traverse our hash to include indirect relationships
my $deps = $sfks->{$sname};
my $lastdeps = $deps;
my $newdeps;
do {
    $newdeps = Set::Scalar->new;
    foreach my $sn ($lastdeps->elements) {
        my $sdeps = $sfks->{$sn} or next;
        if ($sdeps -= $lastdeps) {
            $newdeps += $sdeps;
        }
    }
    $deps += $lastdeps;
    $lastdeps = $newdeps;
} while ($newdeps);

print "Dependencies of $sname:\n" . join("\n", map { $conn->source($_)->from } @$deps);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文