FC2ブログ
2011
01.13

Unable to uniquely identify row object with missing PK columns

Category: perl
いつものDBIx。

undef error - Unable to uniquely identify row object with missing PK columns: id at /usr/lib/perl5/site_perl/5.8.8/DBIx/Class/Schema.pm line 1061



そんぼり。

columns を書く場合は、メインになってるテーブルのPKは必ずいれないといけないようです(SQL的にはOKでも)。

今Catalystでやってるので、それっぽく書きますが
# neko テーブルの PK は id と inu_id。
$c->model('DBIC::Neko')->search(
{'hogehoge' => 100},
{columns=>qw[/id name/]}
);

こんな感じだと出るよーです。
$c->model('DBIC::Neko')->search( 
{'hogehoge' => 100},
{columns=>qw[/id name inu_id/]}
);

も入れると多分大丈夫。

後でもちっと調べる。うん。


Comment:0  Trackback:0
2011
01.11

DBIxのwhere句にEXISTSを使いたい

Category: perl
version: 0.08124

例が適当なんでわかりにくかったらすみませぬ。

やりたいのは、EXISTS 使いたいってコトなのだが、
$cond->{-and} = \"EXISTS select * from hogehoge where name like '%ねこ%'";

ってしたら、

DBIx::Class::ResultSet::search(): [SQL::Abstract::__ANON__] Fatal: -and => \$scalar not supported, use -nest


とか言われたので、

$cond->{-nest} = \"EXISTS select * from hogehoge where name like '%ねこ%'";

みたいな感じで、単体なら問題ない。

でも、これ
$cond->{-nest} = \"EXISTS select * from hogehoge where name like '%ねこ%'";
$cond->{-nest} = \"EXISTS select * from mogemoge where name like '%くま%'";

ってすると、片方しか適用されん・・・当たり前ですねすみません。

もしかして、
$cond->{-nest} = \[
\"EXISTS select * from hogehoge where name like '%ねこ%'",
\"EXISTS select * from mogemoge where name like '%くま%'"
];

ってしたら、EXISTS ~ OR EXISTS ~ って感じになってしまった・・・。

最悪
$cond->{"(select count(*) from hogehoge where name like '%ねこ%'"} = {'>' , 0 };

とかして逃げるからいいんだけd(いやいや・・・)

対応してるソースを探す。grep したら説明っぽいのが出てきた。
SQL/Abstract.pm
There is also a special -nest
operator which adds an additional set of parens, to create a subquery.
For example, to get something like this:

$stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )";
@bind = ('nwiger', '20', 'ASIA');

You would do:

my %where = (
user => 'nwiger',
-nest => [ workhrs => {'>', 20}, geo => 'ASIA' ],
);


Finally, clauses in hashrefs or arrayrefs can be
prefixed with an C<-and> or C<-or> to change the logic
inside :

my @where = (
-and => [
user => 'nwiger',
-nest => [
-and => [workhrs => {'>', 20}, geo => 'ASIA' ],
-and => [workhrs => {'<', 50}, geo => 'EURO' ]
],
],
);

That would yield:

WHERE ( user = ? AND
( ( workhrs > ? AND geo = ? )
OR ( workhrs < ? AND geo = ? ) ) )

ふむふむ。
...
In the examples above, the subquery was used as an operator on a column;
but the same principle also applies for a clause within the main C<%where>
hash, like an EXISTS subquery :

my ($sub_stmt, @sub_bind)
= $sql->select("t1", "*", {c1 => 1, c2 => \"> t0.c0"});
my %where = (
foo => 1234,
-nest => \["EXISTS ($sub_stmt)" => @sub_bind],
);

which yields

$stmt = "WHERE (foo = ? AND EXISTS (SELECT * FROM t1
WHERE c1 = ? AND c2 > t0.c0))";
@bind = (1234, 1);

つーことは、
$cond->{-and} = \[
{'-nest' => \"EXISTS select * from hogehoge where name like '%ねこ%'"},
{'-nest' => \"EXISTS select * from mogemoge where name like '%くま%'"}
];

お、AND でつながった!

まとめ
1. EXISTS を使うときは、 -nest を使う。
2. $cond->{'-nest'} = \[\"EXISTS ~",\"EXISTS ~"] な感じで連結させるとデフォルトで OR になるので、
  AND にしたい場合は $cond->{-and} = \[{'-nest' => \"EXISTS ~"},{'-nest' => \"EXISTS ~"}]
  を使う。

まぁよく考えると、うーん、そーですよねーって感じではあるんですg

精進しましょう!




Comment:0  Trackback:0
2010
12.28

TemplateToolkit tips 2つ!

Category: perl   Tags:perltemplate
テンプレートツールキットマニュアルに書いてなさそうなことをメモしておきます。

てか、ふつーにやるだけなら、↑見れば大体いける感じ。

もっと色々変数を使いたい。


ファイルの呼び出し時とか
[% INCLUDE test/${file.name}/hogehoge.tpl %]

アイテムのkeyの部分に変数を使いたい
[% item.${keyname}.id %]

とか、${変数名} でいけます。

FOREACH の loop のあれこれ


さっきちまっと書いてたのが、前と同じ値の場合出力しないってやつだったのだけど、
[% FOREACH n IN nanntoka%]
[% IF loop.prev.id != n.id %]
[% n.id %]
[% END %]
[% END %]

loop.prev は 1つ前のアイテムそのものなので、 loop.prev.key名 のようにつなげて書けば、
結構いい感じで使えちゃいます。
一番初めの場合でも、空を返してるだけに見えます。なので空白をチェックしたい場合は、
loop.first かどうかをチェックしないとだめかもですね・・・。

ってこれしかなかった!

また気づいたら追記しときますん。

TemplateToolkit 楽しいよ TemplateToolkit !!




Comment:0  Trackback:0
2010
12.08

Catalyt + fastcgi

Category: perl
CentOS5.5
perl5.8.8
Catalyst 5.8系

ほんとは、worker MPM worker でと思ったのだけど、

Cache::FastMmap does not support threads sorry at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/Cache/FastMmap.pm line 1203.


というエラーが。
MyApp/Model/DBIC.pm で使ってるので、面倒そうなのであきらめる。

ではfastcgiで。
CentOS5.5では、mod_fastcgi の rpm が提供されていないので、make install。
FastCGIのインストール(CentOS+Apache2) を参考にしつつ。

httpd.conf に

LoadModule fastcgi_module modules/mod_fastcgi.so


を足して、あれこれ調べつつ設定も書いて再起動したら、

(2)No such file or directory: FastCGI: failed to connect to server "/home/noriko/MyApp/script/myapp_fastcgi.pl": connect() failed
FastCGI: incomplete headers (0 bytes) received from server "/home/noriko/MyApp/script/myapp_fastcgi.pl"


というエラーが。

ぐぐったら、

No such file or directory: FastCGI: failed to connect to server
"/var/www/test/htdocs/app.py": connect() failed

FastCGI tried to start the script you gave as a parameter to the FastCgiServer or FastCgiExternalServer directive, but it did probably does not exist, or couldn’t be started correct.


Via:
Apache, FastCGI and Python


と書いてあって、えとアレですね、script/myapp_fastcgi.pl を起動して、そいつにアクセスしに行くのですね・・・。

$ script/myapp_fastcgi.pl -listen :5000

みたいにして起動。
で、apache の設定ファイルは、
<VirtualHost *:80>
FastCgiExternalServer /home/noriko/MyApp/script/myapp_fastcgi.pl -host 127.0.0.1:5000
ServerName hogehoge
DocumentRoot /home/noriko/MyApp/root

RewriteEngine on
RewriteRule ^/(.*) /home/noriko/MyApp/script/myapp_fastcgi.pl/$1 [L]

ScriptAlias / /home/noriko/MyApp/script/myapp_fastcgi.pl

<Files myapp_fastcgi.pl>
SetHandler fastcgi-script
</Files>
</VirtualHost>

と書きました。正しいかはわかりませんが、とりあえず動くと思います・・・!
Comment:0  Trackback:0
2010
12.03

[Catalyst] __PACKAGE__->path_to の値

Category: perl
__PACKAGE__->path_to は __PACKAGE__->config->{'home'} を返します。

基本的には自動で入るので、設定する必要はなくて、
yaml に書いても、yaml 読み込む前に色々使われちゃうので、そっちに書いても意味ないです(←書いてみたらしい)。


たとえば、似たようなプロジェクト使ってて、 lib 以下とか symlink 使いまくりでいいよね
とかしてると、

たとえば、テンプレートのディレクトリを __PACKAGE__->path_to('root','templates') みたいにしてると

myApp/script/../lib/MyApp/../../root/templates



って返ってきて、これって、myApp/script/root/templates じゃないんですよね。 symlink してる方を見に行っちゃう。

ってのに気づかなくて、 ls -i filename とかして調べたら、inode 違うからおかしいな→ symlink か!
と気づきました。

これは困るので、 MyApp.pm の __PACKAGE__ のいっちゃんはじめで

__PACKAGE__->config->{'home'} = 'フルパス'



したらうまく行きました。

Catalyst.pm の sub path_to をほげほげしまくってやっと捕まえた・・・。

つーか、そんな運用するのが間違ってて、Catalyst の問題じゃないよーな気がしますが、
うーんでも、 __PACKAGE__->config->{'home'} は .. を含まない形で返してほしーな。

__PACKAGE__->path_to('root'); すると、

/hogehoge/script/../lib/MyApp



って返ってきます。

まぁでも一応解決できたのでメモ。





Comment:0  Trackback:0
back-to-top